Generate syncOwnerMask in every network behavior

This commit is contained in:
Paul Pacheco 2018-07-28 12:13:00 +02:00
parent 6c80b054ac
commit e7403a8983
3 changed files with 90 additions and 2 deletions

View File

@ -11,10 +11,14 @@ public class NetworkSettingsAttribute : Attribute
public float sendInterval = 0.1f; public float sendInterval = 0.1f;
} }
// SyncTarget enum is cleaner than 'bool onlyToOwner and allows for more options if needed
public enum SyncTarget {Observers, Owner};
[AttributeUsage(AttributeTargets.Field)] [AttributeUsage(AttributeTargets.Field)]
public class SyncVarAttribute : Attribute public class SyncVarAttribute : Attribute
{ {
public string hook; public string hook;
public SyncTarget target = SyncTarget.Observers; // for 'only sync to owner' support
} }
[AttributeUsage(AttributeTargets.Method)] [AttributeUsage(AttributeTargets.Method)]

View File

@ -27,6 +27,10 @@ public class NetworkBehaviour : MonoBehaviour
public short playerControllerId { get { return myView.playerControllerId; } } public short playerControllerId { get { return myView.playerControllerId; } }
protected ulong syncVarDirtyBits { get { return m_SyncVarDirtyBits; } } protected ulong syncVarDirtyBits { get { return m_SyncVarDirtyBits; } }
protected bool syncVarHookGuard { get { return m_SyncVarGuard; } set { m_SyncVarGuard = value; }} protected bool syncVarHookGuard { get { return m_SyncVarGuard; } set { m_SyncVarGuard = value; }}
// determine which variables are SyncToOwner
// to get dirty owners, we do syncVarDirtyBits & syncVarOwnerMask
// by default it is 0 because none of the variables are synctowoner
protected virtual ulong syncVarOwnerMask { get { return 0; } }
internal NetworkIdentity netIdentity { get { return myView; } } internal NetworkIdentity netIdentity { get { return myView; } }

View File

@ -36,6 +36,8 @@ class NetworkBehaviourProcessor
const string k_RpcPrefix = "InvokeRpc"; const string k_RpcPrefix = "InvokeRpc";
const string k_TargetRpcPrefix = "InvokeTargetRpc"; const string k_TargetRpcPrefix = "InvokeTargetRpc";
public enum SyncTarget { Observers, Owner };
public NetworkBehaviourProcessor(TypeDefinition td) public NetworkBehaviourProcessor(TypeDefinition td)
{ {
Weaver.DLog(td, "NetworkBehaviourProcessor"); Weaver.DLog(td, "NetworkBehaviourProcessor");
@ -1902,6 +1904,26 @@ static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string originalNam
return get; return get;
} }
SyncTarget GetSyncVarSyncTarget(FieldDefinition fd)
{
foreach (CustomAttribute attr in fd.CustomAttributes)
{
if (attr.AttributeType.FullName == Weaver.SyncVarType.FullName)
{
foreach (var field in attr.Fields)
{
if (field.Name == "target") // SyncVar.target == SyncTarget.XYZ
{
// SyncTarget enum: 0 == Observers, 1 == Owner
return (SyncTarget)field.Argument.Value;
}
}
}
}
return SyncTarget.Observers;
}
MethodDefinition ProcessSyncVarSet(FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId) MethodDefinition ProcessSyncVarSet(FieldDefinition fd, string originalName, long dirtyBit, FieldDefinition netFieldId)
{ {
//Create the set method //Create the set method
@ -2010,7 +2032,6 @@ void ProcessSyncVar(FieldDefinition fd, long dirtyBit)
{ {
GetMethod = get, SetMethod = set GetMethod = get, SetMethod = set
}; };
//add the methods and property to the type. //add the methods and property to the type.
m_td.Methods.Add(get); m_td.Methods.Add(get);
m_td.Methods.Add(set); m_td.Methods.Add(set);
@ -2075,6 +2096,52 @@ FieldDefinition ProcessSyncList(FieldDefinition fd, long dirtyBit)
Weaver.int32Type); Weaver.int32Type);
} }
void GenerateOwnerMaskProperty(long ownerMask)
{
// no new variables are owners,
// no need to override syncVarOwnerMask
if (ownerMask == 0L)
return;
//Create the get method
MethodDefinition get = new MethodDefinition(
"get_syncVarOwnerMask", MethodAttributes.Family |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig |
MethodAttributes.Virtual,
Weaver.uint64Type);
ILProcessor getWorker = get.Body.GetILProcessor();
// generate: return (0xabc | base.syncVarOwnerMask);
getWorker.Append(getWorker.Create(OpCodes.Ldc_I8, ownerMask)); // 8 byte integer aka long
if (m_td.BaseType.FullName != Weaver.NetworkBehaviourType.FullName)
{
MethodReference baseSerialize = Weaver.ResolveMethod(m_td.BaseType, "get_syncVarOwnerMask");
if (baseSerialize != null)
{
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0)); // base
getWorker.Append(getWorker.Create(OpCodes.Call, baseSerialize));
getWorker.Append(getWorker.Create(OpCodes.Or));
}
}
getWorker.Append(getWorker.Create(OpCodes.Ret));
get.SemanticsAttributes = MethodSemanticsAttributes.Getter;
PropertyDefinition propertyDefinition = new PropertyDefinition("syncVarOwnerMask", PropertyAttributes.None, Weaver.uint64Type)
{
GetMethod = get
};
//add the methods and property to the type.
m_td.Methods.Add(get);
m_td.Properties.Add(propertyDefinition);
}
void ProcessSyncVars() void ProcessSyncVars()
{ {
int numSyncVars = 0; int numSyncVars = 0;
@ -2083,6 +2150,9 @@ void ProcessSyncVars()
// start assigning syncvars at the place the base class stopped, if any // start assigning syncvars at the place the base class stopped, if any
int dirtyBitCounter = Weaver.GetSyncVarStart(m_td.BaseType.FullName); int dirtyBitCounter = Weaver.GetSyncVarStart(m_td.BaseType.FullName);
// mask that determines which of these bits are sync to owner
long ownerMask = 0;
m_SyncVarNetIds.Clear(); m_SyncVarNetIds.Clear();
List<FieldDefinition> listFields = new List<FieldDefinition>(); List<FieldDefinition> listFields = new List<FieldDefinition>();
@ -2150,9 +2220,17 @@ void ProcessSyncVars()
return; return;
} }
// at this point this is either a list or a syncvar and has
// the [SyncVar] attribute. Check if it is SyncToOwner
// and adjust the mask
if (GetSyncVarSyncTarget(fd) == SyncTarget.Owner)
{
ownerMask |= 1L << dirtyBitCounter;
}
if (Helpers.InheritsFromSyncList(fd.FieldType)) if (Helpers.InheritsFromSyncList(fd.FieldType))
{ {
Log.Warning(string.Format("Script class [{0}] has [SyncVar] attribute on SyncList field {1}, SyncLists should not be marked with SyncVar.", m_td.FullName, fd.Name));
break; break;
} }
@ -2219,6 +2297,8 @@ void ProcessSyncVars()
m_td.Methods.Add(func); m_td.Methods.Add(func);
} }
GenerateOwnerMaskProperty(ownerMask);
Weaver.SetNumSyncVars(m_td.FullName, numSyncVars); Weaver.SetNumSyncVars(m_td.FullName, numSyncVars);
} }