diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs index a223bdee2..93b7ed3d1 100644 --- a/Assets/Mirror/Components/NetworkAnimator.cs +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -229,7 +229,7 @@ bool WriteParameters(NetworkWriter writer) if (par.type == AnimatorControllerParameterType.Int) { int newIntValue = animator.GetInteger(par.nameHash); - writer.WritePackedUInt32((uint)newIntValue); + writer.WritePackedInt32(newIntValue); } else if (par.type == AnimatorControllerParameterType.Float) { @@ -256,7 +256,7 @@ void ReadParameters(NetworkReader reader) AnimatorControllerParameter par = parameters[i]; if (par.type == AnimatorControllerParameterType.Int) { - int newIntValue = (int)reader.ReadPackedUInt32(); + int newIntValue = reader.ReadPackedInt32(); animator.SetInteger(par.nameHash, newIntValue); } else if (par.type == AnimatorControllerParameterType.Float) diff --git a/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs index 0cf82d23a..b87df5417 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs @@ -372,7 +372,7 @@ void GenerateSerialization() serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference)); - serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked64)); + serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePackedUInt64)); // generate a writer call for any dirty variable in this class @@ -462,7 +462,7 @@ void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker, MethodDefi // read id and store in a local variable serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkReaderReadPacked32)); + serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkReaderReadPackedUInt32)); serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue)); if (foundMethod != null) @@ -572,7 +572,7 @@ void GenerateDeSerialization() // get dirty bits serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked64)); + serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPackedUInt64)); serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); // conditionally read each syncvar diff --git a/Assets/Mirror/Editor/Weaver/Weaver.cs b/Assets/Mirror/Editor/Weaver/Weaver.cs index af2138c33..99cfc66e7 100644 --- a/Assets/Mirror/Editor/Weaver/Weaver.cs +++ b/Assets/Mirror/Editor/Weaver/Weaver.cs @@ -101,11 +101,15 @@ class Weaver public static MethodReference NetworkServerGetLocalClientActive; public static MethodReference NetworkClientGetActive; public static MethodReference UBehaviourIsServer; - public static MethodReference NetworkReaderReadPacked32; - public static MethodReference NetworkReaderReadPacked64; + public static MethodReference NetworkReaderReadPackedUInt32; + public static MethodReference NetworkReaderReadPackedInt32; + public static MethodReference NetworkReaderReadPackedUInt64; + public static MethodReference NetworkReaderReadPackedInt64; public static MethodReference NetworkReaderReadByte; - public static MethodReference NetworkWriterWritePacked32; - public static MethodReference NetworkWriterWritePacked64; + public static MethodReference NetworkWriterWritePackedUInt32; + public static MethodReference NetworkWriterWritePackedInt32; + public static MethodReference NetworkWriterWritePackedUInt64; + public static MethodReference NetworkWriterWritePackedInt64; public static MethodReference NetworkReadUInt16; public static MethodReference NetworkWriteUInt16; @@ -1101,12 +1105,16 @@ static void SetupTargetTypes() NetworkWriterWriteInt32 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int32Type); NetworkWriterWriteInt16 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int16Type); - NetworkReaderReadPacked32 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt32"); - NetworkReaderReadPacked64 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt64"); + NetworkReaderReadPackedUInt32 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt32"); + NetworkReaderReadPackedInt32 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedInt32"); + NetworkReaderReadPackedUInt64 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt64"); + NetworkReaderReadPackedInt64 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedInt64"); NetworkReaderReadByte = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadByte"); - NetworkWriterWritePacked32 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt32"); - NetworkWriterWritePacked64 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt64"); + NetworkWriterWritePackedUInt32 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt32"); + NetworkWriterWritePackedInt32 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedInt32"); + NetworkWriterWritePackedUInt64 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt64"); + NetworkWriterWritePackedInt64 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedInt64"); NetworkReadUInt16 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadUInt16"); NetworkWriteUInt16 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", uint16Type); @@ -1180,10 +1188,10 @@ static void SetupReadFunctions() { doubleType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadDouble") }, { boolType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadBoolean") }, { stringType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadString") }, - { int64Type.FullName, NetworkReaderReadPacked64 }, - { uint64Type.FullName, NetworkReaderReadPacked64 }, - { int32Type.FullName, NetworkReaderReadPacked32 }, - { uint32Type.FullName, NetworkReaderReadPacked32 }, + { int64Type.FullName, NetworkReaderReadPackedInt64 }, + { uint64Type.FullName, NetworkReaderReadPackedUInt64 }, + { int32Type.FullName, NetworkReaderReadPackedInt32 }, + { uint32Type.FullName, NetworkReaderReadPackedUInt32 }, { int16Type.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadInt16") }, { uint16Type.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadUInt16") }, { byteType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadByte") }, @@ -1218,10 +1226,10 @@ static void SetupWriteFunctions() { doubleType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", doubleType) }, { boolType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", boolType) }, { stringType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", stringType) }, - { int64Type.FullName, NetworkWriterWritePacked64 }, - { uint64Type.FullName, NetworkWriterWritePacked64 }, - { int32Type.FullName, NetworkWriterWritePacked32 }, - { uint32Type.FullName, NetworkWriterWritePacked32 }, + { int64Type.FullName, NetworkWriterWritePackedInt64 }, + { uint64Type.FullName, NetworkWriterWritePackedUInt64 }, + { int32Type.FullName, NetworkWriterWritePackedInt32 }, + { uint32Type.FullName, NetworkWriterWritePackedUInt32 }, { int16Type.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int16Type) }, { uint16Type.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", uint16Type) }, { byteType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", byteType) }, diff --git a/Assets/Mirror/Runtime/Messages.cs b/Assets/Mirror/Runtime/Messages.cs index b708d42a5..3b96dba33 100644 --- a/Assets/Mirror/Runtime/Messages.cs +++ b/Assets/Mirror/Runtime/Messages.cs @@ -99,12 +99,12 @@ public IntegerMessage(int v) public override void Deserialize(NetworkReader reader) { - value = (int)reader.ReadPackedUInt32(); + value = reader.ReadPackedInt32(); } public override void Serialize(NetworkWriter writer) { - writer.WritePackedUInt32((uint)value); + writer.WritePackedInt32(value); } } diff --git a/Assets/Mirror/Runtime/NetworkReader.cs b/Assets/Mirror/Runtime/NetworkReader.cs index fe174c04f..d79a93208 100644 --- a/Assets/Mirror/Runtime/NetworkReader.cs +++ b/Assets/Mirror/Runtime/NetworkReader.cs @@ -57,6 +57,13 @@ public byte[] ReadBytesAndSize() return null; } + // zigzag decoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba + public int ReadPackedInt32() + { + uint data = ReadPackedUInt32(); + return (int)((data >> 1) ^ -(data & 1)); + } + // http://sqlite.org/src4/doc/trunk/www/varint.wiki // NOTE: big endian. public uint ReadPackedUInt32() @@ -69,6 +76,13 @@ public uint ReadPackedUInt32() return (uint)value; } + // zigzag decoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba + public long ReadPackedInt64() + { + ulong data = ReadPackedUInt64(); + return ((long)(data >> 1)) ^ -((long)data & 1); + } + public ulong ReadPackedUInt64() { byte a0 = ReadByte(); @@ -145,12 +159,12 @@ public Vector4 ReadVector4() public Vector2Int ReadVector2Int() { - return new Vector2Int((int)ReadPackedUInt32(), (int)ReadPackedUInt32()); + return new Vector2Int(ReadPackedInt32(), ReadPackedInt32()); } public Vector3Int ReadVector3Int() { - return new Vector3Int((int)ReadPackedUInt32(), (int)ReadPackedUInt32(), (int)ReadPackedUInt32()); + return new Vector3Int(ReadPackedInt32(), ReadPackedInt32(), ReadPackedInt32()); } public Color ReadColor() diff --git a/Assets/Mirror/Runtime/NetworkWriter.cs b/Assets/Mirror/Runtime/NetworkWriter.cs index 05038cf7f..739868778 100644 --- a/Assets/Mirror/Runtime/NetworkWriter.cs +++ b/Assets/Mirror/Runtime/NetworkWriter.cs @@ -100,6 +100,13 @@ public void WriteBytesAndSize(byte[] buffer) WriteBytesAndSize(buffer, 0, buffer != null ? buffer.Length : 0); } + // zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba + public void WritePackedInt32(int i) + { + uint zigzagged = (uint)((i >> 31) ^ (i << 1)); + WritePackedUInt32(zigzagged); + } + // http://sqlite.org/src4/doc/trunk/www/varint.wiki public void WritePackedUInt32(uint value) { @@ -108,6 +115,13 @@ public void WritePackedUInt32(uint value) WritePackedUInt64(value); } + // zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba + public void WritePackedInt64(long i) + { + ulong zigzagged = (ulong)((i >> 63) ^ (i << 1)); + WritePackedUInt64(zigzagged); + } + public void WritePackedUInt64(ulong value) { if (value <= 240) @@ -216,15 +230,15 @@ public void Write(Vector4 value) public void Write(Vector2Int value) { - WritePackedUInt32((uint)value.x); - WritePackedUInt32((uint)value.y); + WritePackedInt32(value.x); + WritePackedInt32(value.y); } public void Write(Vector3Int value) { - WritePackedUInt32((uint)value.x); - WritePackedUInt32((uint)value.y); - WritePackedUInt32((uint)value.z); + WritePackedInt32(value.x); + WritePackedInt32(value.y); + WritePackedInt32(value.z); } public void Write(Color value) diff --git a/Assets/Mirror/Runtime/SyncList.cs b/Assets/Mirror/Runtime/SyncList.cs index 689698ab8..81c3da532 100644 --- a/Assets/Mirror/Runtime/SyncList.cs +++ b/Assets/Mirror/Runtime/SyncList.cs @@ -19,8 +19,8 @@ public class SyncListFloat : SyncList public class SyncListInt : SyncList { - protected override void SerializeItem(NetworkWriter writer, int item) => writer.WritePackedUInt32((uint)item); - protected override int DeserializeItem(NetworkReader reader) => (int)reader.ReadPackedUInt32(); + protected override void SerializeItem(NetworkWriter writer, int item) => writer.WritePackedInt32(item); + protected override int DeserializeItem(NetworkReader reader) => reader.ReadPackedInt32(); } public class SyncListUInt : SyncList diff --git a/Assets/Mirror/Tests/NetworkWriterTest.cs b/Assets/Mirror/Tests/NetworkWriterTest.cs index 7b7306e57..0d84dfec9 100644 --- a/Assets/Mirror/Tests/NetworkWriterTest.cs +++ b/Assets/Mirror/Tests/NetworkWriterTest.cs @@ -79,6 +79,42 @@ public void TestPackedUInt32() Assert.That(reader.ReadPackedUInt32(), Is.EqualTo(uint.MaxValue)); } + [Test] + public void TestPackedInt32() + { + NetworkWriter writer = new NetworkWriter(); + writer.WritePackedInt32(0); + writer.WritePackedInt32(234); + writer.WritePackedInt32(2284); + writer.WritePackedInt32(67821); + writer.WritePackedInt32(16777210); + writer.WritePackedInt32(16777219); + writer.WritePackedInt32(int.MaxValue); + writer.WritePackedInt32(-1); + writer.WritePackedInt32(-234); + writer.WritePackedInt32(-2284); + writer.WritePackedInt32(-67821); + writer.WritePackedInt32(-16777210); + writer.WritePackedInt32(-16777219); + writer.WritePackedInt32(int.MinValue); + + NetworkReader reader = new NetworkReader(writer.ToArray()); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(0)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(234)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(2284)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(67821)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(16777210)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(16777219)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(int.MaxValue)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-1)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-234)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-2284)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-67821)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-16777210)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-16777219)); + Assert.That(reader.ReadPackedInt32(), Is.EqualTo(int.MinValue)); + } + [Test] public void TestPackedUInt64() { @@ -109,6 +145,58 @@ public void TestPackedUInt64() Assert.That(reader.ReadPackedUInt64(), Is.EqualTo(ulong.MaxValue)); } + [Test] + public void TestPackedInt64() + { + NetworkWriter writer = new NetworkWriter(); + writer.WritePackedInt64(0); + writer.WritePackedInt64(234); + writer.WritePackedInt64(2284); + writer.WritePackedInt64(67821); + writer.WritePackedInt64(16777210); + writer.WritePackedInt64(16777219); + writer.WritePackedInt64(4294967295); + writer.WritePackedInt64(1099511627775); + writer.WritePackedInt64(281474976710655); + writer.WritePackedInt64(72057594037927935); + writer.WritePackedInt64(long.MaxValue); + writer.WritePackedInt64(-1); + writer.WritePackedInt64(-234); + writer.WritePackedInt64(-2284); + writer.WritePackedInt64(-67821); + writer.WritePackedInt64(-16777210); + writer.WritePackedInt64(-16777219); + writer.WritePackedInt64(-4294967295); + writer.WritePackedInt64(-1099511627775); + writer.WritePackedInt64(-281474976710655); + writer.WritePackedInt64(-72057594037927935); + writer.WritePackedInt64(long.MinValue); + + NetworkReader reader = new NetworkReader(writer.ToArray()); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(0)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(234)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(2284)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(67821)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(16777210)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(16777219)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(4294967295)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(1099511627775)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(281474976710655)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(72057594037927935)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(long.MaxValue)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-1)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-234)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-2284)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-67821)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-16777210)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-16777219)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-4294967295)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-1099511627775)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-281474976710655)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(-72057594037927935)); + Assert.That(reader.ReadPackedInt64(), Is.EqualTo(long.MinValue)); + } + [Test] public void TestGuid() {