mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
* fix * Test file * Syntax * NetworkBehaviour.Set/GetSyncVarNetworkIdentity functions added * add definitions to weaver * Use them * add NetworkIdentity cases everywhere else too * ProcessInstructionSetter/GetterField replaces for OnDeserialize too, so that [SyncVar]GameObjects/NetworkIdentities work with custom On(De)Serialize as well * Custom on(De)serialize test * Weaver.ProcessSiteMethod doesn't ignore OnDeserialize anymore either * [SyncVar] GameObject/NetworkIdentity hooks work again * testscene * public gameobject field test * pass gameobject field to getsyncvargameobject etc. * GetSyncVarGameObject/NetworkIdentity always returns the field if server, looks up netId otherwise; functions aren't static anymore. * Use original OnSerialize generation again, so it simply calls writer.Write(go) on server, which sends the netId internally anyway. * fixed hooks not using 'this.' because getter function isn't static anymore. * add scene referencing test * remove tests
This commit is contained in:
parent
3c0ff33c94
commit
43baeff444
@ -276,39 +276,99 @@ internal bool InvokeHandlerDelegate(int cmdHash, UNetInvokeType invokeType, Netw
|
||||
|
||||
// ----------------------------- Helpers --------------------------------
|
||||
|
||||
// helper function for [SyncVar] GameObjects.
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, ulong dirtyBit, ref uint netIdField)
|
||||
{
|
||||
if (m_SyncVarGuard)
|
||||
return;
|
||||
|
||||
uint newGameObjectNetId = 0;
|
||||
uint newNetId = 0;
|
||||
if (newGameObject != null)
|
||||
{
|
||||
NetworkIdentity identity = newGameObject.GetComponent<NetworkIdentity>();
|
||||
if (identity != null)
|
||||
{
|
||||
newGameObjectNetId = identity.netId;
|
||||
if (newGameObjectNetId == 0)
|
||||
newNetId = identity.netId;
|
||||
if (newNetId == 0)
|
||||
{
|
||||
Debug.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint oldGameObjectNetId = 0;
|
||||
if (gameObjectField != null)
|
||||
// netId changed?
|
||||
if (newNetId != netIdField)
|
||||
{
|
||||
oldGameObjectNetId = gameObjectField.GetComponent<NetworkIdentity>().netId;
|
||||
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.
|
||||
// -> ref GameObject as second argument makes OnDeserialize processing easier
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
protected GameObject GetSyncVarGameObject(uint netId, ref GameObject gameObjectField)
|
||||
{
|
||||
// server always uses the field
|
||||
if (isServer)
|
||||
{
|
||||
return gameObjectField;
|
||||
}
|
||||
|
||||
if (newGameObjectNetId != oldGameObjectNetId)
|
||||
// client always looks up based on netId because objects might get in and out of range
|
||||
// over and over again, which shouldn't null them forever
|
||||
NetworkIdentity identity;
|
||||
if (NetworkIdentity.spawned.TryGetValue(netId, out identity) && identity != null)
|
||||
return identity.gameObject;
|
||||
return null;
|
||||
}
|
||||
|
||||
// helper function for [SyncVar] NetworkIdentities.
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref NetworkIdentity identityField, ulong dirtyBit, ref uint netIdField)
|
||||
{
|
||||
if (m_SyncVarGuard)
|
||||
return;
|
||||
|
||||
uint newNetId = 0;
|
||||
if (newIdentity != null)
|
||||
{
|
||||
if (LogFilter.Debug) { Debug.Log("SetSyncVar GameObject " + GetType().Name + " bit [" + dirtyBit + "] netfieldId:" + oldGameObjectNetId + "->" + newGameObjectNetId); }
|
||||
SetDirtyBit(dirtyBit);
|
||||
gameObjectField = newGameObject;
|
||||
netIdField = newGameObjectNetId;
|
||||
newNetId = newIdentity.netId;
|
||||
if (newNetId == 0)
|
||||
{
|
||||
Debug.LogWarning("SetSyncVarNetworkIdentity NetworkIdentity " + newIdentity + " has a zero netId. Maybe it is not spawned yet?");
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// helper function for [SyncVar] NetworkIdentities.
|
||||
// -> ref GameObject as second argument makes OnDeserialize processing easier
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
protected NetworkIdentity GetSyncVarNetworkIdentity(uint netId, ref NetworkIdentity identityField)
|
||||
{
|
||||
// server always uses the field
|
||||
if (isServer)
|
||||
{
|
||||
return identityField;
|
||||
}
|
||||
|
||||
// client always looks up based on netId because objects might get in and out of range
|
||||
// over and over again, which shouldn't null them forever
|
||||
NetworkIdentity identity;
|
||||
NetworkIdentity.spawned.TryGetValue(netId, out identity);
|
||||
return identity;
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
@ -440,7 +500,6 @@ private void DeSerializeObjectsDelta(NetworkReader reader)
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public virtual void PreStartClient() {}
|
||||
public virtual void OnNetworkDestroy() {}
|
||||
public virtual void OnStartServer() {}
|
||||
public virtual void OnStartClient() {}
|
||||
|
@ -363,7 +363,6 @@ internal void OnStartClient()
|
||||
{
|
||||
try
|
||||
{
|
||||
comp.PreStartClient(); // generated startup to resolve object references
|
||||
comp.OnStartClient(); // user implemented startup
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -63,7 +63,6 @@ public void Process()
|
||||
}
|
||||
|
||||
GenerateDeSerialization();
|
||||
GeneratePreStartClient();
|
||||
Weaver.DLog(m_td, "Process Done");
|
||||
}
|
||||
|
||||
@ -447,66 +446,9 @@ public static int GetChannelId(CustomAttribute ca)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GeneratePreStartClient()
|
||||
{
|
||||
int netIdFieldCounter = 0;
|
||||
MethodDefinition preStartMethod = null;
|
||||
ILProcessor serWorker = null;
|
||||
|
||||
foreach (var m in m_td.Methods)
|
||||
{
|
||||
if (m.Name == "PreStartClient")
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (FieldDefinition syncVar in m_SyncVars)
|
||||
{
|
||||
if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
|
||||
{
|
||||
if (preStartMethod == null)
|
||||
{
|
||||
preStartMethod = new MethodDefinition("PreStartClient", MethodAttributes.Public |
|
||||
MethodAttributes.Virtual |
|
||||
MethodAttributes.HideBySig,
|
||||
Weaver.voidType);
|
||||
|
||||
serWorker = preStartMethod.Body.GetILProcessor();
|
||||
}
|
||||
|
||||
FieldDefinition netIdField = m_SyncVarNetIds[netIdFieldCounter];
|
||||
netIdFieldCounter += 1;
|
||||
|
||||
// Generates: if (!_crateNetId.IsEmpty()) { crate = ClientScene.FindLocalObject(_crateNetId); }
|
||||
Instruction nullLabel = serWorker.Create(OpCodes.Nop);
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldfld, netIdField));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_0));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ceq));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Brtrue, nullLabel));
|
||||
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldfld, netIdField));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.FindLocalObjectReference));
|
||||
|
||||
// return value of FindLocalObjectReference is on stack, assign it to the syncvar
|
||||
serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
|
||||
|
||||
// Generates: end crateNetId != 0
|
||||
serWorker.Append(nullLabel);
|
||||
}
|
||||
}
|
||||
if (preStartMethod != null)
|
||||
{
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
m_td.Methods.Add(preStartMethod);
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateDeSerialization()
|
||||
{
|
||||
Weaver.DLog(m_td, " GenerateDeSerialization");
|
||||
int netIdFieldCounter = 0;
|
||||
|
||||
foreach (var m in m_td.Methods)
|
||||
{
|
||||
@ -544,15 +486,21 @@ void GenerateDeSerialization()
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));
|
||||
|
||||
int netIdFieldCounter = 0;
|
||||
foreach (var 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)
|
||||
if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
|
||||
syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
|
||||
{
|
||||
// GameObject SyncVar - assign to generated netId var
|
||||
// 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[netIdFieldCounter];
|
||||
netIdFieldCounter += 1;
|
||||
|
||||
@ -592,6 +540,7 @@ void GenerateDeSerialization()
|
||||
serWorker.Append(serWorker.Create(OpCodes.Stloc_0));
|
||||
|
||||
// conditionally read each syncvar
|
||||
netIdFieldCounter = 0; // reset
|
||||
int dirtyBit = Weaver.GetSyncVarStart(m_td.BaseType.FullName); // start at number of syncvars in parent
|
||||
foreach (FieldDefinition syncVar in m_SyncVars)
|
||||
{
|
||||
@ -603,14 +552,6 @@ void GenerateDeSerialization()
|
||||
serWorker.Append(serWorker.Create(OpCodes.And));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));
|
||||
|
||||
MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType);
|
||||
if (readFunc == null)
|
||||
{
|
||||
Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types.");
|
||||
Weaver.fail = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// check for Hook function
|
||||
MethodDefinition foundMethod;
|
||||
if (!SyncVarProcessor.CheckForHookFunction(m_td, syncVar, out foundMethod))
|
||||
@ -618,21 +559,67 @@ void GenerateDeSerialization()
|
||||
return;
|
||||
}
|
||||
|
||||
if (foundMethod == null)
|
||||
if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
|
||||
syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
|
||||
{
|
||||
// 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));
|
||||
// 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[netIdFieldCounter];
|
||||
netIdFieldCounter += 1;
|
||||
|
||||
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
|
||||
{
|
||||
// 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.Ldarg_0));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
|
||||
if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
|
||||
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarGameObjectReference));
|
||||
else if (syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
|
||||
serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarNetworkIdentityReference));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// call hook instead
|
||||
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.Call, foundMethod));
|
||||
MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType);
|
||||
if (readFunc == null)
|
||||
{
|
||||
Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types.");
|
||||
Weaver.fail = true;
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// call hook instead
|
||||
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.Call, foundMethod));
|
||||
}
|
||||
}
|
||||
serWorker.Append(varLabel);
|
||||
dirtyBit += 1;
|
||||
|
@ -53,7 +53,7 @@ public static bool CheckForHookFunction(TypeDefinition td, FieldDefinition syncV
|
||||
return true;
|
||||
}
|
||||
|
||||
public static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string originalName)
|
||||
public static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string originalName, FieldDefinition netFieldId)
|
||||
{
|
||||
//Create the get method
|
||||
MethodDefinition get = new MethodDefinition(
|
||||
@ -64,9 +64,37 @@ public static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string orig
|
||||
|
||||
ILProcessor getWorker = get.Body.GetILProcessor();
|
||||
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldfld, fd));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ret));
|
||||
// [SyncVar] GameObject?
|
||||
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
|
||||
{
|
||||
// return this.GetSyncVarGameObject(ref field, uint netId);
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0)); // this.
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldfld, netFieldId));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldflda, fd));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Call, Weaver.getSyncVarGameObjectReference));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ret));
|
||||
}
|
||||
// [SyncVar] NetworkIdentity?
|
||||
else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
|
||||
{
|
||||
// return this.GetSyncVarNetworkIdentity(ref field, uint netId);
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0)); // this.
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldfld, netFieldId));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldflda, fd));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Call, Weaver.getSyncVarNetworkIdentityReference));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ret));
|
||||
}
|
||||
// [SyncVar] int, string, etc.
|
||||
else
|
||||
{
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ldfld, fd));
|
||||
getWorker.Append(getWorker.Create(OpCodes.Ret));
|
||||
}
|
||||
|
||||
get.Body.Variables.Add(new VariableDefinition(fd.FieldType));
|
||||
get.Body.InitLocals = true;
|
||||
@ -137,6 +165,14 @@ public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinit
|
||||
|
||||
setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarGameObjectReference));
|
||||
}
|
||||
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.Ldflda, netFieldId));
|
||||
|
||||
setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarNetworkIdentityReference));
|
||||
}
|
||||
else
|
||||
{
|
||||
// make generic version of SetSyncVar with field type
|
||||
@ -158,12 +194,12 @@ public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinit
|
||||
public static void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, List<FieldDefinition> syncVarNetIds, long dirtyBit)
|
||||
{
|
||||
string originalName = fd.Name;
|
||||
|
||||
Weaver.DLog(td, "Sync Var " + fd.Name + " " + fd.FieldType + " " + Weaver.gameObjectType);
|
||||
|
||||
// GameObject SyncVars have a new field for netId
|
||||
// GameObject/NetworkIdentity SyncVars have a new field for netId
|
||||
FieldDefinition netFieldId = null;
|
||||
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
|
||||
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName ||
|
||||
fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
|
||||
{
|
||||
netFieldId = new FieldDefinition("___" + fd.Name + "NetId",
|
||||
FieldAttributes.Private,
|
||||
@ -173,7 +209,7 @@ public static void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, List<Fi
|
||||
Weaver.lists.netIdFields.Add(netFieldId);
|
||||
}
|
||||
|
||||
var get = ProcessSyncVarGet(fd, originalName);
|
||||
var get = ProcessSyncVarGet(fd, originalName, netFieldId);
|
||||
var set = ProcessSyncVarSet(td, fd, originalName, dirtyBit, netFieldId);
|
||||
|
||||
//NOTE: is property even needed? Could just use a setter function?
|
||||
@ -188,6 +224,16 @@ public static void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, List<Fi
|
||||
td.Methods.Add(set);
|
||||
td.Properties.Add(propertyDefinition);
|
||||
Weaver.lists.replacementSetterProperties[fd] = set;
|
||||
|
||||
// replace getter field if GameObject/NetworkIdentity so it uses
|
||||
// netId instead
|
||||
// -> only for GameObjects, otherwise an int syncvar's getter would
|
||||
// end up in recursion.
|
||||
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName ||
|
||||
fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
|
||||
{
|
||||
Weaver.lists.replacementGetterProperties[fd] = get;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessSyncVars(TypeDefinition td, List<FieldDefinition> syncVars, List<FieldDefinition> syncObjects, List<FieldDefinition> syncVarNetIds)
|
||||
|
@ -15,6 +15,8 @@ class WeaverLists
|
||||
{
|
||||
// setter functions that replace [SyncVar] member variable references. dict<field, replacement>
|
||||
public Dictionary<FieldDefinition, MethodDefinition> replacementSetterProperties = new Dictionary<FieldDefinition, MethodDefinition>();
|
||||
// getter functions that replace [SyncVar] member variable references. dict<field, replacement>
|
||||
public Dictionary<FieldDefinition, MethodDefinition> replacementGetterProperties = new Dictionary<FieldDefinition, MethodDefinition>();
|
||||
// GameObject SyncVar generated netId fields
|
||||
public List<FieldDefinition> netIdFields = new List<FieldDefinition>();
|
||||
|
||||
@ -146,6 +148,9 @@ class Weaver
|
||||
public static MethodReference setSyncVarHookGuard;
|
||||
public static MethodReference getSyncVarHookGuard;
|
||||
public static MethodReference setSyncVarGameObjectReference;
|
||||
public static MethodReference getSyncVarGameObjectReference;
|
||||
public static MethodReference setSyncVarNetworkIdentityReference;
|
||||
public static MethodReference getSyncVarNetworkIdentityReference;
|
||||
public static MethodReference registerCommandDelegateReference;
|
||||
public static MethodReference registerRpcDelegateReference;
|
||||
public static MethodReference registerEventDelegateReference;
|
||||
@ -742,10 +747,11 @@ static void ConfirmGeneratedCodeClass(ModuleDefinition moduleDef)
|
||||
}
|
||||
}
|
||||
|
||||
// replaces syncvar write access with the NetworkXYZ.get property calls
|
||||
static void ProcessInstructionSetterField(TypeDefinition td, MethodDefinition md, Instruction i, FieldDefinition opField)
|
||||
{
|
||||
// dont replace property call sites in constructors or deserialize
|
||||
if (md.Name == ".ctor" || md.Name == "OnDeserialize")
|
||||
// dont replace property call sites in constructors
|
||||
if (md.Name == ".ctor")
|
||||
return;
|
||||
|
||||
// does it set a field that we replaced?
|
||||
@ -760,6 +766,25 @@ static void ProcessInstructionSetterField(TypeDefinition td, MethodDefinition md
|
||||
}
|
||||
}
|
||||
|
||||
// replaces syncvar read access with the NetworkXYZ.get property calls
|
||||
static void ProcessInstructionGetterField(TypeDefinition td, MethodDefinition md, Instruction i, FieldDefinition opField)
|
||||
{
|
||||
// dont replace property call sites in constructors
|
||||
if (md.Name == ".ctor")
|
||||
return;
|
||||
|
||||
// does it set a field that we replaced?
|
||||
MethodDefinition replacement;
|
||||
if (lists.replacementGetterProperties.TryGetValue(opField, out replacement))
|
||||
{
|
||||
//replace with property
|
||||
//DLog(td, " replacing " + md.Name + ":" + i);
|
||||
i.OpCode = OpCodes.Call;
|
||||
i.Operand = replacement;
|
||||
//DLog(td, " replaced " + md.Name + ":" + i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessInstruction(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, Instruction i, int iCount)
|
||||
{
|
||||
if (i.OpCode == OpCodes.Call || i.OpCode == OpCodes.Callvirt)
|
||||
@ -780,6 +805,16 @@ static void ProcessInstruction(ModuleDefinition moduleDef, TypeDefinition td, Me
|
||||
ProcessInstructionSetterField(td, md, i, opField);
|
||||
}
|
||||
}
|
||||
|
||||
if (i.OpCode == OpCodes.Ldfld)
|
||||
{
|
||||
// this instruction gets the value of a field. cache the field reference.
|
||||
FieldDefinition opField = i.Operand as FieldDefinition;
|
||||
if (opField != null)
|
||||
{
|
||||
ProcessInstructionGetterField(td, md, i, opField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is required to early-out from a function with "ref" or "out" parameters
|
||||
@ -885,7 +920,6 @@ static void ProcessSiteMethod(ModuleDefinition moduleDef, TypeDefinition td, Met
|
||||
//Weaver.DLog(td, " ProcessSiteMethod " + md);
|
||||
|
||||
if (md.Name == ".cctor" ||
|
||||
md.Name == "OnDeserialize" ||
|
||||
md.Name == NetworkBehaviourProcessor.ProcessedFunctionName ||
|
||||
md.Name.StartsWith("CallCmd") ||
|
||||
md.Name.StartsWith("InvokeCmd") ||
|
||||
@ -1129,6 +1163,9 @@ static void SetupTargetTypes()
|
||||
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "get_syncVarHookGuard");
|
||||
|
||||
setSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "SetSyncVarGameObject");
|
||||
getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "GetSyncVarGameObject");
|
||||
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "SetSyncVarNetworkIdentity");
|
||||
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "GetSyncVarNetworkIdentity");
|
||||
registerCommandDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "RegisterCommandDelegate");
|
||||
registerRpcDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "RegisterRpcDelegate");
|
||||
registerEventDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, scriptDef, "RegisterEventDelegate");
|
||||
|
Loading…
Reference in New Issue
Block a user