EVERYTHING
This commit is contained in:
@@ -0,0 +1,672 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using BlockSpace.Voxels;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BlockSpace.Worlds
|
||||
{
|
||||
public static class WorldGroupsCodec
|
||||
{
|
||||
[Serializable]
|
||||
public struct WorldGroupRecord
|
||||
{
|
||||
public Vector3Int position;
|
||||
|
||||
public byte packedRotation;
|
||||
|
||||
public Vector3Int size;
|
||||
|
||||
public byte[] voxels;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct NodePortValueRecord
|
||||
{
|
||||
public string portName;
|
||||
|
||||
public BSValue value;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct WorldNodeRecord
|
||||
{
|
||||
public int nodeId;
|
||||
|
||||
public string definitionName;
|
||||
|
||||
public Vector3 position;
|
||||
|
||||
public Quaternion rotation;
|
||||
|
||||
public NodePortValueRecord[] inputValues;
|
||||
|
||||
public NodePortValueRecord[] outputValues;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct WorldWireRecord
|
||||
{
|
||||
public int outputNodeId;
|
||||
|
||||
public string outputPortName;
|
||||
|
||||
public int inputNodeId;
|
||||
|
||||
public string inputPortName;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct WorldSaveData
|
||||
{
|
||||
public List<WorldGroupRecord> groupRecords;
|
||||
|
||||
public List<WorldNodeRecord> nodeRecords;
|
||||
|
||||
public List<WorldWireRecord> wireRecords;
|
||||
}
|
||||
|
||||
private static readonly byte[] Magic = Encoding.ASCII.GetBytes("BSW1");
|
||||
|
||||
private static readonly byte[] NodesSectionMagic = Encoding.ASCII.GetBytes("BSN1");
|
||||
|
||||
private static readonly byte[] WiresSectionMagic = Encoding.ASCII.GetBytes("BSR1");
|
||||
|
||||
private const string GroupRuntimeWirePrefix = "__group_runtime__:";
|
||||
|
||||
private const string GroupSavedWirePrefix = "__group_saved__:";
|
||||
|
||||
public static WorldWireRecord CreateGroupRuntimeWireRecord(int groupId, int inputNodeId, string inputPortName)
|
||||
{
|
||||
return new WorldWireRecord
|
||||
{
|
||||
outputNodeId = 0,
|
||||
outputPortName = "__group_runtime__:" + Mathf.Max(0, groupId),
|
||||
inputNodeId = inputNodeId,
|
||||
inputPortName = inputPortName
|
||||
};
|
||||
}
|
||||
|
||||
public static WorldWireRecord CreateGroupSavedWireRecord(int savedGroupIndex, int inputNodeId, string inputPortName)
|
||||
{
|
||||
return new WorldWireRecord
|
||||
{
|
||||
outputNodeId = 0,
|
||||
outputPortName = "__group_saved__:" + Mathf.Max(0, savedGroupIndex),
|
||||
inputNodeId = inputNodeId,
|
||||
inputPortName = inputPortName
|
||||
};
|
||||
}
|
||||
|
||||
public static bool TryGetGroupRuntimeWireSourceId(WorldWireRecord record, out int groupId)
|
||||
{
|
||||
return TryParseGroupWireValue(record, "__group_runtime__:", out groupId);
|
||||
}
|
||||
|
||||
public static bool TryGetGroupSavedWireIndex(WorldWireRecord record, out int savedGroupIndex)
|
||||
{
|
||||
return TryParseGroupWireValue(record, "__group_saved__:", out savedGroupIndex);
|
||||
}
|
||||
|
||||
public static byte[] EncodeGzip(IEnumerable<VoxelGroup> groups)
|
||||
{
|
||||
return EncodeGzip(groups, null, null);
|
||||
}
|
||||
|
||||
public static byte[] EncodeGzip(IEnumerable<VoxelGroup> groups, IEnumerable<WorldNodeRecord> nodes, IEnumerable<WorldWireRecord> wires)
|
||||
{
|
||||
List<WorldGroupRecord> list = BuildGroupRecords(groups);
|
||||
List<WorldNodeRecord> list2 = ((nodes != null) ? new List<WorldNodeRecord>(nodes) : new List<WorldNodeRecord>());
|
||||
List<WorldWireRecord> list3 = ((wires != null) ? new List<WorldWireRecord>(wires) : new List<WorldWireRecord>());
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
memoryStream.Write(Magic, 0, Magic.Length);
|
||||
WriteVarUInt(memoryStream, (uint)list.Count);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
WriteGroupRecord(memoryStream, list[i]);
|
||||
}
|
||||
if (list2.Count > 0)
|
||||
{
|
||||
memoryStream.Write(NodesSectionMagic, 0, NodesSectionMagic.Length);
|
||||
WriteVarUInt(memoryStream, (uint)list2.Count);
|
||||
for (int j = 0; j < list2.Count; j++)
|
||||
{
|
||||
WriteNodeRecord(memoryStream, list2[j]);
|
||||
}
|
||||
}
|
||||
if (list3.Count > 0)
|
||||
{
|
||||
memoryStream.Write(WiresSectionMagic, 0, WiresSectionMagic.Length);
|
||||
WriteVarUInt(memoryStream, (uint)list3.Count);
|
||||
for (int k = 0; k < list3.Count; k++)
|
||||
{
|
||||
WriteWireRecord(memoryStream, list3[k]);
|
||||
}
|
||||
}
|
||||
memoryStream.Position = 0L;
|
||||
using MemoryStream memoryStream2 = new MemoryStream();
|
||||
using (GZipStream destination = new GZipStream(memoryStream2, System.IO.Compression.CompressionLevel.Optimal, leaveOpen: true))
|
||||
{
|
||||
memoryStream.CopyTo(destination);
|
||||
}
|
||||
return memoryStream2.ToArray();
|
||||
}
|
||||
|
||||
public static bool TryDecodeGzip(byte[] gzipBytes, out List<WorldGroupRecord> records)
|
||||
{
|
||||
WorldSaveData saveData;
|
||||
bool result = TryDecodeGzip(gzipBytes, out saveData);
|
||||
records = saveData.groupRecords ?? new List<WorldGroupRecord>();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool TryParseGroupWireValue(WorldWireRecord record, string prefix, out int value)
|
||||
{
|
||||
value = 0;
|
||||
if (record.outputNodeId > 0 || string.IsNullOrEmpty(record.outputPortName) || !record.outputPortName.StartsWith(prefix, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (int.TryParse(record.outputPortName.Substring(prefix.Length), out value))
|
||||
{
|
||||
return value >= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryDecodeGzip(byte[] gzipBytes, out WorldSaveData saveData)
|
||||
{
|
||||
saveData = new WorldSaveData
|
||||
{
|
||||
groupRecords = new List<WorldGroupRecord>(),
|
||||
nodeRecords = new List<WorldNodeRecord>(),
|
||||
wireRecords = new List<WorldWireRecord>()
|
||||
};
|
||||
if (gzipBytes == null || gzipBytes.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
byte[] array;
|
||||
try
|
||||
{
|
||||
array = DecompressGzip(gzipBytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (array.Length < Magic.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
using MemoryStream memoryStream = new MemoryStream(array);
|
||||
byte[] array2 = new byte[Magic.Length];
|
||||
if (memoryStream.Read(array2, 0, array2.Length) != array2.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < Magic.Length; i++)
|
||||
{
|
||||
if (array2[i] != Magic[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
uint num;
|
||||
try
|
||||
{
|
||||
num = ReadVarUInt(memoryStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (uint num2 = 0u; num2 < num; num2++)
|
||||
{
|
||||
if (!TryReadGroupRecord(memoryStream, out var record))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
saveData.groupRecords.Add(record);
|
||||
}
|
||||
string sectionName;
|
||||
while (memoryStream.Position < memoryStream.Length && TryReadSectionHeader(memoryStream, out sectionName))
|
||||
{
|
||||
if (sectionName == "nodes")
|
||||
{
|
||||
if (!TryReadNodeSection(memoryStream, saveData.nodeRecords))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!(sectionName == "wires"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!TryReadWireSection(memoryStream, saveData.wireRecords))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<WorldGroupRecord> BuildGroupRecords(IEnumerable<VoxelGroup> groups)
|
||||
{
|
||||
List<WorldGroupRecord> list = new List<WorldGroupRecord>();
|
||||
if (groups == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
foreach (VoxelGroup group in groups)
|
||||
{
|
||||
if (!(group == null) && group.size.x > 0 && group.size.y > 0 && group.size.z > 0 && group.voxels != null)
|
||||
{
|
||||
list.Add(new WorldGroupRecord
|
||||
{
|
||||
position = group.position,
|
||||
packedRotation = group.packedRotation,
|
||||
size = group.size,
|
||||
voxels = (byte[])group.voxels.Clone()
|
||||
});
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void WriteGroupRecord(Stream stream, WorldGroupRecord record)
|
||||
{
|
||||
WriteVarInt(stream, record.position.x);
|
||||
WriteVarInt(stream, record.position.y);
|
||||
WriteVarInt(stream, record.position.z);
|
||||
stream.WriteByte(record.packedRotation);
|
||||
WriteVarUInt(stream, (uint)Mathf.Max(0, record.size.x));
|
||||
WriteVarUInt(stream, (uint)Mathf.Max(0, record.size.y));
|
||||
WriteVarUInt(stream, (uint)Mathf.Max(0, record.size.z));
|
||||
WriteVoxelsRle(stream, record.voxels);
|
||||
}
|
||||
|
||||
private static bool TryReadGroupRecord(Stream stream, out WorldGroupRecord record)
|
||||
{
|
||||
record = default(WorldGroupRecord);
|
||||
try
|
||||
{
|
||||
int x = ReadVarInt(stream);
|
||||
int y = ReadVarInt(stream);
|
||||
int z = ReadVarInt(stream);
|
||||
int num = stream.ReadByte();
|
||||
if (num < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint num2 = ReadVarUInt(stream);
|
||||
uint num3 = ReadVarUInt(stream);
|
||||
uint num4 = ReadVarUInt(stream);
|
||||
int num5 = (int)(num2 * num3 * num4);
|
||||
if (num5 < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte[] voxels = ReadVoxelsRle(stream, num5);
|
||||
record = new WorldGroupRecord
|
||||
{
|
||||
position = new Vector3Int(x, y, z),
|
||||
packedRotation = (byte)num,
|
||||
size = new Vector3Int((int)num2, (int)num3, (int)num4),
|
||||
voxels = voxels
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryReadSectionHeader(Stream stream, out string sectionName)
|
||||
{
|
||||
sectionName = string.Empty;
|
||||
if (stream.Position + 4 > stream.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte[] array = new byte[4];
|
||||
if (stream.Read(array, 0, array.Length) != array.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (SectionMatches(array, NodesSectionMagic))
|
||||
{
|
||||
sectionName = "nodes";
|
||||
return true;
|
||||
}
|
||||
if (SectionMatches(array, WiresSectionMagic))
|
||||
{
|
||||
sectionName = "wires";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryReadNodeSection(Stream stream, List<WorldNodeRecord> records)
|
||||
{
|
||||
try
|
||||
{
|
||||
uint num = ReadVarUInt(stream);
|
||||
for (uint num2 = 0u; num2 < num; num2++)
|
||||
{
|
||||
records.Add(ReadNodeRecord(stream));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryReadWireSection(Stream stream, List<WorldWireRecord> records)
|
||||
{
|
||||
try
|
||||
{
|
||||
uint num = ReadVarUInt(stream);
|
||||
for (uint num2 = 0u; num2 < num; num2++)
|
||||
{
|
||||
records.Add(ReadWireRecord(stream));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteNodeRecord(Stream stream, WorldNodeRecord record)
|
||||
{
|
||||
WriteVarInt(stream, record.nodeId);
|
||||
WriteString(stream, record.definitionName);
|
||||
WriteFloat(stream, record.position.x);
|
||||
WriteFloat(stream, record.position.y);
|
||||
WriteFloat(stream, record.position.z);
|
||||
WriteFloat(stream, record.rotation.x);
|
||||
WriteFloat(stream, record.rotation.y);
|
||||
WriteFloat(stream, record.rotation.z);
|
||||
WriteFloat(stream, record.rotation.w);
|
||||
WritePortValueRecords(stream, record.inputValues);
|
||||
WritePortValueRecords(stream, record.outputValues);
|
||||
}
|
||||
|
||||
private static WorldNodeRecord ReadNodeRecord(Stream stream)
|
||||
{
|
||||
return new WorldNodeRecord
|
||||
{
|
||||
nodeId = ReadVarInt(stream),
|
||||
definitionName = ReadString(stream),
|
||||
position = new Vector3(ReadFloat(stream), ReadFloat(stream), ReadFloat(stream)),
|
||||
rotation = new Quaternion(ReadFloat(stream), ReadFloat(stream), ReadFloat(stream), ReadFloat(stream)),
|
||||
inputValues = ReadPortValueRecords(stream),
|
||||
outputValues = ReadPortValueRecords(stream)
|
||||
};
|
||||
}
|
||||
|
||||
private static void WriteWireRecord(Stream stream, WorldWireRecord record)
|
||||
{
|
||||
WriteVarInt(stream, record.outputNodeId);
|
||||
WriteString(stream, record.outputPortName);
|
||||
WriteVarInt(stream, record.inputNodeId);
|
||||
WriteString(stream, record.inputPortName);
|
||||
}
|
||||
|
||||
private static WorldWireRecord ReadWireRecord(Stream stream)
|
||||
{
|
||||
return new WorldWireRecord
|
||||
{
|
||||
outputNodeId = ReadVarInt(stream),
|
||||
outputPortName = ReadString(stream),
|
||||
inputNodeId = ReadVarInt(stream),
|
||||
inputPortName = ReadString(stream)
|
||||
};
|
||||
}
|
||||
|
||||
private static void WritePortValueRecords(Stream stream, NodePortValueRecord[] records)
|
||||
{
|
||||
if (records == null)
|
||||
{
|
||||
WriteVarUInt(stream, 0u);
|
||||
return;
|
||||
}
|
||||
WriteVarUInt(stream, (uint)records.Length);
|
||||
for (int i = 0; i < records.Length; i++)
|
||||
{
|
||||
WriteString(stream, records[i].portName);
|
||||
WriteBSValue(stream, records[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
private static NodePortValueRecord[] ReadPortValueRecords(Stream stream)
|
||||
{
|
||||
uint num = ReadVarUInt(stream);
|
||||
NodePortValueRecord[] array = new NodePortValueRecord[num];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
array[i] = new NodePortValueRecord
|
||||
{
|
||||
portName = ReadString(stream),
|
||||
value = ReadBSValue(stream)
|
||||
};
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private static void WriteBSValue(Stream stream, BSValue value)
|
||||
{
|
||||
value = value.Normalize();
|
||||
stream.WriteByte((byte)value.Kind);
|
||||
switch (value.Kind)
|
||||
{
|
||||
case BSValueKind.Number:
|
||||
WriteDouble(stream, value.Number);
|
||||
break;
|
||||
case BSValueKind.Text:
|
||||
WriteString(stream, value.Text);
|
||||
break;
|
||||
case BSValueKind.Bool:
|
||||
stream.WriteByte((byte)(value.Bool ? 1u : 0u));
|
||||
break;
|
||||
case BSValueKind.Player:
|
||||
WriteVarInt(stream, value.PlayerId);
|
||||
break;
|
||||
case BSValueKind.Group:
|
||||
WriteVarInt(stream, value.GroupId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static BSValue ReadBSValue(Stream stream)
|
||||
{
|
||||
return (BSValueKind)stream.ReadByte() switch
|
||||
{
|
||||
BSValueKind.Number => BSValue.FromNumber(ReadDouble(stream)),
|
||||
BSValueKind.Text => BSValue.FromText(ReadString(stream)),
|
||||
BSValueKind.Bool => BSValue.FromBool(stream.ReadByte() != 0),
|
||||
BSValueKind.Player => BSValue.FromPlayer(ReadVarInt(stream)),
|
||||
BSValueKind.Group => BSValue.FromGroup(ReadVarInt(stream)),
|
||||
_ => BSValue.None,
|
||||
};
|
||||
}
|
||||
|
||||
private static bool SectionMatches(byte[] a, byte[] b)
|
||||
{
|
||||
if (a == null || b == null || a.Length != b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
{
|
||||
if (a[i] != b[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void WriteVoxelsRle(Stream stream, byte[] voxels)
|
||||
{
|
||||
if (voxels == null || voxels.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int j;
|
||||
for (int i = 0; i < voxels.Length; i += j)
|
||||
{
|
||||
byte b = voxels[i];
|
||||
j = 1;
|
||||
for (int num = voxels.Length - i; j < num && voxels[i + j] == b; j++)
|
||||
{
|
||||
}
|
||||
stream.WriteByte(b);
|
||||
WriteVarUInt(stream, (uint)j);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] ReadVoxelsRle(Stream stream, int expectedLength)
|
||||
{
|
||||
if (expectedLength <= 0)
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
byte[] array = new byte[expectedLength];
|
||||
int num3;
|
||||
for (int i = 0; i < expectedLength; i += num3)
|
||||
{
|
||||
int num = stream.ReadByte();
|
||||
if (num < 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
uint num2 = ReadVarUInt(stream);
|
||||
if (num2 == 0)
|
||||
{
|
||||
throw new InvalidDataException("RLE run length was 0.");
|
||||
}
|
||||
int val = expectedLength - i;
|
||||
num3 = (int)Math.Min(num2, (uint)val);
|
||||
for (int j = 0; j < num3; j++)
|
||||
{
|
||||
array[i + j] = (byte)num;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private static byte[] DecompressGzip(byte[] gzipBytes)
|
||||
{
|
||||
using MemoryStream stream = new MemoryStream(gzipBytes);
|
||||
using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress);
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
gZipStream.CopyTo(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
private static void WriteString(Stream stream, string value)
|
||||
{
|
||||
string s = value ?? string.Empty;
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(s);
|
||||
WriteVarUInt(stream, (uint)bytes.Length);
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
private static string ReadString(Stream stream)
|
||||
{
|
||||
uint num = ReadVarUInt(stream);
|
||||
if (num == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
byte[] array = new byte[num];
|
||||
if (stream.Read(array, 0, array.Length) != array.Length)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
return Encoding.UTF8.GetString(array);
|
||||
}
|
||||
|
||||
private static void WriteFloat(Stream stream, float value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
private static float ReadFloat(Stream stream)
|
||||
{
|
||||
byte[] array = new byte[4];
|
||||
if (stream.Read(array, 0, array.Length) != array.Length)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
return BitConverter.ToSingle(array, 0);
|
||||
}
|
||||
|
||||
private static void WriteDouble(Stream stream, double value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
private static double ReadDouble(Stream stream)
|
||||
{
|
||||
byte[] array = new byte[8];
|
||||
if (stream.Read(array, 0, array.Length) != array.Length)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
return BitConverter.ToDouble(array, 0);
|
||||
}
|
||||
|
||||
private static void WriteVarInt(Stream stream, int value)
|
||||
{
|
||||
uint value2 = (uint)((value << 1) ^ (value >> 31));
|
||||
WriteVarUInt(stream, value2);
|
||||
}
|
||||
|
||||
private static int ReadVarInt(Stream stream)
|
||||
{
|
||||
uint num = ReadVarUInt(stream);
|
||||
return (int)((num >> 1) ^ (0 - (num & 1)));
|
||||
}
|
||||
|
||||
private static void WriteVarUInt(Stream stream, uint value)
|
||||
{
|
||||
while (value >= 128)
|
||||
{
|
||||
stream.WriteByte((byte)(value | 0x80));
|
||||
value >>= 7;
|
||||
}
|
||||
stream.WriteByte((byte)value);
|
||||
}
|
||||
|
||||
private static uint ReadVarUInt(Stream stream)
|
||||
{
|
||||
uint num = 0u;
|
||||
for (int i = 0; i < 35; i += 7)
|
||||
{
|
||||
int num2 = stream.ReadByte();
|
||||
if (num2 < 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
num |= (uint)((num2 & 0x7F) << i);
|
||||
if ((num2 & 0x80) == 0)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
}
|
||||
throw new InvalidDataException("VarUInt was too long.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user