Skip to content

Commit 79b1a31

Browse files
committed
Added diff sending for arrays
1 parent f419471 commit 79b1a31

File tree

5 files changed

+197
-24
lines changed

5 files changed

+197
-24
lines changed

MLAPI/Data/FieldType.cs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,109 @@ internal static bool ObjectEqual(object o1, object o2)
3434
return o1.Equals(o2);
3535
}
3636

37+
//TODO: Better description, method name is not very descriptive.
38+
internal static object GetReferenceArrayValue(object newValue, object currentValue)
39+
{
40+
if (newValue.GetType().IsArray)
41+
{
42+
Array newArray = (Array)newValue;
43+
Array currentArray = (Array)currentValue;
44+
if (currentValue != null && newArray.Length == currentArray.Length)
45+
{
46+
for (int i = 0; i < newArray.Length; i++) newArray.SetValue(currentArray.GetValue(i), i); //Copy the old array values
47+
return newArray;
48+
}
49+
else
50+
{
51+
//Create a new instance.
52+
Array newArr = Array.CreateInstance(newValue.GetType().GetElementType(), newArray.Length);
53+
for (int i = 0; i < newArray.Length; i++) newArr.SetValue(newArray.GetValue(i), i);
54+
return newArr;
55+
}
56+
}
57+
return newValue;
58+
}
59+
60+
internal static void WriteFieldType(BitWriter writer, object newValue, object oldValue)
61+
{
62+
Type type = newValue.GetType();
63+
if (type.IsArray)
64+
{
65+
Array newArray = (Array)newValue;
66+
Array oldArray = (Array)oldValue;
67+
if (oldValue == null || newArray.Length != oldArray.Length)
68+
{
69+
writer.WriteBool(false); //False = not a diff
70+
//Send the full array.
71+
ushort arrayLength = (ushort)newArray.Length;
72+
writer.WriteUShort(arrayLength);
73+
foreach (object element in newArray) WriteFieldType(writer, element);
74+
}
75+
else
76+
{
77+
writer.WriteBool(true); //True = diff
78+
//Send diff
79+
for (int i = 0; i < newArray.Length; i++)
80+
{
81+
bool changed = newArray.GetValue(i) != oldArray.GetValue(i);
82+
writer.WriteBool(changed);
83+
if (changed) WriteFieldType(writer, newArray.GetValue(i));
84+
}
85+
}
86+
}
87+
else
88+
{
89+
if (newValue is bool)
90+
writer.WriteBool((bool)newValue);
91+
else if (newValue is byte)
92+
writer.WriteByte((byte)newValue);
93+
else if (newValue is double)
94+
writer.WriteDouble((double)newValue);
95+
else if (newValue is float)
96+
writer.WriteFloat((float)newValue);
97+
else if (newValue is int)
98+
writer.WriteInt((int)newValue);
99+
else if (newValue is long)
100+
writer.WriteLong((long)newValue);
101+
else if (newValue is sbyte)
102+
writer.WriteSByte((sbyte)newValue);
103+
else if (newValue is short)
104+
writer.WriteShort((short)newValue);
105+
else if (newValue is uint)
106+
writer.WriteUInt((uint)newValue);
107+
else if (newValue is ulong)
108+
writer.WriteULong((ulong)newValue);
109+
else if (newValue is ushort)
110+
writer.WriteUShort((ushort)newValue);
111+
else if (newValue is string)
112+
writer.WriteString((string)newValue);
113+
else if (newValue is Vector3)
114+
{
115+
Vector3 vector3 = (Vector3)newValue;
116+
writer.WriteFloat(vector3.x);
117+
writer.WriteFloat(vector3.y);
118+
writer.WriteFloat(vector3.z);
119+
}
120+
else if (newValue is Vector2)
121+
{
122+
Vector2 vector2 = (Vector2)newValue;
123+
writer.WriteFloat(vector2.x);
124+
writer.WriteFloat(vector2.y);
125+
}
126+
else if (newValue is Quaternion)
127+
{
128+
Vector3 euler = ((Quaternion)newValue).eulerAngles;
129+
writer.WriteFloat(euler.x);
130+
writer.WriteFloat(euler.y);
131+
writer.WriteFloat(euler.z);
132+
}
133+
else
134+
{
135+
BinarySerializer.Serialize(newValue, writer);
136+
}
137+
}
138+
}
139+
37140
internal static void WriteFieldType(BitWriter writer, object value)
38141
{
39142
Type type = value.GetType();
@@ -97,6 +200,88 @@ internal static void WriteFieldType(BitWriter writer, object value)
97200
}
98201
}
99202

203+
internal static object ReadFieldType(BitReader reader, Type type, ref object oldValueRef)
204+
{
205+
if (type.IsArray)
206+
{
207+
bool diffMode = reader.ReadBool();
208+
if (diffMode)
209+
{
210+
Array arr = (Array)oldValueRef;
211+
for (int i = 0; i < arr.Length; i++)
212+
{
213+
if (!reader.ReadBool()) //If it's not changed
214+
continue;
215+
216+
arr.SetValue(ReadFieldType(reader, type.GetElementType()), i);
217+
}
218+
return arr;
219+
}
220+
else
221+
{
222+
ushort arrayLength = reader.ReadUShort();
223+
Type elementType = type.GetElementType();
224+
Array array = Array.CreateInstance(elementType, arrayLength);
225+
for (int i = 0; i < arrayLength; i++) array.SetValue(ReadFieldType(reader, elementType), i);
226+
return array;
227+
}
228+
}
229+
else
230+
{
231+
if (type == typeof(bool))
232+
return reader.ReadBool();
233+
else if (type == typeof(byte))
234+
return reader.ReadByte();
235+
else if (type == typeof(double))
236+
return reader.ReadDouble();
237+
else if (type == typeof(float))
238+
return reader.ReadFloat();
239+
else if (type == typeof(int))
240+
return reader.ReadInt();
241+
else if (type == typeof(long))
242+
return reader.ReadLong();
243+
else if (type == typeof(sbyte))
244+
return reader.ReadSByte();
245+
else if (type == typeof(short))
246+
return reader.ReadShort();
247+
else if (type == typeof(uint))
248+
return reader.ReadUInt();
249+
else if (type == typeof(ulong))
250+
return reader.ReadULong();
251+
else if (type == typeof(ushort))
252+
return reader.ReadUShort();
253+
else if (type == typeof(string))
254+
return reader.ReadString();
255+
else if (type == typeof(Vector3))
256+
{
257+
Vector3 vector3 = new Vector3();
258+
vector3.x = reader.ReadFloat();
259+
vector3.x = reader.ReadFloat();
260+
vector3.y = reader.ReadFloat();
261+
return vector3;
262+
}
263+
else if (type == typeof(Vector2))
264+
{
265+
Vector2 vector2 = new Vector2();
266+
vector2.x = reader.ReadFloat();
267+
vector2.x = reader.ReadFloat();
268+
return vector2;
269+
}
270+
else if (type == typeof(Quaternion))
271+
{
272+
Vector3 euler = new Vector3();
273+
euler.x = reader.ReadFloat();
274+
euler.x = reader.ReadFloat();
275+
euler.y = reader.ReadFloat();
276+
return Quaternion.Euler(euler);
277+
}
278+
else
279+
{
280+
return BinarySerializer.Deserialize(reader, type);
281+
}
282+
}
283+
}
284+
100285
internal static object ReadFieldType(BitReader reader, Type type)
101286
{
102287
if (type.IsArray)

MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,7 @@ protected void InvokeCommand(string methodName, params object[] methodParams)
246246
writer.WriteUShort(networkedObject.GetOrderIndex(this));
247247
writer.WriteULong(hash);
248248
for (int i = 0; i < methodParams.Length; i++)
249-
{
250-
Type type = methodParams[i].GetType();
251249
FieldTypeHelper.WriteFieldType(writer, methodParams[i]);
252-
}
253250

254251
InternalMessageHandler.Send(NetworkingManager.singleton.NetworkConfig.NetworkTransport.ServerNetId, "MLAPI_COMMAND", messageChannelName[methodName], writer, null);
255252
}
@@ -286,9 +283,7 @@ protected void InvokeClientRpc(string methodName, params object[] methodParams)
286283
writer.WriteULong(hash);
287284

288285
for (int i = 0; i < methodParams.Length; i++)
289-
{
290286
FieldTypeHelper.WriteFieldType(writer, methodParams[i]);
291-
}
292287
InternalMessageHandler.Send("MLAPI_RPC", messageChannelName[methodName], writer, networkId);
293288
}
294289
}
@@ -323,9 +318,7 @@ protected void InvokeTargetRpc(string methodName, params object[] methodParams)
323318
writer.WriteUShort(networkedObject.GetOrderIndex(this));
324319
writer.WriteULong(hash);
325320
for (int i = 0; i < methodParams.Length; i++)
326-
{
327321
FieldTypeHelper.WriteFieldType(writer, methodParams[i]);
328-
}
329322
InternalMessageHandler.Send(ownerClientId, "MLAPI_RPC", messageChannelName[methodName], writer, networkId);
330323
}
331324
}
@@ -484,7 +477,7 @@ internal void SyncVarInit()
484477
Dirty = false,
485478
Target = attribute.target,
486479
FieldInfo = sortedFields[i],
487-
FieldValue = sortedFields[i].GetValue(this),
480+
FieldValue = FieldTypeHelper.GetReferenceArrayValue(sortedFields[i].GetValue(this), null),
488481
HookMethod = hookMethod,
489482
Attribute = attribute
490483
});
@@ -530,7 +523,7 @@ internal void FlushSyncedVarsToClient(uint clientId)
530523
writer.WriteBool(mask[i]);
531524
if (syncedVarFields[i].Target && clientId != ownerClientId)
532525
continue;
533-
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this));
526+
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this), null);
534527
}
535528
bool observed = InternalMessageHandler.Send(clientId, "MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", writer, networkId);
536529
if (observed)
@@ -591,8 +584,8 @@ internal void SyncVarUpdate()
591584
//Writes all the indexes of the dirty syncvars.
592585
if (syncedVarFields[i].Dirty == true)
593586
{
594-
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this));
595-
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
587+
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue);
588+
syncedVarFields[i].FieldValue = FieldTypeHelper.GetReferenceArrayValue(syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue);
596589
syncedVarFields[i].Dirty = false;
597590
}
598591
}
@@ -623,11 +616,11 @@ internal void SyncVarUpdate()
623616
//Writes all the indexes of the dirty syncvars.
624617
if (syncedVarFields[i].Dirty == true)
625618
{
626-
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this));
619+
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue);
627620
if (nonTargetDirtyCount == 0)
628621
{
629622
//Only targeted SyncedVars were changed. Thus we need to set them as non dirty here since it wont be done by the next loop.
630-
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
623+
syncedVarFields[i].FieldValue = FieldTypeHelper.GetReferenceArrayValue(syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue);
631624
syncedVarFields[i].Dirty = false;
632625
}
633626
}
@@ -656,8 +649,8 @@ internal void SyncVarUpdate()
656649
//Writes all the indexes of the dirty syncvars.
657650
if (syncedVarFields[i].Dirty == true && !syncedVarFields[i].Target)
658651
{
659-
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this));
660-
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
652+
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue);
653+
syncedVarFields[i].FieldValue = FieldTypeHelper.GetReferenceArrayValue(syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue);
661654
syncedVarFields[i].Dirty = false;
662655
}
663656
}
@@ -682,7 +675,7 @@ private bool SetDirtyness()
682675
if (NetworkingManager.singleton.NetworkTime - syncedVarFields[i].Attribute.lastSyncTime < syncedVarFields[i].Attribute.syncDelay)
683676
continue;
684677
//Big TODO. This will return true for reference objects. This NEEDS to be fixed. a better compare
685-
if (!FieldTypeHelper.ObjectEqual(syncedVarFields[i].FieldInfo.GetValue(this).GetHashCode(), syncedVarFields[i].FieldValue))
678+
if (!FieldTypeHelper.ObjectEqual(syncedVarFields[i].FieldInfo.GetValue(this), syncedVarFields[i].FieldValue))
686679
{
687680
syncedVarFields[i].Dirty = true; //This fields value is out of sync!
688681
syncedVarFields[i].Attribute.lastSyncTime = NetworkingManager.singleton.NetworkTime;

MLAPI/MonoBehaviours/Core/NetworkedObject.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,7 @@ internal void WriteFormattedSyncedVarData(BitWriter writer)
324324
continue;
325325
writer.WriteUShort(GetOrderIndex(childNetworkedBehaviours[i])); //Write the behaviourId
326326
for (int j = 0; j < childNetworkedBehaviours[i].syncedVarFields.Count; j++)
327-
{
328327
FieldTypeHelper.WriteFieldType(writer, childNetworkedBehaviours[i].syncedVarFields[j].FieldValue);
329-
}
330328
}
331329
}
332330

MLAPI/NetworkingManagerComponents/Binary/BinarySerializer.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ public static byte[] Serialize<T>(T instance)
7474
using (BitReader reader = BitReader.Get(binary))
7575
{
7676
for (int i = 0; i < sortedFields.Length; i++)
77-
{
7877
sortedFields[i].SetValue(instance, FieldTypeHelper.ReadFieldType(reader, sortedFields[i].FieldType));
79-
}
8078
return instance;
8179
}
8280
}
@@ -120,9 +118,7 @@ internal static void Serialize(object instance, BitWriter writer)
120118
cachedFields.Add(instance.GetType().FullName, sortedFields);
121119
}
122120
for (int i = 0; i < sortedFields.Length; i++)
123-
{
124121
FieldTypeHelper.WriteFieldType(writer, sortedFields[i].GetValue(instance));
125-
}
126122
}
127123

128124
internal static object Deserialize(BitReader reader, Type type)

MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ internal static void HandleSyncVarUpdate(uint clientId, BitReader reader, int ch
251251
{
252252
if (!reader.ReadBool())
253253
continue;
254-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(FieldTypeHelper.ReadFieldType(reader,
255-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields[i].FieldInfo.FieldType), i);
254+
SyncedVarField field = SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields[i];
255+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(FieldTypeHelper.ReadFieldType(reader,
256+
field.FieldInfo.FieldType, ref field.FieldValue), i);
256257
}
257258
}
258259

0 commit comments

Comments
 (0)