Fix #372, call syncvar hook for spawn (#410)

* Fix #372, call syncvar hook for spawn

* Rebuilt the weaver with the changes
This commit is contained in:
Paul Pacheco 2019-02-18 06:07:36 -06:00 committed by vis2k
parent b7ef2b3521
commit dfd0e02125
2 changed files with 75 additions and 99 deletions

View File

@ -445,108 +445,8 @@ public static int GetChannelId(CustomAttribute ca)
return 0; return 0;
} }
void GenerateDeSerialization() void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker)
{ {
Weaver.DLog(m_td, " GenerateDeSerialization");
foreach (MethodDefinition m in m_td.Methods)
{
if (m.Name == "OnDeserialize")
return;
}
if (m_SyncVars.Count == 0)
{
// no synvars, no need for custom OnDeserialize
return;
}
MethodDefinition serialize = new MethodDefinition("OnDeserialize",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
Weaver.voidType);
serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType));
ILProcessor serWorker = serialize.Body.GetILProcessor();
MethodReference baseDeserialize = Resolvers.ResolveMethodInParents(m_td.BaseType, Weaver.scriptDef, "OnDeserialize");
if (baseDeserialize != null)
{
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // reader
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // initialState
serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize));
}
// Generates: if (initialState);
Instruction initialStateLabel = serWorker.Create(OpCodes.Nop);
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));
foreach (FieldDefinition syncVar in m_SyncVars)
{
// assign value
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
{
// GameObject/NetworkIdentity SyncVar:
// OnSerialize sends writer.Write(go);
// OnDeserialize reads to __netId manually so we can use
// lookups in the getter (so it still works if objects
// move in and out of range repeatedly)
FieldDefinition netIdField = m_SyncVarNetIds[syncVar];
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
}
else
{
MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType);
if (readFunc != null)
{
serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
}
else
{
Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types.");
Weaver.fail = true;
return;
}
serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
}
}
serWorker.Append(serWorker.Create(OpCodes.Ret));
// Generates: end if (initialState);
serWorker.Append(initialStateLabel);
// setup local for dirty bits
serialize.Body.InitLocals = true;
VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int64Type);
serialize.Body.Variables.Add(dirtyBitsLocal);
// get dirty bits
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked64));
serWorker.Append(serWorker.Create(OpCodes.Stloc_0));
// conditionally read each syncvar
int dirtyBit = Weaver.GetSyncVarStart(m_td.BaseType.FullName); // start at number of syncvars in parent
foreach (FieldDefinition syncVar in m_SyncVars)
{
Instruction varLabel = serWorker.Create(OpCodes.Nop);
// check if dirty bit is set
serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit));
serWorker.Append(serWorker.Create(OpCodes.And));
serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));
// check for Hook function // check for Hook function
MethodDefinition foundMethod; MethodDefinition foundMethod;
if (!SyncVarProcessor.CheckForHookFunction(m_td, syncVar, out foundMethod)) if (!SyncVarProcessor.CheckForHookFunction(m_td, syncVar, out foundMethod))
@ -615,6 +515,82 @@ void GenerateDeSerialization()
serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod)); serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
} }
} }
}
void GenerateDeSerialization()
{
Weaver.DLog(m_td, " GenerateDeSerialization");
foreach (MethodDefinition m in m_td.Methods)
{
if (m.Name == "OnDeserialize")
return;
}
if (m_SyncVars.Count == 0)
{
// no synvars, no need for custom OnDeserialize
return;
}
MethodDefinition serialize = new MethodDefinition("OnDeserialize",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
Weaver.voidType);
serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType));
ILProcessor serWorker = serialize.Body.GetILProcessor();
MethodReference baseDeserialize = Resolvers.ResolveMethodInParents(m_td.BaseType, Weaver.scriptDef, "OnDeserialize");
if (baseDeserialize != null)
{
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // reader
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // initialState
serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize));
}
// Generates: if (initialState);
Instruction initialStateLabel = serWorker.Create(OpCodes.Nop);
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));
foreach (FieldDefinition syncVar in m_SyncVars)
{
DeserializeField(syncVar, serWorker);
}
serWorker.Append(serWorker.Create(OpCodes.Ret));
// Generates: end if (initialState);
serWorker.Append(initialStateLabel);
// setup local for dirty bits
serialize.Body.InitLocals = true;
VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int64Type);
serialize.Body.Variables.Add(dirtyBitsLocal);
// get dirty bits
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked64));
serWorker.Append(serWorker.Create(OpCodes.Stloc_0));
// conditionally read each syncvar
int dirtyBit = Weaver.GetSyncVarStart(m_td.BaseType.FullName); // start at number of syncvars in parent
foreach (FieldDefinition syncVar in m_SyncVars)
{
Instruction varLabel = serWorker.Create(OpCodes.Nop);
// check if dirty bit is set
serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit));
serWorker.Append(serWorker.Create(OpCodes.And));
serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));
DeserializeField(syncVar, serWorker);
serWorker.Append(varLabel); serWorker.Append(varLabel);
dirtyBit += 1; dirtyBit += 1;
} }