Added Targeted SyncedVars that only sync to the owner of a object

This commit is contained in:
Albin Corén 2018-04-17 19:37:12 +02:00
parent c96634f797
commit 1838808860
5 changed files with 544 additions and 247 deletions

View File

@ -12,5 +12,9 @@ namespace MLAPI.Attributes
/// The method name to invoke when the SyncVar get's updated. /// The method name to invoke when the SyncVar get's updated.
/// </summary> /// </summary>
public string hook; public string hook;
/// <summary>
/// If true, the syncedVar will only be synced to the owner.
/// </summary>
public bool target;
} }
} }

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace MLAPI.Data
{
internal class SyncedVarField
{
internal FieldInfo FieldInfo;
internal FieldType FieldType;
internal object FieldValue;
internal MethodInfo HookMethod;
internal bool Dirty;
internal bool Target;
}
}

View File

@ -73,6 +73,7 @@
<Compile Include="Data\NetworkConfig.cs" /> <Compile Include="Data\NetworkConfig.cs" />
<Compile Include="Data\NetworkedPrefab.cs" /> <Compile Include="Data\NetworkedPrefab.cs" />
<Compile Include="Data\NetworkPool.cs" /> <Compile Include="Data\NetworkPool.cs" />
<Compile Include="Data\SyncedVarField.cs" />
<Compile Include="Data\TrackedPointData.cs" /> <Compile Include="Data\TrackedPointData.cs" />
<Compile Include="Data\TransportHost.cs" /> <Compile Include="Data\TransportHost.cs" />
<Compile Include="GlobalSuppressions.cs" /> <Compile Include="GlobalSuppressions.cs" />

View File

@ -202,13 +202,8 @@ namespace MLAPI.MonoBehaviours.Core
} }
#region SYNC_VAR #region SYNC_VAR
private List<FieldInfo> syncedFields = new List<FieldInfo>(); internal List<SyncedVarField> syncedVarFields = new List<SyncedVarField>();
internal List<FieldType> syncedFieldTypes = new List<FieldType>();
private List<object> syncedFieldValues = new List<object>();
private List<MethodInfo> syncedVarHooks = new List<MethodInfo>();
private bool syncVarInit = false; private bool syncVarInit = false;
//A dirty field is a field that's not synced.
private bool[] dirtyFields;
internal void SyncVarInit() internal void SyncVarInit()
{ {
if (syncVarInit) if (syncVarInit)
@ -221,132 +216,214 @@ namespace MLAPI.MonoBehaviours.Core
{ {
object[] syncedVarAttributes = sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true); object[] syncedVarAttributes = sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true);
MethodInfo method = null; MethodInfo method = null;
for (int j = 0; j < syncedVarAttributes.Length; j++) if (!string.IsNullOrEmpty(((SyncedVar)syncedVarAttributes[0]).hook))
{ {
if(!string.IsNullOrEmpty(((SyncedVar)syncedVarAttributes[j]).hook)) method = GetType().GetMethod(((SyncedVar)syncedVarAttributes[0]).hook, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
{ break;
method = GetType().GetMethod(((SyncedVar)syncedVarAttributes[j]).hook, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
break;
}
} }
if (sortedFields[i].FieldType == typeof(bool)) if (sortedFields[i].FieldType == typeof(bool))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Bool); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if(sortedFields[i].FieldType == typeof(byte)) else if(sortedFields[i].FieldType == typeof(byte))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Byte); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(char)) else if (sortedFields[i].FieldType == typeof(char))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Char); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(double)) else if (sortedFields[i].FieldType == typeof(double))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Double); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(float)) else if (sortedFields[i].FieldType == typeof(float))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Single); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(int)) else if (sortedFields[i].FieldType == typeof(int))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Int); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(long)) else if (sortedFields[i].FieldType == typeof(long))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Long); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(sbyte)) else if (sortedFields[i].FieldType == typeof(sbyte))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.SByte); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(short)) else if (sortedFields[i].FieldType == typeof(short))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Short); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(uint)) else if (sortedFields[i].FieldType == typeof(uint))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.UInt); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(ulong)) else if (sortedFields[i].FieldType == typeof(ulong))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.ULong); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(ushort)) else if (sortedFields[i].FieldType == typeof(ushort))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.UShort); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if(sortedFields[i].FieldType == typeof(string)) else if(sortedFields[i].FieldType == typeof(string))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.String); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if(sortedFields[i].FieldType == typeof(Vector3)) else if(sortedFields[i].FieldType == typeof(Vector3))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Vector3); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if(sortedFields[i].FieldType == typeof(Vector2)) else if(sortedFields[i].FieldType == typeof(Vector2))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Vector2); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if (sortedFields[i].FieldType == typeof(Quaternion)) else if (sortedFields[i].FieldType == typeof(Quaternion))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.Quaternion); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else if(sortedFields[i].FieldType == typeof(byte[])) else if(sortedFields[i].FieldType == typeof(byte[]))
{ {
syncedFields.Add(sortedFields[i]); syncedVarFields.Add(new SyncedVarField()
syncedFieldValues.Add(sortedFields[i].GetValue(this)); {
syncedFieldTypes.Add(FieldType.ByteArray); Dirty = false,
syncedVarHooks.Add(method); Target = ((SyncedVar)sortedFields[i].GetCustomAttributes(typeof(SyncedVar), true)[0]).target,
FieldInfo = sortedFields[i],
FieldType = FieldType.Bool,
FieldValue = sortedFields[i].GetValue(this),
HookMethod = method
});
} }
else else
{ {
@ -354,8 +431,7 @@ namespace MLAPI.MonoBehaviours.Core
} }
} }
} }
dirtyFields = new bool[syncedFields.Count]; if (syncedVarFields.Count > 255)
if (dirtyFields.Length > 255)
{ {
Debug.LogError("MLAPI: You can not have more than 255 SyncVar's per NetworkedBehaviour!"); Debug.LogError("MLAPI: You can not have more than 255 SyncVar's per NetworkedBehaviour!");
} }
@ -363,15 +439,15 @@ namespace MLAPI.MonoBehaviours.Core
internal void OnSyncVarUpdate(object value, byte fieldIndex) internal void OnSyncVarUpdate(object value, byte fieldIndex)
{ {
syncedFields[fieldIndex].SetValue(this, value); syncedVarFields[fieldIndex].FieldInfo.SetValue(this, value);
if (syncedVarHooks[fieldIndex] != null) if (syncedVarFields[fieldIndex].HookMethod != null)
syncedVarHooks[fieldIndex].Invoke(this, null); syncedVarFields[fieldIndex].HookMethod.Invoke(this, null);
} }
internal void FlushToClient(uint clientId) internal void FlushToClient(uint clientId)
{ {
//This NetworkedBehaviour has no SyncVars //This NetworkedBehaviour has no SyncVars
if (dirtyFields.Length == 0) if (syncedVarFields.Count == 0)
return; return;
using (MemoryStream stream = new MemoryStream()) using (MemoryStream stream = new MemoryStream())
@ -379,73 +455,85 @@ namespace MLAPI.MonoBehaviours.Core
using (BinaryWriter writer = new BinaryWriter(stream)) using (BinaryWriter writer = new BinaryWriter(stream))
{ {
//Write all indexes //Write all indexes
writer.Write((byte)dirtyFields.Length); int syncCount = 0;
for (int i = 0; i < syncedVarFields.Count; i++)
{
if (!syncedVarFields[i].Target)
syncCount++;
else if (syncedVarFields[i].Target && ownerClientId == clientId)
syncCount++;
}
if (syncCount == 0)
return;
writer.Write((byte)syncCount);
writer.Write(networkId); //NetId writer.Write(networkId); //NetId
writer.Write(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex writer.Write(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
for (byte i = 0; i < dirtyFields.Length; i++) for (byte i = 0; i < syncedVarFields.Count; i++)
{ {
if (syncedVarFields[i].Target && clientId != ownerClientId)
continue;
writer.Write(i); //FieldIndex writer.Write(i); //FieldIndex
switch (syncedFieldTypes[i]) switch (syncedVarFields[i].FieldType)
{ {
case FieldType.Bool: case FieldType.Bool:
writer.Write((bool)syncedFields[i].GetValue(this)); writer.Write((bool)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Byte: case FieldType.Byte:
writer.Write((byte)syncedFields[i].GetValue(this)); writer.Write((byte)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Char: case FieldType.Char:
writer.Write((char)syncedFields[i].GetValue(this)); writer.Write((char)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Double: case FieldType.Double:
writer.Write((double)syncedFields[i].GetValue(this)); writer.Write((double)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Single: case FieldType.Single:
writer.Write((float)syncedFields[i].GetValue(this)); writer.Write((float)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Int: case FieldType.Int:
writer.Write((int)syncedFields[i].GetValue(this)); writer.Write((int)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Long: case FieldType.Long:
writer.Write((long)syncedFields[i].GetValue(this)); writer.Write((long)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.SByte: case FieldType.SByte:
writer.Write((sbyte)syncedFields[i].GetValue(this)); writer.Write((sbyte)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Short: case FieldType.Short:
writer.Write((short)syncedFields[i].GetValue(this)); writer.Write((short)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.UInt: case FieldType.UInt:
writer.Write((uint)syncedFields[i].GetValue(this)); writer.Write((uint)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.ULong: case FieldType.ULong:
writer.Write((ulong)syncedFields[i].GetValue(this)); writer.Write((ulong)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.UShort: case FieldType.UShort:
writer.Write((ushort)syncedFields[i].GetValue(this)); writer.Write((ushort)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.String: case FieldType.String:
writer.Write((string)syncedFields[i].GetValue(this)); writer.Write((string)syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
case FieldType.Vector3: case FieldType.Vector3:
Vector3 vector3 = (Vector3)syncedFields[i].GetValue(this); Vector3 vector3 = (Vector3)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector3.x); writer.Write(vector3.x);
writer.Write(vector3.y); writer.Write(vector3.y);
writer.Write(vector3.z); writer.Write(vector3.z);
break; break;
case FieldType.Vector2: case FieldType.Vector2:
Vector2 vector2 = (Vector2)syncedFields[i].GetValue(this); Vector2 vector2 = (Vector2)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector2.x); writer.Write(vector2.x);
writer.Write(vector2.y); writer.Write(vector2.y);
break; break;
case FieldType.Quaternion: case FieldType.Quaternion:
Vector3 euler = ((Quaternion)syncedFields[i].GetValue(this)).eulerAngles; Vector3 euler = ((Quaternion)syncedVarFields[i].FieldInfo.GetValue(this)).eulerAngles;
writer.Write(euler.x); writer.Write(euler.x);
writer.Write(euler.y); writer.Write(euler.y);
writer.Write(euler.z); writer.Write(euler.z);
break; break;
case FieldType.ByteArray: case FieldType.ByteArray:
writer.Write((ushort)((byte[])syncedFields[i].GetValue(this)).Length); writer.Write((ushort)((byte[])syncedVarFields[i].FieldInfo.GetValue(this)).Length);
writer.Write((byte[])syncedFields[i].GetValue(this)); writer.Write((byte[])syncedVarFields[i].FieldInfo.GetValue(this));
break; break;
} }
} }
@ -462,100 +550,286 @@ namespace MLAPI.MonoBehaviours.Core
SetDirtyness(); SetDirtyness();
if(NetworkingManager.singleton.NetworkTime - lastSyncTime >= SyncVarSyncDelay) if(NetworkingManager.singleton.NetworkTime - lastSyncTime >= SyncVarSyncDelay)
{ {
byte dirtyCount = 0; byte nonTargetDirtyCount = 0;
for (byte i = 0; i < dirtyFields.Length; i++) byte totalDirtyCount = 0;
byte dirtyTargets = 0;
for (byte i = 0; i < syncedVarFields.Count; i++)
{ {
if (dirtyFields[i]) if (syncedVarFields[i].Dirty)
dirtyCount++; totalDirtyCount++;
if (syncedVarFields[i].Target && syncedVarFields[i].Dirty)
dirtyTargets++;
if (syncedVarFields[i].Dirty && !syncedVarFields[i].Target)
nonTargetDirtyCount++;
} }
if (dirtyCount == 0) if (totalDirtyCount == 0)
return; //All up to date! return; //All up to date!
//It's sync time!
using (MemoryStream stream = new MemoryStream())
{
using(BinaryWriter writer = new BinaryWriter(stream))
{
//Write all indexes
writer.Write(dirtyCount);
writer.Write(networkId); //NetId
writer.Write(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
for (byte i = 0; i < dirtyFields.Length; i++)
{
//Writes all the indexes of the dirty syncvars.
if (dirtyFields[i] == true)
{
writer.Write(i); //FieldIndex
switch (syncedFieldTypes[i])
{
case FieldType.Bool:
writer.Write((bool)syncedFields[i].GetValue(this));
break;
case FieldType.Byte:
writer.Write((byte)syncedFields[i].GetValue(this));
break;
case FieldType.Char:
writer.Write((char)syncedFields[i].GetValue(this));
break;
case FieldType.Double:
writer.Write((double)syncedFields[i].GetValue(this));
break;
case FieldType.Single:
writer.Write((float)syncedFields[i].GetValue(this));
break;
case FieldType.Int:
writer.Write((int)syncedFields[i].GetValue(this));
break;
case FieldType.Long:
writer.Write((long)syncedFields[i].GetValue(this));
break;
case FieldType.SByte:
writer.Write((sbyte)syncedFields[i].GetValue(this));
break;
case FieldType.Short:
writer.Write((short)syncedFields[i].GetValue(this));
break;
case FieldType.UInt:
writer.Write((uint)syncedFields[i].GetValue(this));
break;
case FieldType.ULong:
writer.Write((ulong)syncedFields[i].GetValue(this));
break;
case FieldType.UShort:
writer.Write((ushort)syncedFields[i].GetValue(this));
break;
case FieldType.String:
writer.Write((string)syncedFields[i].GetValue(this));
break;
case FieldType.Vector3:
Vector3 vector3 = (Vector3)syncedFields[i].GetValue(this);
writer.Write(vector3.x);
writer.Write(vector3.y);
writer.Write(vector3.z);
break;
case FieldType.Vector2:
Vector2 vector2 = (Vector2)syncedFields[i].GetValue(this);
writer.Write(vector2.x);
writer.Write(vector2.y);
break;
case FieldType.Quaternion:
Vector3 euler = ((Quaternion)syncedFields[i].GetValue(this)).eulerAngles;
writer.Write(euler.x);
writer.Write(euler.y);
writer.Write(euler.z);
break;
case FieldType.ByteArray:
writer.Write((ushort)((byte[])syncedFields[i].GetValue(this)).Length);
writer.Write((byte[])syncedFields[i].GetValue(this));
break;
// If we don't have targets. We can send one big message,
// thus only serializing it once. Otherwise, we have to create two messages. One for the non targets and one for the target
if (dirtyTargets == 0)
{
//It's sync time!
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
//Write all indexes
writer.Write(totalDirtyCount);
writer.Write(networkId); //NetId
writer.Write(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
for (byte i = 0; i < syncedVarFields.Count; i++)
{
//Writes all the indexes of the dirty syncvars.
if (syncedVarFields[i].Dirty == true)
{
writer.Write(i); //FieldIndex
switch (syncedVarFields[i].FieldType)
{
case FieldType.Bool:
writer.Write((bool)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Byte:
writer.Write((byte)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Char:
writer.Write((char)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Double:
writer.Write((double)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Single:
writer.Write((float)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Int:
writer.Write((int)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Long:
writer.Write((long)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.SByte:
writer.Write((sbyte)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Short:
writer.Write((short)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.UInt:
writer.Write((uint)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.ULong:
writer.Write((ulong)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.UShort:
writer.Write((ushort)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.String:
writer.Write((string)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Vector3:
Vector3 vector3 = (Vector3)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector3.x);
writer.Write(vector3.y);
writer.Write(vector3.z);
break;
case FieldType.Vector2:
Vector2 vector2 = (Vector2)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector2.x);
writer.Write(vector2.y);
break;
case FieldType.Quaternion:
Vector3 euler = ((Quaternion)syncedVarFields[i].FieldInfo.GetValue(this)).eulerAngles;
writer.Write(euler.x);
writer.Write(euler.y);
writer.Write(euler.z);
break;
case FieldType.ByteArray:
writer.Write((ushort)((byte[])syncedVarFields[i].FieldInfo.GetValue(this)).Length);
writer.Write((byte[])syncedVarFields[i].FieldInfo.GetValue(this));
break;
}
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
syncedVarFields[i].Dirty = false;
} }
syncedFieldValues[i] = syncedFields[i].GetValue(this);
dirtyFields[i] = false;
} }
} }
InternalMessageHandler.Send("MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", stream.ToArray());
}
}
else
{
//It's sync time. This is the target receivers packet.
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
//Write all indexes
writer.Write(totalDirtyCount);
writer.Write(networkId); //NetId
writer.Write(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
for (byte i = 0; i < syncedVarFields.Count; i++)
{
//Writes all the indexes of the dirty syncvars.
if (syncedVarFields[i].Dirty == true)
{
writer.Write(i); //FieldIndex
switch (syncedVarFields[i].FieldType)
{
case FieldType.Bool:
writer.Write((bool)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Byte:
writer.Write((byte)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Char:
writer.Write((char)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Double:
writer.Write((double)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Single:
writer.Write((float)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Int:
writer.Write((int)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Long:
writer.Write((long)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.SByte:
writer.Write((sbyte)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Short:
writer.Write((short)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.UInt:
writer.Write((uint)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.ULong:
writer.Write((ulong)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.UShort:
writer.Write((ushort)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.String:
writer.Write((string)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Vector3:
Vector3 vector3 = (Vector3)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector3.x);
writer.Write(vector3.y);
writer.Write(vector3.z);
break;
case FieldType.Vector2:
Vector2 vector2 = (Vector2)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector2.x);
writer.Write(vector2.y);
break;
case FieldType.Quaternion:
Vector3 euler = ((Quaternion)syncedVarFields[i].FieldInfo.GetValue(this)).eulerAngles;
writer.Write(euler.x);
writer.Write(euler.y);
writer.Write(euler.z);
break;
case FieldType.ByteArray:
writer.Write((ushort)((byte[])syncedVarFields[i].FieldInfo.GetValue(this)).Length);
writer.Write((byte[])syncedVarFields[i].FieldInfo.GetValue(this));
break;
}
}
}
}
InternalMessageHandler.Send(ownerClientId, "MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", stream.ToArray()); //Send only to target
}
//It's sync time. This is the NON target receivers packet.
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
//Write all indexes
writer.Write(nonTargetDirtyCount);
writer.Write(networkId); //NetId
writer.Write(networkedObject.GetOrderIndex(this)); //Behaviour OrderIndex
for (byte i = 0; i < syncedVarFields.Count; i++)
{
//Writes all the indexes of the dirty syncvars.
if (syncedVarFields[i].Dirty == true && !syncedVarFields[i].Target)
{
writer.Write(i); //FieldIndex
switch (syncedVarFields[i].FieldType)
{
case FieldType.Bool:
writer.Write((bool)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Byte:
writer.Write((byte)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Char:
writer.Write((char)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Double:
writer.Write((double)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Single:
writer.Write((float)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Int:
writer.Write((int)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Long:
writer.Write((long)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.SByte:
writer.Write((sbyte)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Short:
writer.Write((short)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.UInt:
writer.Write((uint)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.ULong:
writer.Write((ulong)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.UShort:
writer.Write((ushort)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.String:
writer.Write((string)syncedVarFields[i].FieldInfo.GetValue(this));
break;
case FieldType.Vector3:
Vector3 vector3 = (Vector3)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector3.x);
writer.Write(vector3.y);
writer.Write(vector3.z);
break;
case FieldType.Vector2:
Vector2 vector2 = (Vector2)syncedVarFields[i].FieldInfo.GetValue(this);
writer.Write(vector2.x);
writer.Write(vector2.y);
break;
case FieldType.Quaternion:
Vector3 euler = ((Quaternion)syncedVarFields[i].FieldInfo.GetValue(this)).eulerAngles;
writer.Write(euler.x);
writer.Write(euler.y);
writer.Write(euler.z);
break;
case FieldType.ByteArray:
writer.Write((ushort)((byte[])syncedVarFields[i].FieldInfo.GetValue(this)).Length);
writer.Write((byte[])syncedVarFields[i].FieldInfo.GetValue(this));
break;
}
syncedVarFields[i].FieldValue = syncedVarFields[i].FieldInfo.GetValue(this);
syncedVarFields[i].Dirty = false;
}
}
}
InternalMessageHandler.Send("MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", stream.ToArray(), ownerClientId); // Send to everyone except target.
} }
InternalMessageHandler.Send("MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", stream.ToArray());
} }
lastSyncTime = NetworkingManager.singleton.NetworkTime; lastSyncTime = NetworkingManager.singleton.NetworkTime;
} }
@ -565,111 +839,111 @@ namespace MLAPI.MonoBehaviours.Core
{ {
if (!isServer) if (!isServer)
return; return;
for (int i = 0; i < syncedFields.Count; i++) for (int i = 0; i < syncedVarFields.Count; i++)
{ {
switch (syncedFieldTypes[i]) switch (syncedVarFields[i].FieldType)
{ {
case FieldType.Bool: case FieldType.Bool:
if ((bool)syncedFields[i].GetValue(this) != (bool)syncedFieldValues[i]) if ((bool)syncedVarFields[i].FieldInfo.GetValue(this) != (bool)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Byte: case FieldType.Byte:
if ((byte)syncedFields[i].GetValue(this) != (byte)syncedFieldValues[i]) if ((byte)syncedVarFields[i].FieldInfo.GetValue(this) != (byte)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Char: case FieldType.Char:
if ((char)syncedFields[i].GetValue(this) != (char)syncedFieldValues[i]) if ((char)syncedVarFields[i].FieldInfo.GetValue(this) != (char)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Double: case FieldType.Double:
if ((double)syncedFields[i].GetValue(this) != (double)syncedFieldValues[i]) if ((double)syncedVarFields[i].FieldInfo.GetValue(this) != (double)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Single: case FieldType.Single:
if ((float)syncedFields[i].GetValue(this) != (float)syncedFieldValues[i]) if ((float)syncedVarFields[i].FieldInfo.GetValue(this) != (float)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Int: case FieldType.Int:
if ((int)syncedFields[i].GetValue(this) != (int)syncedFieldValues[i]) if ((int)syncedVarFields[i].FieldInfo.GetValue(this) != (int)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Long: case FieldType.Long:
if ((long)syncedFields[i].GetValue(this) != (long)syncedFieldValues[i]) if ((long)syncedVarFields[i].FieldInfo.GetValue(this) != (long)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.SByte: case FieldType.SByte:
if ((sbyte)syncedFields[i].GetValue(this) != (sbyte)syncedFieldValues[i]) if ((sbyte)syncedVarFields[i].FieldInfo.GetValue(this) != (sbyte)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Short: case FieldType.Short:
if ((short)syncedFields[i].GetValue(this) != (short)syncedFieldValues[i]) if ((short)syncedVarFields[i].FieldInfo.GetValue(this) != (short)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.UInt: case FieldType.UInt:
if ((uint)syncedFields[i].GetValue(this) != (uint)syncedFieldValues[i]) if ((uint)syncedVarFields[i].FieldInfo.GetValue(this) != (uint)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.ULong: case FieldType.ULong:
if ((ulong)syncedFields[i].GetValue(this) != (ulong)syncedFieldValues[i]) if ((ulong)syncedVarFields[i].FieldInfo.GetValue(this) != (ulong)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.UShort: case FieldType.UShort:
if ((ushort)syncedFields[i].GetValue(this) != (ushort)syncedFieldValues[i]) if ((ushort)syncedVarFields[i].FieldInfo.GetValue(this) != (ushort)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.String: case FieldType.String:
if ((string)syncedFields[i].GetValue(this) != (string)syncedFieldValues[i]) if ((string)syncedVarFields[i].FieldInfo.GetValue(this) != (string)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Vector3: case FieldType.Vector3:
if ((Vector3)syncedFields[i].GetValue(this) != (Vector3)syncedFieldValues[i]) if ((Vector3)syncedVarFields[i].FieldInfo.GetValue(this) != (Vector3)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Vector2: case FieldType.Vector2:
if ((Vector2)syncedFields[i].GetValue(this) != (Vector2)syncedFieldValues[i]) if ((Vector2)syncedVarFields[i].FieldInfo.GetValue(this) != (Vector2)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.Quaternion: case FieldType.Quaternion:
if ((Quaternion)syncedFields[i].GetValue(this) != (Quaternion)syncedFieldValues[i]) if ((Quaternion)syncedVarFields[i].FieldInfo.GetValue(this) != (Quaternion)syncedVarFields[i].FieldValue)
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
case FieldType.ByteArray: case FieldType.ByteArray:
if(((byte[])syncedFields[i].GetValue(this)).SequenceEqual(((byte[])syncedFieldValues[i]))) if(((byte[])syncedVarFields[i].FieldInfo.GetValue(this)).SequenceEqual(((byte[])syncedVarFields[i].FieldValue)))
dirtyFields[i] = true; //This fields value is out of sync! syncedVarFields[i].Dirty = true; //This fields value is out of sync!
else else
dirtyFields[i] = false; //Up to date syncedVarFields[i].Dirty = false; //Up to date
break; break;
} }
} }

View File

@ -304,12 +304,12 @@ namespace MLAPI.NetworkingManagerComponents.Core
Debug.LogWarning("MLAPI: Sync message recieved for a non existant behaviour"); Debug.LogWarning("MLAPI: Sync message recieved for a non existant behaviour");
return; return;
} }
else if (fieldIndex > (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedFieldTypes.Count - 1)) else if (fieldIndex > (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields.Count - 1))
{ {
Debug.LogWarning("MLAPI: Sync message recieved for field out of bounds"); Debug.LogWarning("MLAPI: Sync message recieved for field out of bounds");
return; return;
} }
FieldType type = SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedFieldTypes[fieldIndex]; FieldType type = SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedVarFields[fieldIndex].FieldType;
switch (type) switch (type)
{ {
case FieldType.Bool: case FieldType.Bool: