Skip to content

Commit

Permalink
fix: don't call hook in host if no change, fixes #1142 (#1143)
Browse files Browse the repository at this point in the history
* fix: don't call hook in host if no change,  fixes #1142

* Update Assets/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs

Co-Authored-By: MrGadget <chris@clevertech.net>

* avoid hook calls for GO and NI in host

* Update Assets/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs

* Remove check from SetSyncVarGameObject
  • Loading branch information
paulpach authored and miwarnec committed Oct 17, 2019
1 parent 34c419e commit d8ce80f
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 23 deletions.
40 changes: 40 additions & 0 deletions Assets/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,44 @@ public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinit

ILProcessor setWorker = set.Body.GetILProcessor();


// if (!SyncVarEqual(value, ref playerData))
Instruction endOfMethod = setWorker.Create(OpCodes.Nop);

// this
setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
// new value to set
setWorker.Append(setWorker.Create(OpCodes.Ldarg_1));
// reference to field to set
// make generic version of SetSyncVar with field type
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
{
// reference to netId Field to set
setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
setWorker.Append(setWorker.Create(OpCodes.Ldfld, netFieldId));

setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.syncVarGameObjectEqualReference));
}
else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
{
// reference to netId Field to set
setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
setWorker.Append(setWorker.Create(OpCodes.Ldfld, netFieldId));

setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.syncVarNetworkIdentityEqualReference));
}
else
{
setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
setWorker.Append(setWorker.Create(OpCodes.Ldflda, fd));

GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
syncVarEqualGm.GenericArguments.Add(fd.FieldType);
setWorker.Append(setWorker.Create(OpCodes.Call, syncVarEqualGm));
}

setWorker.Append(setWorker.Create(OpCodes.Brtrue, endOfMethod));

CheckForHookFunction(td, fd, out MethodDefinition hookFunctionMethod);

if (hookFunctionMethod != null)
Expand Down Expand Up @@ -183,6 +221,8 @@ public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinit
setWorker.Append(setWorker.Create(OpCodes.Call, gm));
}

setWorker.Append(endOfMethod);

setWorker.Append(setWorker.Create(OpCodes.Ret));

set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType));
Expand Down
6 changes: 6 additions & 0 deletions Assets/Mirror/Editor/Weaver/Weaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class Weaver
public static TypeReference gameObjectType;
public static TypeReference transformType;

public static MethodReference syncVarEqualReference;
public static MethodReference syncVarNetworkIdentityEqualReference;
public static MethodReference syncVarGameObjectEqualReference;
public static MethodReference setSyncVarReference;
public static MethodReference setSyncVarHookGuard;
public static MethodReference getSyncVarHookGuard;
Expand Down Expand Up @@ -286,6 +289,9 @@ static void SetupTargetTypes()
ReadyConnectionReference = Resolvers.ResolveMethod(ClientSceneType, CurrentAssembly, "get_readyConnection");

getBehaviourIsServer = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "get_isServer");
syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SyncVarEqual");
syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SyncVarNetworkIdentityEqual");
syncVarGameObjectEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SyncVarGameObjectEqual");
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SetSyncVar");
setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "setSyncVarHookGuard");
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "getSyncVarHookGuard");
Expand Down
83 changes: 60 additions & 23 deletions Assets/Mirror/Runtime/NetworkBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,29 @@ public static CmdDelegate GetRpcHandler(int cmdHash)
#endregion

#region Helpers

// helper function for [SyncVar] GameObjects.
[EditorBrowsable(EditorBrowsableState.Never)]
protected bool SyncVarGameObjectEqual(GameObject newGameObject, uint netIdField)
{
uint newNetId = 0;
if (newGameObject != null)
{
NetworkIdentity identity = newGameObject.GetComponent<NetworkIdentity>();
if (identity != null)
{
newNetId = identity.netId;
if (newNetId == 0)
{
Debug.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
}
}
}

return newNetId == netIdField;
}


// helper function for [SyncVar] GameObjects.
[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, ulong dirtyBit, ref uint netIdField)
Expand All @@ -479,14 +502,10 @@ protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gam
}
}

// netId changed?
if (newNetId != netIdField)
{
if (LogFilter.Debug) Debug.Log("SetSyncVar GameObject " + GetType().Name + " bit [" + dirtyBit + "] netfieldId:" + netIdField + "->" + newNetId);
SetDirtyBit(dirtyBit);
gameObjectField = newGameObject; // assign new one on the server, and in case we ever need it on client too
netIdField = newNetId;
}
if (LogFilter.Debug) Debug.Log("SetSyncVar GameObject " + GetType().Name + " bit [" + dirtyBit + "] netfieldId:" + netIdField + "->" + newNetId);
SetDirtyBit(dirtyBit);
gameObjectField = newGameObject; // assign new one on the server, and in case we ever need it on client too
netIdField = newNetId;
}

// helper function for [SyncVar] GameObjects.
Expand All @@ -507,6 +526,25 @@ protected GameObject GetSyncVarGameObject(uint netId, ref GameObject gameObjectF
return null;
}


// helper function for [SyncVar] NetworkIdentities.
[EditorBrowsable(EditorBrowsableState.Never)]
protected bool SyncVarNetworkIdentityEqual(NetworkIdentity newIdentity, uint netIdField)
{
uint newNetId = 0;
if (newIdentity != null)
{
newNetId = newIdentity.netId;
if (newNetId == 0)
{
Debug.LogWarning("SetSyncVarNetworkIdentity NetworkIdentity " + newIdentity + " has a zero netId. Maybe it is not spawned yet?");
}
}

// netId changed?
return newNetId == netIdField;
}

// helper function for [SyncVar] NetworkIdentities.
[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref NetworkIdentity identityField, ulong dirtyBit, ref uint netIdField)
Expand All @@ -524,14 +562,10 @@ protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref Networ
}
}

// netId changed?
if (newNetId != netIdField)
{
if (LogFilter.Debug) Debug.Log("SetSyncVarNetworkIdentity NetworkIdentity " + GetType().Name + " bit [" + dirtyBit + "] netIdField:" + netIdField + "->" + newNetId);
SetDirtyBit(dirtyBit);
netIdField = newNetId;
identityField = newIdentity; // assign new one on the server, and in case we ever need it on client too
}
if (LogFilter.Debug) Debug.Log("SetSyncVarNetworkIdentity NetworkIdentity " + GetType().Name + " bit [" + dirtyBit + "] netIdField:" + netIdField + "->" + newNetId);
SetDirtyBit(dirtyBit);
netIdField = newNetId;
identityField = newIdentity; // assign new one on the server, and in case we ever need it on client too
}

// helper function for [SyncVar] NetworkIdentities.
Expand All @@ -552,15 +586,18 @@ protected NetworkIdentity GetSyncVarNetworkIdentity(uint netId, ref NetworkIdent
}

[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVar<T>(T value, ref T fieldValue, ulong dirtyBit)
protected bool SyncVarEqual<T>(T value, ref T fieldValue)
{
// newly initialized or changed value?
if (!EqualityComparer<T>.Default.Equals(value, fieldValue))
{
if (LogFilter.Debug) Debug.Log("SetSyncVar " + GetType().Name + " bit [" + dirtyBit + "] " + fieldValue + "->" + value);
SetDirtyBit(dirtyBit);
fieldValue = value;
}
return EqualityComparer<T>.Default.Equals(value, fieldValue);
}

[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVar<T>(T value, ref T fieldValue, ulong dirtyBit)
{
if (LogFilter.Debug) Debug.Log("SetSyncVar " + GetType().Name + " bit [" + dirtyBit + "] " + fieldValue + "->" + value);
SetDirtyBit(dirtyBit);
fieldValue = value;
}
#endregion

Expand Down

0 comments on commit d8ce80f

Please sign in to comment.