Skip to content

Commit

Permalink
fix: Set syncvar variables after calling the hook (#659)
Browse files Browse the repository at this point in the history
Previously, during deserialize,  Mirror either called the hook for a syncvar or it set the variable, but never both. So users had to set the variable inside the hook.

```cs
class Player : NetworkBehaviour {

	[SyncVar(hook=nameof(OnVarChanged))]
	public int myvar;

	public void OnVarChanged(int newvalue) {

		Debug.Log("Got new value " + newvalue);
		Debug.Log("Old value is " + myvar);

		// with this pull request the following line is no longer needed
		// the weaver will do this after the hook finishes
		// this.myvar = newvalue;
	}
}
```

fix: Hook not working with NetworkIdentity or GameObjects

Deserializing NetworkIdentity or GameObjects was broken, it called the hook only if there was no hook,  and it saved the variable only if there was a hook.
  • Loading branch information
paulpach committed Mar 26, 2019
1 parent fac0542 commit 2d63ee1
Showing 1 changed file with 35 additions and 29 deletions.
64 changes: 35 additions & 29 deletions Assets/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ public static int GetChannelId(CustomAttribute ca)
return 0;
}

void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker)
void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker, MethodDefinition deserialize)
{
// check for Hook function
MethodDefinition foundMethod;
Expand All @@ -457,21 +457,21 @@ void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker)
// move in and out of range repeatedly)
FieldDefinition netIdField = m_SyncVarNetIds[syncVar];

if (foundMethod == null)
{
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
}
else
VariableDefinition tmpValue = new VariableDefinition(Weaver.uint32Type);
deserialize.Body.Variables.Add(tmpValue);

// read id and store in a local variable
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkReaderReadPacked32));
serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));

if (foundMethod != null)
{
// call Hook(this.GetSyncVarGameObject/NetworkIdentity(reader.ReadPackedUInt32()))
// because we send/receive the netID, not the GameObject/NetworkIdentity
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this.
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32));
serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
Expand All @@ -480,6 +480,10 @@ void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker)
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarNetworkIdentityReference));
serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
}
// set the netid field
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
}
else
{
Expand All @@ -489,23 +493,25 @@ void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker)
Weaver.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. Mirror [SyncVar] member variables must be basic types.");
return;
}
VariableDefinition tmpValue = new VariableDefinition(syncVar.FieldType);
deserialize.Body.Variables.Add(tmpValue);

if (foundMethod == null)
{
// just assign value
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
}
else
// read value and put it in a local variable
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));

if (foundMethod != null)
{
// call hook instead
// call hook
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
}
// set the property
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
}

}
Expand Down Expand Up @@ -533,6 +539,10 @@ void GenerateDeSerialization()
serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType));
ILProcessor serWorker = serialize.Body.GetILProcessor();
// setup local for dirty bits
serialize.Body.InitLocals = true;
VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int64Type);
serialize.Body.Variables.Add(dirtyBitsLocal);

MethodReference baseDeserialize = Resolvers.ResolveMethodInParents(m_td.BaseType, Weaver.CurrentAssembly, "OnDeserialize");
if (baseDeserialize != null)
Expand All @@ -551,18 +561,14 @@ void GenerateDeSerialization()

foreach (FieldDefinition syncVar in m_SyncVars)
{
DeserializeField(syncVar, serWorker);
DeserializeField(syncVar, serWorker, serialize);
}

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));
Expand All @@ -581,7 +587,7 @@ void GenerateDeSerialization()
serWorker.Append(serWorker.Create(OpCodes.And));
serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));

DeserializeField(syncVar, serWorker);
DeserializeField(syncVar, serWorker, serialize);

serWorker.Append(varLabel);
dirtyBit += 1;
Expand Down

0 comments on commit 2d63ee1

Please sign in to comment.