Skip to content

Commit 35a8ff1

Browse files
committed
Removed SyncedVar limits by reworking field id
1 parent c0cc629 commit 35a8ff1

File tree

2 files changed

+117
-104
lines changed

2 files changed

+117
-104
lines changed

MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using MLAPI.Data;
88
using MLAPI.NetworkingManagerComponents.Binary;
99
using MLAPI.NetworkingManagerComponents.Core;
10+
using System.Collections;
1011

1112
namespace MLAPI.MonoBehaviours.Core
1213
{
@@ -440,13 +441,14 @@ private void OnDestroy()
440441
internal List<SyncedVarField> syncedVarFields = new List<SyncedVarField>();
441442
private HashSet<uint> OutOfSyncClients = new HashSet<uint>();
442443
private bool syncVarInit = false;
444+
internal bool[] syncMask;
443445
internal void SyncVarInit()
444446
{
445447
if (syncVarInit)
446448
return;
447449
syncVarInit = true;
448450
FieldInfo[] sortedFields = GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance).OrderBy(x => x.Name).ToArray();
449-
for (byte i = 0; i < sortedFields.Length; i++)
451+
for (int i = 0; i < sortedFields.Length; i++)
450452
{
451453
if(sortedFields[i].IsDefined(typeof(SyncedVar), true))
452454
{
@@ -477,13 +479,10 @@ internal void SyncVarInit()
477479
}
478480
}
479481
}
480-
if (syncedVarFields.Count > 255)
481-
{
482-
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogError("MLAPI: You can not have more than 255 SyncVar's per NetworkedBehaviour!");
483-
}
482+
syncMask = new bool[syncedVarFields.Count];
484483
}
485484

486-
internal void OnSyncVarUpdate(object value, byte fieldIndex)
485+
internal void OnSyncVarUpdate(object value, int fieldIndex)
487486
{
488487
syncedVarFields[fieldIndex].FieldInfo.SetValue(this, value);
489488
if (syncedVarFields[fieldIndex].HookMethod != null)
@@ -509,14 +508,17 @@ internal void FlushToClient(uint clientId)
509508
}
510509
if (syncCount == 0)
511510
return;
512-
writer.WriteByte((byte)syncCount);
511+
513512
writer.WriteUInt(networkId); //NetId
514513
writer.WriteUShort(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
515-
for (byte i = 0; i < syncedVarFields.Count; i++)
514+
515+
bool[] mask = GetDirtyMask(false, clientId);
516+
for (int i = 0; i < mask.Length; i++) writer.WriteBool(mask[i]);
517+
518+
for (int i = 0; i < syncedVarFields.Count; i++)
516519
{
517520
if (syncedVarFields[i].Target && clientId != ownerClientId)
518521
continue;
519-
writer.WriteByte(i); //FieldIndex
520522
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo, this, syncedVarFields[i].FieldType);
521523
}
522524
bool observed = InternalMessageHandler.Send(clientId, "MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", writer, networkId);
@@ -525,6 +527,16 @@ internal void FlushToClient(uint clientId)
525527
}
526528
}
527529

530+
private ref bool[] GetDirtyMask(bool ignoreTarget, uint? clientId = null)
531+
{
532+
for (int i = 0; i < syncedVarFields.Count; i++)
533+
syncMask[i] = (clientId == null && ignoreTarget && syncedVarFields[i].Dirty && !syncedVarFields[i].Target) ||
534+
(clientId == null && !ignoreTarget && syncedVarFields[i].Dirty) ||
535+
(clientId != null && !syncedVarFields[i].Target) ||
536+
(clientId != null && syncedVarFields[i].Target && ownerClientId == clientId.Value);
537+
return ref syncMask;
538+
}
539+
528540
internal void SyncVarUpdate()
529541
{
530542
if (!syncVarInit)
@@ -533,10 +545,10 @@ internal void SyncVarUpdate()
533545
if (!SetDirtyness())
534546
return;
535547

536-
byte nonTargetDirtyCount = 0;
537-
byte totalDirtyCount = 0;
538-
byte dirtyTargets = 0;
539-
for (byte i = 0; i < syncedVarFields.Count; i++)
548+
int nonTargetDirtyCount = 0;
549+
int totalDirtyCount = 0;
550+
int dirtyTargets = 0;
551+
for (int i = 0; i < syncedVarFields.Count; i++)
540552
{
541553
if (syncedVarFields[i].Dirty)
542554
totalDirtyCount++;
@@ -557,15 +569,17 @@ internal void SyncVarUpdate()
557569
using (BitWriter writer = BitWriter.Get())
558570
{
559571
//Write all indexes
560-
writer.WriteByte(totalDirtyCount);
561572
writer.WriteUInt(networkId); //NetId
562573
writer.WriteUShort(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
563-
for (byte i = 0; i < syncedVarFields.Count; i++)
574+
575+
bool[] mask = GetDirtyMask(false);
576+
for (int i = 0; i < mask.Length; i++) writer.WriteBool(mask[i]);
577+
578+
for (int i = 0; i < syncedVarFields.Count; i++)
564579
{
565580
//Writes all the indexes of the dirty syncvars.
566581
if (syncedVarFields[i].Dirty == true)
567582
{
568-
writer.WriteByte(i); //FieldIndex
569583
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo, this, syncedVarFields[i].FieldType);
570584
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
571585
syncedVarFields[i].Dirty = false;
@@ -587,15 +601,17 @@ internal void SyncVarUpdate()
587601
using (BitWriter writer = BitWriter.Get())
588602
{
589603
//Write all indexes
590-
writer.WriteByte(totalDirtyCount);
591604
writer.WriteUInt(networkId); //NetId
592605
writer.WriteUShort(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
593-
for (byte i = 0; i < syncedVarFields.Count; i++)
606+
607+
bool[] mask = GetDirtyMask(false);
608+
for (int i = 0; i < mask.Length; i++) writer.WriteBool(mask[i]);
609+
610+
for (int i = 0; i < syncedVarFields.Count; i++)
594611
{
595612
//Writes all the indexes of the dirty syncvars.
596613
if (syncedVarFields[i].Dirty == true)
597614
{
598-
writer.WriteByte(i); //FieldIndex
599615
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo, this, syncedVarFields[i].FieldType);
600616
if (nonTargetDirtyCount == 0)
601617
{
@@ -618,15 +634,17 @@ internal void SyncVarUpdate()
618634
using (BitWriter writer = BitWriter.Get())
619635
{
620636
//Write all indexes
621-
writer.WriteByte(nonTargetDirtyCount);
622637
writer.WriteUInt(networkId); //NetId
623638
writer.WriteUShort(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
624-
for (byte i = 0; i < syncedVarFields.Count; i++)
639+
640+
bool[] mask = GetDirtyMask(true);
641+
for (int i = 0; i < mask.Length; i++) writer.WriteBool(mask[i]);
642+
643+
for (int i = 0; i < syncedVarFields.Count; i++)
625644
{
626645
//Writes all the indexes of the dirty syncvars.
627646
if (syncedVarFields[i].Dirty == true && !syncedVarFields[i].Target)
628647
{
629-
writer.WriteByte(i); //FieldIndex
630648
FieldTypeHelper.WriteFieldType(writer, syncedVarFields[i].FieldInfo, this, syncedVarFields[i].FieldType);
631649
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
632650
syncedVarFields[i].Dirty = false;

MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs

Lines changed: 77 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -227,92 +227,87 @@ internal static void HandleChangeOwner(uint clientId, BitReader reader, int chan
227227

228228
internal static void HandleSyncVarUpdate(uint clientId, BitReader reader, int channelId)
229229
{
230-
byte dirtyCount = reader.ReadByte();
231230
uint netId = reader.ReadUInt();
232231
ushort orderIndex = reader.ReadUShort();
233-
if (dirtyCount > 0)
232+
233+
if (!SpawnManager.spawnedObjects.ContainsKey(netId))
234+
{
235+
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Sync message recieved for a non existant object with id: " + netId);
236+
return;
237+
}
238+
else if (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex) == null)
234239
{
235-
for (int i = 0; i < dirtyCount; i++)
240+
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Sync message recieved for a non existant behaviour");
241+
return;
242+
}
243+
244+
for (int i = 0; i < SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields.Count; i++)
245+
{
246+
if (!reader.ReadBool())
247+
continue;
248+
249+
FieldType type = SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields[i].FieldType;
250+
switch (type)
236251
{
237-
byte fieldIndex = reader.ReadByte();
238-
if (!SpawnManager.spawnedObjects.ContainsKey(netId))
239-
{
240-
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Sync message recieved for a non existant object with id: " + netId);
241-
return;
242-
}
243-
else if (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex) == null)
244-
{
245-
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Sync message recieved for a non existant behaviour");
246-
return;
247-
}
248-
else if (fieldIndex > (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields.Count - 1))
249-
{
250-
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Sync message recieved for field out of bounds");
251-
return;
252-
}
253-
FieldType type = SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields[fieldIndex].FieldType;
254-
switch (type)
255-
{
256-
case FieldType.Bool:
257-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadBool(), fieldIndex);
258-
break;
259-
case FieldType.Byte:
260-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadByte(), fieldIndex);
261-
break;
262-
case FieldType.Double:
263-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadDouble(), fieldIndex);
264-
break;
265-
case FieldType.Single:
266-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadFloat(), fieldIndex);
267-
break;
268-
case FieldType.Int:
269-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadInt(), fieldIndex);
270-
break;
271-
case FieldType.Long:
272-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadLong(), fieldIndex);
273-
break;
274-
case FieldType.SByte:
275-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadSByte(), fieldIndex);
276-
break;
277-
case FieldType.Short:
278-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadShort(), fieldIndex);
279-
break;
280-
case FieldType.UInt:
281-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadUInt(), fieldIndex);
282-
break;
283-
case FieldType.ULong:
284-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadULong(), fieldIndex);
285-
break;
286-
case FieldType.UShort:
287-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadUShort(), fieldIndex);
288-
break;
289-
case FieldType.String:
290-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadString(), fieldIndex);
291-
break;
292-
case FieldType.Vector3:
293-
{ //Cases aren't their own scope. Therefor we create a scope for them as they share the X,Y,Z local variables otherwise.
294-
float x = reader.ReadFloat();
295-
float y = reader.ReadFloat();
296-
float z = reader.ReadFloat();
297-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(new Vector3(x, y, z), fieldIndex);
298-
}
299-
break;
300-
case FieldType.Vector2:
301-
{
302-
float x = reader.ReadFloat();
303-
float y = reader.ReadFloat();
304-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(new Vector2(x, y), fieldIndex);
305-
}
306-
break;
307-
case FieldType.Quaternion:
308-
{
309-
float x = reader.ReadFloat();
310-
float y = reader.ReadFloat();
311-
float z = reader.ReadFloat();
312-
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(Quaternion.Euler(x, y, z), fieldIndex);
313-
}
314-
break;
315-
}
252+
case FieldType.Bool:
253+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadBool(), i);
254+
break;
255+
case FieldType.Byte:
256+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadByte(), i);
257+
break;
258+
case FieldType.Double:
259+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadDouble(), i);
260+
break;
261+
case FieldType.Single:
262+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadFloat(), i);
263+
break;
264+
case FieldType.Int:
265+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadInt(), i);
266+
break;
267+
case FieldType.Long:
268+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadLong(), i);
269+
break;
270+
case FieldType.SByte:
271+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadSByte(), i);
272+
break;
273+
case FieldType.Short:
274+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadShort(), i);
275+
break;
276+
case FieldType.UInt:
277+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadUInt(), i);
278+
break;
279+
case FieldType.ULong:
280+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadULong(), i);
281+
break;
282+
case FieldType.UShort:
283+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadUShort(), i);
284+
break;
285+
case FieldType.String:
286+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(reader.ReadString(), i);
287+
break;
288+
case FieldType.Vector3:
289+
{ //Cases aren't their own scope. Therefor we create a scope for them as they share the X,Y,Z local variables otherwise.
290+
float x = reader.ReadFloat();
291+
float y = reader.ReadFloat();
292+
float z = reader.ReadFloat();
293+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(new Vector3(x, y, z), i);
294+
}
295+
break;
296+
case FieldType.Vector2:
297+
{
298+
float x = reader.ReadFloat();
299+
float y = reader.ReadFloat();
300+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(new Vector2(x, y), i);
301+
}
302+
break;
303+
case FieldType.Quaternion:
304+
{
305+
float x = reader.ReadFloat();
306+
float y = reader.ReadFloat();
307+
float z = reader.ReadFloat();
308+
SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).OnSyncVarUpdate(Quaternion.Euler(x, y, z), i);
309+
}
310+
break;
316311
}
317312
}
318313
}

0 commit comments

Comments
 (0)