Skip to content

Commit 3624ec4

Browse files
committed
Reworked BinarySerializer to use BitWriter
1 parent 20b315b commit 3624ec4

File tree

3 files changed

+148
-125
lines changed

3 files changed

+148
-125
lines changed

MLAPI/Data/FieldType.cs

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,124 @@ internal enum FieldType
4545

4646
internal static class FieldTypeHelper
4747
{
48+
internal static object ReadFieldType(BitReader reader, FieldType fieldType)
49+
{
50+
switch (fieldType)
51+
{
52+
case FieldType.Bool:
53+
return reader.ReadBool();
54+
case FieldType.Byte:
55+
return reader.ReadByte();
56+
case FieldType.Double:
57+
return reader.ReadDouble();
58+
case FieldType.Single:
59+
return reader.ReadFloat();
60+
case FieldType.Int:
61+
return reader.ReadInt();
62+
case FieldType.Long:
63+
return reader.ReadLong();
64+
case FieldType.SByte:
65+
return reader.ReadSByte();
66+
case FieldType.Short:
67+
return reader.ReadShort();
68+
case FieldType.UInt:
69+
return reader.ReadUInt();
70+
case FieldType.ULong:
71+
return reader.ReadULong();
72+
case FieldType.UShort:
73+
return reader.ReadUShort();
74+
case FieldType.String:
75+
return reader.ReadString();
76+
case FieldType.Vector3:
77+
Vector3 vector3 = Vector3.zero;
78+
vector3.x = reader.ReadFloat();
79+
vector3.y = reader.ReadFloat();
80+
vector3.z = reader.ReadFloat();
81+
return vector3;
82+
case FieldType.Vector2:
83+
Vector2 vector2 = Vector2.zero;
84+
vector2.x = reader.ReadFloat();
85+
vector2.y = reader.ReadFloat();
86+
return vector2;
87+
case FieldType.Quaternion:
88+
Vector3 eulerAngle = Vector3.zero;
89+
eulerAngle.x = reader.ReadFloat();
90+
eulerAngle.y = reader.ReadFloat();
91+
eulerAngle.z = reader.ReadFloat();
92+
return Quaternion.Euler(eulerAngle);
93+
case FieldType.BoolArray:
94+
ushort boolCount = reader.ReadUShort();
95+
bool[] bools = new bool[boolCount];
96+
for (int j = 0; j < boolCount; j++)
97+
bools[j] = reader.ReadBool();
98+
return bools;
99+
case FieldType.ByteArray:
100+
return reader.ReadByteArray();
101+
case FieldType.DoubleArray:
102+
return reader.ReadDoubleArray();
103+
case FieldType.SingleArray:
104+
return reader.ReadFloatArray();
105+
case FieldType.IntArray:
106+
return reader.ReadIntArray();
107+
case FieldType.LongArray:
108+
return reader.ReadLongArray();
109+
case FieldType.SByteArray:
110+
return reader.ReadSByteArray();
111+
case FieldType.ShortArray:
112+
return reader.ReadShortArray();
113+
case FieldType.UIntArray:
114+
return reader.ReadUIntArray();
115+
case FieldType.ULongArray:
116+
return reader.ReadULongArray();
117+
case FieldType.UShortArray:
118+
return reader.ReadUShortArray();
119+
case FieldType.StringArray:
120+
ushort stringCount = reader.ReadUShort();
121+
string[] strings = new string[stringCount];
122+
for (int j = 0; j < stringCount; j++)
123+
strings[j] = reader.ReadString();
124+
return strings;
125+
case FieldType.Vector3Array:
126+
ushort vector3Count = reader.ReadUShort();
127+
Vector3[] vector3s = new Vector3[vector3Count];
128+
for (int j = 0; j < vector3Count; j++)
129+
{
130+
Vector3 vec3 = Vector3.zero;
131+
vec3.x = reader.ReadFloat();
132+
vec3.y = reader.ReadFloat();
133+
vec3.z = reader.ReadFloat();
134+
vector3s[j] = vec3;
135+
}
136+
return vector3s;
137+
case FieldType.Vector2Array:
138+
ushort vector2Count = reader.ReadUShort();
139+
Vector2[] vector2s = new Vector2[vector2Count];
140+
for (int j = 0; j < vector2Count; j++)
141+
{
142+
Vector2 vec2 = Vector2.zero;
143+
vec2.x = reader.ReadFloat();
144+
vec2.y = reader.ReadFloat();
145+
vector2s[j] = vec2;
146+
}
147+
return vector2s;
148+
case FieldType.QuaternionArray:
149+
ushort quaternionCount = reader.ReadUShort();
150+
Quaternion[] quaternions = new Quaternion[quaternionCount];
151+
for (int j = 0; j < quaternionCount; j++)
152+
{
153+
Vector3 vec3 = Vector3.zero;
154+
vec3.x = reader.ReadFloat();
155+
vec3.y = reader.ReadFloat();
156+
vec3.z = reader.ReadFloat();
157+
quaternions[j] = Quaternion.Euler(vec3);
158+
}
159+
return quaternions;
160+
case FieldType.Invalid:
161+
return null;
162+
}
163+
return null;
164+
}
165+
48166
internal static void WriteFieldType(BitWriter writer, object value, FieldType fieldType)
49167
{
50168
switch (fieldType)
@@ -440,8 +558,10 @@ internal static object[] ReadObjects(BitReader reader, byte paramCount)
440558
break;
441559
case FieldType.BoolArray:
442560
ushort boolCount = reader.ReadUShort();
561+
bool[] bools = new bool[boolCount];
443562
for (int j = 0; j < boolCount; j++)
444-
returnVal[i] = reader.ReadBool();
563+
bools[j] = reader.ReadBool();
564+
returnVal[i] = bools;
445565
break;
446566
case FieldType.ByteArray:
447567
returnVal[i] = reader.ReadByteArray();

MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,17 @@ protected int RegisterMessageHandler(string name, Action<uint, byte[]> action)
284284
return counter;
285285
}
286286

287+
/// <summary>
288+
/// Deserializes a message that has been serialized by the BinarySerializer. This is the same as calling BinarySerializer.Deserialize
289+
/// </summary>
290+
/// <typeparam name="T">The type</typeparam>
291+
/// <param name="binary">The serialized version</param>
292+
/// <returns>Instance of type</returns>
293+
protected T DeserializeMessage<T>(byte[] binary) where T : new()
294+
{
295+
return BinarySerializer.Deserialize<T>(binary);
296+
}
297+
287298
/// <summary>
288299
/// Deregisters a given message handler
289300
/// </summary>

MLAPI/NetworkingManagerComponents/Binary/BinarySerializer.cs

Lines changed: 16 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using MLAPI.Attributes;
2+
using MLAPI.Data;
23
using System.Collections.Generic;
3-
using System.IO;
44
using System.Linq;
55
using System.Reflection;
6-
using System.Text;
76
using UnityEngine;
87

98
namespace MLAPI.NetworkingManagerComponents.Binary
@@ -41,90 +40,19 @@ public static byte[] Serialize<T>(T instance)
4140
cachedFields.Add(instance.GetType().FullName, sortedFields);
4241
}
4342

44-
int outputSize = 0;
45-
//Calculate output size
46-
for (int i = 0; i < sortedFields.Length; i++)
47-
{
48-
if (sortedFields[i].FieldType == typeof(bool))
49-
outputSize += 1;
50-
else if (sortedFields[i].FieldType == typeof(byte))
51-
outputSize += 1;
52-
else if (sortedFields[i].FieldType == typeof(char))
53-
outputSize += 2;
54-
else if (sortedFields[i].FieldType == typeof(double))
55-
outputSize += 8;
56-
else if (sortedFields[i].FieldType == typeof(float))
57-
outputSize += 4;
58-
else if (sortedFields[i].FieldType == typeof(decimal))
59-
outputSize += 16;
60-
else if (sortedFields[i].FieldType == typeof(int))
61-
outputSize += 4;
62-
else if (sortedFields[i].FieldType == typeof(long))
63-
outputSize += 8;
64-
else if (sortedFields[i].FieldType == typeof(sbyte))
65-
outputSize += 1;
66-
else if (sortedFields[i].FieldType == typeof(short))
67-
outputSize += 2;
68-
else if (sortedFields[i].FieldType == typeof(uint))
69-
outputSize += 4;
70-
else if (sortedFields[i].FieldType == typeof(ulong))
71-
outputSize += 8;
72-
else if (sortedFields[i].FieldType == typeof(ushort))
73-
outputSize += 2;
74-
else if (sortedFields[i].FieldType == typeof(string))
75-
outputSize += Encoding.UTF8.GetByteCount((string)sortedFields[i].GetValue(instance)) + 2;
76-
else if (sortedFields[i].FieldType == typeof(byte[]))
77-
outputSize += ((byte[])sortedFields[i].GetValue(instance)).Length + 2; //Two bytes to specify the size
78-
else
79-
Debug.LogWarning("MLAPI: The type \"" + sortedFields[i].FieldType.Name + "\" is not supported by the Binary Serializer. It will be ignored");
80-
}
81-
82-
//Write data
83-
using (MemoryStream stream = new MemoryStream(outputSize))
43+
using (BitWriter writer = new BitWriter())
8444
{
85-
using (BinaryWriter writer = new BinaryWriter(stream))
45+
for (int i = 0; i < sortedFields.Length; i++)
8646
{
87-
for (int i = 0; i < sortedFields.Length; i++)
47+
FieldType fieldType = FieldTypeHelper.GetFieldType(sortedFields[i].FieldType);
48+
if (fieldType == FieldType.Invalid)
8849
{
89-
if (sortedFields[i].FieldType == typeof(bool))
90-
writer.Write((bool)sortedFields[i].GetValue(instance));
91-
else if (sortedFields[i].FieldType == typeof(byte))
92-
writer.Write((byte)sortedFields[i].GetValue(instance));
93-
else if (sortedFields[i].FieldType == typeof(char))
94-
writer.Write((char)sortedFields[i].GetValue(instance));
95-
else if (sortedFields[i].FieldType == typeof(double))
96-
writer.Write((double)sortedFields[i].GetValue(instance));
97-
else if (sortedFields[i].FieldType == typeof(float))
98-
writer.Write((float)sortedFields[i].GetValue(instance));
99-
else if (sortedFields[i].FieldType == typeof(decimal))
100-
writer.Write((decimal)sortedFields[i].GetValue(instance));
101-
else if (sortedFields[i].FieldType == typeof(int))
102-
writer.Write((int)sortedFields[i].GetValue(instance));
103-
else if (sortedFields[i].FieldType == typeof(long))
104-
writer.Write((long)sortedFields[i].GetValue(instance));
105-
else if (sortedFields[i].FieldType == typeof(sbyte))
106-
writer.Write((sbyte)sortedFields[i].GetValue(instance));
107-
else if (sortedFields[i].FieldType == typeof(short))
108-
writer.Write((short)sortedFields[i].GetValue(instance));
109-
else if (sortedFields[i].FieldType == typeof(uint))
110-
writer.Write((uint)sortedFields[i].GetValue(instance));
111-
else if (sortedFields[i].FieldType == typeof(ulong))
112-
writer.Write((ulong)sortedFields[i].GetValue(instance));
113-
else if (sortedFields[i].FieldType == typeof(ushort))
114-
writer.Write((ushort)sortedFields[i].GetValue(instance));
115-
else if (sortedFields[i].FieldType == typeof(string))
116-
{
117-
writer.Write((ushort)Encoding.UTF8.GetByteCount((string)sortedFields[i].GetValue(instance))); //Size of string in bytes
118-
writer.Write(Encoding.UTF8.GetBytes((string)sortedFields[i].GetValue(instance)));
119-
}
120-
else if (sortedFields[i].FieldType == typeof(byte[]))
121-
{
122-
writer.Write((ushort)((byte[])sortedFields[i].GetValue(instance)).Length); //Size of byte array
123-
writer.Write((byte[])sortedFields[i].GetValue(instance));
124-
}
50+
Debug.LogWarning("MLAPI: The field " + sortedFields[i].Name + " will not be serialized as it's not of a supported type. Add the BinaryIgnore attribute to prevent this message from shwoing up.");
51+
continue;
12552
}
53+
FieldTypeHelper.WriteFieldType(writer, sortedFields[i].GetValue(instance), fieldType);
12654
}
127-
return stream.ToArray();
55+
return writer.Finalize();
12856
}
12957
}
13058

@@ -148,52 +76,16 @@ public static byte[] Serialize<T>(T instance)
14876
cachedFields.Add(instance.GetType().FullName, sortedFields);
14977
}
15078

151-
using (MemoryStream stream = new MemoryStream(binary))
79+
BitReader reader = new BitReader(binary);
80+
for (int i = 0; i < sortedFields.Length; i++)
15281
{
153-
using (BinaryReader reader = new BinaryReader(stream))
82+
FieldType fieldType = FieldTypeHelper.GetFieldType(sortedFields[i].FieldType);
83+
if (fieldType == FieldType.Invalid)
15484
{
155-
for (int i = 0; i < sortedFields.Length; i++)
156-
{
157-
if (sortedFields[i].FieldType == typeof(bool))
158-
sortedFields[i].SetValue(instance, reader.ReadBoolean());
159-
else if (sortedFields[i].FieldType == typeof(byte))
160-
sortedFields[i].SetValue(instance, reader.ReadByte());
161-
else if (sortedFields[i].FieldType == typeof(char))
162-
sortedFields[i].SetValue(instance, reader.ReadChar());
163-
else if (sortedFields[i].FieldType == typeof(double))
164-
sortedFields[i].SetValue(instance, reader.ReadDouble());
165-
else if (sortedFields[i].FieldType == typeof(float))
166-
sortedFields[i].SetValue(instance, reader.ReadSingle());
167-
else if (sortedFields[i].FieldType == typeof(decimal))
168-
sortedFields[i].SetValue(instance, reader.ReadDecimal());
169-
else if (sortedFields[i].FieldType == typeof(int))
170-
sortedFields[i].SetValue(instance, reader.ReadInt32());
171-
else if (sortedFields[i].FieldType == typeof(long))
172-
sortedFields[i].SetValue(instance, reader.ReadInt64());
173-
else if (sortedFields[i].FieldType == typeof(sbyte))
174-
sortedFields[i].SetValue(instance, reader.ReadSByte());
175-
else if (sortedFields[i].FieldType == typeof(short))
176-
sortedFields[i].SetValue(instance, reader.ReadInt16());
177-
else if (sortedFields[i].FieldType == typeof(uint))
178-
sortedFields[i].SetValue(instance, reader.ReadUInt32());
179-
else if (sortedFields[i].FieldType == typeof(ulong))
180-
sortedFields[i].SetValue(instance, reader.ReadUInt64());
181-
else if (sortedFields[i].FieldType == typeof(ushort))
182-
sortedFields[i].SetValue(instance, reader.ReadUInt64());
183-
else if (sortedFields[i].FieldType == typeof(string))
184-
{
185-
ushort size = reader.ReadUInt16();
186-
sortedFields[i].SetValue(instance, Encoding.UTF8.GetString(reader.ReadBytes(size)));
187-
}
188-
else if (sortedFields[i].FieldType == typeof(byte[]))
189-
{
190-
ushort size = reader.ReadUInt16();
191-
sortedFields[i].SetValue(instance, reader.ReadBytes(size));
192-
}
193-
else
194-
Debug.LogWarning("MLAPI: The type \"" + sortedFields[i].FieldType.Name + "\" is not supported by the Binary Serializer. It will be ignored");
195-
}
85+
Debug.LogWarning("MLAPI: The field " + sortedFields[i].Name + " will not be deserialized as it's not of a supported type. Add the BinaryIgnore attribute to prevent this message from shwoing up.");
86+
continue;
19687
}
88+
sortedFields[i].SetValue(instance, FieldTypeHelper.ReadFieldType(reader, fieldType));
19789
}
19890
return instance;
19991
}

0 commit comments

Comments
 (0)