update weaver

This commit is contained in:
JohnCorby 2023-04-26 15:06:17 -07:00
parent 2ca7046480
commit 613a2704b7
11 changed files with 182 additions and 91 deletions

View File

@ -12,8 +12,18 @@ namespace Mirror.Weaver
? td.GetElementType().FullName == type.FullName
: td.FullName == type.FullName;
// check if 'td' is exactly of type T.
// it does not check if any base type is of <T>, only the specific type.
// for example:
// NetworkConnection Is NetworkConnection: true
// NetworkConnectionToClient Is NetworkConnection: false
public static bool Is<T>(this TypeReference td) => Is(td, typeof(T));
// check if 'tr' is derived from T.
// it does not check if 'tr' is exactly T.
// for example:
// NetworkConnection IsDerivedFrom<NetworkConnection>: false
// NetworkConnectionToClient IsDerivedFrom<NetworkConnection>: true
public static bool IsDerivedFrom<T>(this TypeReference tr) => IsDerivedFrom(tr, typeof(T));
public static bool IsDerivedFrom(this TypeReference tr, Type baseClass)
@ -79,7 +89,10 @@ namespace Mirror.Weaver
public static bool IsNetworkIdentityField(this TypeReference tr) =>
tr.Is<UnityEngine.GameObject>() ||
tr.Is<NetworkIdentity>() ||
tr.IsDerivedFrom<NetworkBehaviour>();
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
tr.IsDerivedFrom<NetworkBehaviour>() ||
tr.Is<NetworkBehaviour>();
public static bool CanBeResolved(this TypeReference parent)
{
@ -266,7 +279,7 @@ namespace Mirror.Weaver
// Takes generic arguments from child class and applies them to parent reference, if possible
// eg makes `Base<T>` in Child<int> : Base<int> have `int` instead of `T`
// Originally by James-Frowen under MIT
// Originally by James-Frowen under MIT
// https://github.com/MirageNet/Mirage/commit/cf91e1d54796866d2cf87f8e919bb5c681977e45
public static TypeReference ApplyGenericParameters(this TypeReference parentReference,
TypeReference childReference)
@ -306,7 +319,7 @@ namespace Mirror.Weaver
}
// Finds the type reference for a generic parameter with the provided name in the child reference
// Originally by James-Frowen under MIT
// Originally by James-Frowen under MIT
// https://github.com/MirageNet/Mirage/commit/cf91e1d54796866d2cf87f8e919bb5c681977e45
static TypeReference FindMatchingGenericArgument(TypeReference childReference, string paramName)
{

View File

@ -10,10 +10,11 @@ namespace Mirror.Weaver
// generates code like:
public void CmdThrust(float thrusting, int spin)
{
NetworkWriter networkWriter = new NetworkWriter();
networkWriter.Write(thrusting);
networkWriter.WritePackedUInt32((uint)spin);
base.SendCommandInternal(cmdName, networkWriter, channel);
NetworkWriterPooled writer = NetworkWriterPool.Get();
writer.Write(thrusting);
writer.WritePackedUInt32((uint)spin);
base.SendCommandInternal(cmdName, cmdHash, writer, channel);
NetworkWriterPool.Return(writer);
}
public void CallCmdThrust(float thrusting, int spin)
@ -38,7 +39,7 @@ namespace Mirror.Weaver
NetworkBehaviourProcessor.WriteSetupLocals(worker, weaverTypes);
// NetworkWriter writer = new NetworkWriter();
NetworkBehaviourProcessor.WriteCreateWriter(worker, weaverTypes);
NetworkBehaviourProcessor.WriteGetWriter(worker, weaverTypes);
// write all the arguments that the user passed to the Cmd call
if (!NetworkBehaviourProcessor.WriteArguments(worker, writers, Log, md, RemoteCallType.Command, ref WeavingFailed))
@ -52,6 +53,11 @@ namespace Mirror.Weaver
worker.Emit(OpCodes.Ldarg_0);
// pass full function name to avoid ClassA.Func <-> ClassB.Func collisions
worker.Emit(OpCodes.Ldstr, md.FullName);
// pass the function hash so we don't have to compute it at runtime
// otherwise each GetStableHash call requires O(N) complexity.
// noticeable for long function names:
// https://github.com/MirrorNetworking/Mirror/issues/3375
worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode());
// writer
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ldc_I4, channel);
@ -59,7 +65,7 @@ namespace Mirror.Weaver
worker.Emit(requiresAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Call, weaverTypes.sendCommandInternal);
NetworkBehaviourProcessor.WriteRecycleWriter(worker, weaverTypes);
NetworkBehaviourProcessor.WriteReturnWriter(worker, weaverTypes);
worker.Emit(OpCodes.Ret);
return cmd;

View File

@ -137,21 +137,21 @@ namespace Mirror.Weaver
public static void WriteSetupLocals(ILProcessor worker, WeaverTypes weaverTypes)
{
worker.Body.InitLocals = true;
worker.Body.Variables.Add(new VariableDefinition(weaverTypes.Import<PooledNetworkWriter>()));
worker.Body.Variables.Add(new VariableDefinition(weaverTypes.Import<NetworkWriterPooled>()));
}
public static void WriteCreateWriter(ILProcessor worker, WeaverTypes weaverTypes)
public static void WriteGetWriter(ILProcessor worker, WeaverTypes weaverTypes)
{
// create writer
worker.Emit(OpCodes.Call, weaverTypes.GetPooledWriterReference);
worker.Emit(OpCodes.Call, weaverTypes.GetWriterReference);
worker.Emit(OpCodes.Stloc_0);
}
public static void WriteRecycleWriter(ILProcessor worker, WeaverTypes weaverTypes)
public static void WriteReturnWriter(ILProcessor worker, WeaverTypes weaverTypes)
{
// NetworkWriterPool.Recycle(writer);
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Call, weaverTypes.RecycleWriterReference);
worker.Emit(OpCodes.Call, weaverTypes.ReturnWriterReference);
}
public static bool WriteArguments(ILProcessor worker, Writers writers, Logger Log, MethodDefinition method, RemoteCallType callType, ref bool WeavingFailed)
@ -397,7 +397,7 @@ namespace Mirror.Weaver
MethodDefinition serialize = new MethodDefinition(SerializeMethodName,
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
weaverTypes.Import<bool>());
weaverTypes.Import(typeof(void)));
serialize.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, weaverTypes.Import<NetworkWriter>()));
serialize.Parameters.Add(new ParameterDefinition("forceAll", ParameterAttributes.None, weaverTypes.Import<bool>()));
@ -405,10 +405,7 @@ namespace Mirror.Weaver
serialize.Body.InitLocals = true;
// loc_0, this local variable is to determine if any variable was dirty
VariableDefinition dirtyLocal = new VariableDefinition(weaverTypes.Import<bool>());
serialize.Body.Variables.Add(dirtyLocal);
// base.SerializeSyncVars(writer, forceAll);
MethodReference baseSerialize = Resolvers.TryResolveMethodInParents(netBehaviourSubclass.BaseType, assembly, SerializeMethodName);
if (baseSerialize != null)
{
@ -419,16 +416,20 @@ namespace Mirror.Weaver
// forceAll
worker.Emit(OpCodes.Ldarg_2);
worker.Emit(OpCodes.Call, baseSerialize);
// set dirtyLocal to result of base.OnSerialize()
worker.Emit(OpCodes.Stloc_0);
}
// Generates: if (forceAll);
// Generates:
// if (forceAll)
// {
// writer.WriteInt(health);
// ...
// }
Instruction initialStateLabel = worker.Create(OpCodes.Nop);
// forceAll
worker.Emit(OpCodes.Ldarg_2);
worker.Emit(OpCodes.Brfalse, initialStateLabel);
worker.Emit(OpCodes.Ldarg_2); // load 'forceAll' flag
worker.Emit(OpCodes.Brfalse, initialStateLabel); // start the 'if forceAll' branch
// generates write.Write(syncVar) for each SyncVar in forceAll case
foreach (FieldDefinition syncVarDef in syncVars)
{
FieldReference syncVar = syncVarDef;
@ -442,7 +443,21 @@ namespace Mirror.Weaver
// this
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, syncVar);
MethodReference writeFunc = writers.GetWriteFunc(syncVar.FieldType, ref WeavingFailed);
MethodReference writeFunc;
// For NBs we always need to use the default NetworkBehaviour write func
// since the reader counter part uses that exact layout which is not easy to change
// without introducing more edge cases
// effectively this disallows custom NB-type writers/readers on SyncVars
// see: https://github.com/MirrorNetworking/Mirror/issues/2680
if (syncVar.FieldType.IsDerivedFrom<NetworkBehaviour>())
{
writeFunc = writers.GetWriteFunc(weaverTypes.Import<NetworkBehaviour>(), ref WeavingFailed);
}
else
{
writeFunc = writers.GetWriteFunc(syncVar.FieldType, ref WeavingFailed);
}
if (writeFunc != null)
{
worker.Emit(OpCodes.Call, writeFunc);
@ -455,15 +470,14 @@ namespace Mirror.Weaver
}
}
// always return true if forceAll
// Generates: return true
worker.Emit(OpCodes.Ldc_I4_1);
// if (forceAll) then always return at the end of the 'if' case
worker.Emit(OpCodes.Ret);
// Generates: end if (forceAll);
// end the 'if' case for "if (forceAll)"
worker.Append(initialStateLabel);
////////////////////////////////////////////////////////////////////
// write dirty bits before the data fields
// Generates: writer.WritePackedUInt64 (base.get_syncVarDirtyBits ());
// writer
@ -480,7 +494,6 @@ namespace Mirror.Weaver
int dirtyBit = syncVarAccessLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName);
foreach (FieldDefinition syncVarDef in syncVars)
{
FieldReference syncVar = syncVarDef;
if (netBehaviourSubclass.HasGenericParameters)
{
@ -504,7 +517,21 @@ namespace Mirror.Weaver
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, syncVar);
MethodReference writeFunc = writers.GetWriteFunc(syncVar.FieldType, ref WeavingFailed);
MethodReference writeFunc;
// For NBs we always need to use the default NetworkBehaviour write func
// since the reader counter part uses that exact layout which is not easy to change
// without introducing more edge cases
// effectively this disallows custom NB-type writers/readers on SyncVars
// see: https://github.com/MirrorNetworking/Mirror/issues/2680
if (syncVar.FieldType.IsDerivedFrom<NetworkBehaviour>())
{
writeFunc = writers.GetWriteFunc(weaverTypes.Import<NetworkBehaviour>(), ref WeavingFailed);
}
else
{
writeFunc = writers.GetWriteFunc(syncVar.FieldType, ref WeavingFailed);
}
if (writeFunc != null)
{
worker.Emit(OpCodes.Call, writeFunc);
@ -516,11 +543,6 @@ namespace Mirror.Weaver
return;
}
// something was dirty
worker.Emit(OpCodes.Ldc_I4_1);
// set dirtyLocal to true
worker.Emit(OpCodes.Stloc_0);
worker.Append(varLabel);
dirtyBit += 1;
}
@ -529,8 +551,7 @@ namespace Mirror.Weaver
//worker.Emit(OpCodes.Ldstr, $"Injected Serialize {netBehaviourSubclass.Name}");
//worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
// generate: return dirtyLocal
worker.Emit(OpCodes.Ldloc_0);
// generate: return
worker.Emit(OpCodes.Ret);
netBehaviourSubclass.Methods.Add(serialize);
}
@ -589,10 +610,9 @@ namespace Mirror.Weaver
worker.Emit(OpCodes.Ldflda, netIdField);
worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarDeserialize_NetworkIdentity);
}
// TODO this only uses the persistent netId for types DERIVED FROM NB.
// not if the type is just 'NetworkBehaviour'.
// this is what original implementation did too. fix it after.
else if (syncVar.FieldType.IsDerivedFrom<NetworkBehaviour>())
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
else if (syncVar.FieldType.IsDerivedFrom<NetworkBehaviour>() || syncVar.FieldType.Is<NetworkBehaviour>())
{
// reader
worker.Emit(OpCodes.Ldarg_1);

View File

@ -68,7 +68,7 @@ namespace Mirror.Weaver
//worker.Emit(OpCodes.Ldstr, $"Call ClientRpc function {md.Name}");
//worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
NetworkBehaviourProcessor.WriteCreateWriter(worker, weaverTypes);
NetworkBehaviourProcessor.WriteGetWriter(worker, weaverTypes);
// write all the arguments that the user passed to the Rpc call
if (!NetworkBehaviourProcessor.WriteArguments(worker, writers, Log, md, RemoteCallType.ClientRpc, ref WeavingFailed))
@ -82,6 +82,11 @@ namespace Mirror.Weaver
worker.Emit(OpCodes.Ldarg_0);
// pass full function name to avoid ClassA.Func <-> ClassB.Func collisions
worker.Emit(OpCodes.Ldstr, md.FullName);
// pass the function hash so we don't have to compute it at runtime
// otherwise each GetStableHash call requires O(N) complexity.
// noticeable for long function names:
// https://github.com/MirrorNetworking/Mirror/issues/3375
worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode());
// writer
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ldc_I4, channel);
@ -89,7 +94,7 @@ namespace Mirror.Weaver
worker.Emit(includeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Callvirt, weaverTypes.sendRpcInternal);
NetworkBehaviourProcessor.WriteRecycleWriter(worker, weaverTypes);
NetworkBehaviourProcessor.WriteReturnWriter(worker, weaverTypes);
worker.Emit(OpCodes.Ret);

View File

@ -16,7 +16,7 @@ namespace Mirror.Weaver
foreach (FieldDefinition fd in td.Fields)
{
if (fd.FieldType.IsGenericParameter)
if (fd.FieldType.IsGenericParameter || fd.ContainsGenericParameter)
{
// can't call .Resolve on generic ones
continue;

View File

@ -203,7 +203,9 @@ namespace Mirror.Weaver
worker.Emit(OpCodes.Call, weaverTypes.getSyncVarNetworkIdentityReference);
worker.Emit(OpCodes.Ret);
}
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>() || fd.FieldType.Is<NetworkBehaviour>())
{
// return this.GetSyncVarNetworkBehaviour<T>(ref field, uint netId);
// this.
@ -331,10 +333,9 @@ namespace Mirror.Weaver
worker.Emit(OpCodes.Ldflda, netIdFieldReference);
worker.Emit(OpCodes.Call, weaverTypes.generatedSyncVarSetter_NetworkIdentity);
}
// TODO this only uses the persistent netId for types DERIVED FROM NB.
// not if the type is just 'NetworkBehaviour'.
// this is what original implementation did too. fix it after.
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>() || fd.FieldType.Is<NetworkBehaviour>())
{
// NetworkIdentity setter needs one more parameter: netId field ref
// (actually its a NetworkBehaviourSyncVar type)
@ -368,11 +369,13 @@ namespace Mirror.Weaver
// GameObject/NetworkIdentity SyncVars have a new field for netId
FieldDefinition netIdField = null;
// NetworkBehaviour has different field type than other NetworkIdentityFields
if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>() || fd.FieldType.Is<NetworkBehaviour>())
{
netIdField = new FieldDefinition($"___{fd.Name}NetId",
FieldAttributes.Family, // needs to be protected for generic classes, otherwise access isn't allowed
weaverTypes.Import<NetworkBehaviour.NetworkBehaviourSyncVar>());
weaverTypes.Import<NetworkBehaviourSyncVar>());
netIdField.DeclaringType = td;
syncVarNetIds[fd] = netIdField;
@ -475,7 +478,11 @@ namespace Mirror.Weaver
{
td.Fields.Add(fd);
}
syncVarAccessLists.SetNumSyncVars(td.FullName, syncVars.Count);
// include parent class syncvars
// fixes: https://github.com/MirrorNetworking/Mirror/issues/3457
int parentSyncVarCount = syncVarAccessLists.GetSyncVarStart(td.BaseType.FullName);
syncVarAccessLists.SetNumSyncVars(td.FullName, parentSyncVarCount + syncVars.Count);
return (syncVars, syncVarNetIds);
}

View File

@ -9,8 +9,16 @@ namespace Mirror.Weaver
// helper functions to check if the method has a NetworkConnection parameter
public static bool HasNetworkConnectionParameter(MethodDefinition md)
{
return md.Parameters.Count > 0 &&
md.Parameters[0].ParameterType.Is<NetworkConnection>();
if (md.Parameters.Count > 0)
{
// we need to allow both NetworkConnection, and inheriting types.
// NetworkBehaviour.SendTargetRpc takes a NetworkConnection parameter.
// fixes https://github.com/vis2k/Mirror/issues/3290
TypeReference type = md.Parameters[0].ParameterType;
return type.Is<NetworkConnection>() ||
type.IsDerivedFrom<NetworkConnection>();
}
return false;
}
public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed)
@ -34,16 +42,25 @@ namespace Mirror.Weaver
// NetworkConnection parameter is optional
if (HasNetworkConnectionParameter(md))
{
// on server, the NetworkConnection parameter is a connection to client.
// when the rpc is invoked on the client, it still has the same
// function signature. we pass in the connection to server,
// which is cleaner than just passing null)
//NetworkClient.readyconnection
// TargetRpcs are sent from server to client.
// on server, we currently support two types:
// TargetRpc(NetworkConnection)
// TargetRpc(NetworkConnectionToClient)
// however, it's always a connection to client.
// in the future, only NetworkConnectionToClient will be supported.
// explicit typing helps catch issues at compile time.
//
// TODO
// a) .connectionToServer = best solution. no doubt.
// b) NetworkClient.connection for now. add TODO to not use static later.
worker.Emit(OpCodes.Call, weaverTypes.NetworkClientConnectionReference);
// on client, InvokeTargetRpc calls the original code.
// we need to fill in the NetworkConnection parameter.
// NetworkClient.connection is always a connection to server.
//
// we used to pass NetworkClient.connection as the TargetRpc parameter.
// which caused: https://github.com/MirrorNetworking/Mirror/issues/3455
// when the parameter is defined as a NetworkConnectionToClient.
//
// a client's connection never fits into a NetworkConnectionToClient.
// we need to always pass null here.
worker.Emit(OpCodes.Ldnull);
}
// process reader parameters and skip first one if first one is NetworkConnection
@ -100,7 +117,7 @@ namespace Mirror.Weaver
NetworkBehaviourProcessor.WriteSetupLocals(worker, weaverTypes);
NetworkBehaviourProcessor.WriteCreateWriter(worker, weaverTypes);
NetworkBehaviourProcessor.WriteGetWriter(worker, weaverTypes);
// write all the arguments that the user passed to the TargetRpc call
// (skip first one if first one is NetworkConnection)
@ -122,12 +139,17 @@ namespace Mirror.Weaver
}
// pass full function name to avoid ClassA.Func <-> ClassB.Func collisions
worker.Emit(OpCodes.Ldstr, md.FullName);
// pass the function hash so we don't have to compute it at runtime
// otherwise each GetStableHash call requires O(N) complexity.
// noticeable for long function names:
// https://github.com/MirrorNetworking/Mirror/issues/3375
worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode());
// writer
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0));
worker.Emit(OpCodes.Callvirt, weaverTypes.sendTargetRpcInternal);
NetworkBehaviourProcessor.WriteRecycleWriter(worker, weaverTypes);
NetworkBehaviourProcessor.WriteReturnWriter(worker, weaverTypes);
worker.Emit(OpCodes.Ret);

View File

@ -19,6 +19,7 @@ namespace Mirror.Weaver
AssemblyDefinition assembly;
WeaverTypes weaverTypes;
TypeDefinition GeneratedCodeClass;
// CHANGED
internal Logger Log;
Dictionary<TypeReference, MethodReference> readFuncs =
@ -114,7 +115,9 @@ namespace Mirror.Weaver
return GenerateReadCollection(variableReference, elementType, nameof(NetworkReaderExtensions.ReadList), ref WeavingFailed);
}
else if (variableReference.IsDerivedFrom<NetworkBehaviour>())
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
else if (variableReference.IsDerivedFrom<NetworkBehaviour>() || variableReference.Is<NetworkBehaviour>())
{
return GetNetworkBehaviourReader(variableReference);
}
@ -138,6 +141,7 @@ namespace Mirror.Weaver
WeavingFailed = true;
return null;
}
// CHANGED
/*
if (variableDefinition.HasGenericParameters)
{
@ -270,6 +274,7 @@ namespace Mirror.Weaver
GenerateNullCheck(worker, ref WeavingFailed);
CreateNew(variable, worker, td, ref WeavingFailed);
// CHANGED
this.ReadAllFieldsGeneric(variable, worker, ref WeavingFailed);
worker.Emit(OpCodes.Ldloc_0);

View File

@ -25,6 +25,12 @@ namespace Mirror.Weaver
AssemblyDefinition CurrentAssembly;
Writers writers;
Readers readers;
// in case of weaver errors, we don't stop immediately.
// we log all errors and then eventually return false if
// weaving has failed.
// this way the user can fix multiple errors at once, instead of having
// to fix -> recompile -> fix -> recompile for one error at a time.
bool WeavingFailed;
// logger functions can be set from the outside.
@ -200,6 +206,7 @@ namespace Mirror.Weaver
ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
Console.WriteLine($"Script Module: {moduleDefinition.Name}");
// CHANGED
QSBReaderWriterProcessor.Process(moduleDefinition, writers, readers, ref WeavingFailed);
modified |= WeaveModule(moduleDefinition);

View File

@ -11,8 +11,8 @@ namespace Mirror.Weaver
public MethodReference ScriptableObjectCreateInstanceMethod;
public MethodReference NetworkBehaviourDirtyBitsReference;
public MethodReference GetPooledWriterReference;
public MethodReference RecycleWriterReference;
public MethodReference GetWriterReference;
public MethodReference ReturnWriterReference;
public MethodReference NetworkClientConnectionReference;
@ -77,28 +77,14 @@ namespace Mirror.Weaver
TypeReference NetworkServerType = Import(typeof(NetworkServer));
NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, assembly, Log, "get_active", ref WeavingFailed);
TypeReference NetworkClientType = Import(typeof(NetworkClient));
NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_active", ref WeavingFailed);
TypeReference RemoteCallDelegateType = Import<RemoteCalls.RemoteCallDelegate>();
RemoteCallDelegateConstructor = Resolvers.ResolveMethod(RemoteCallDelegateType, assembly, Log, ".ctor", ref WeavingFailed);
NetworkClientConnectionReference = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_connection", ref WeavingFailed);
TypeReference NetworkBehaviourType = Import<NetworkBehaviour>();
TypeReference RemoteProcedureCallsType = Import(typeof(RemoteCalls.RemoteProcedureCalls));
TypeReference ScriptableObjectType = Import<ScriptableObject>();
ScriptableObjectCreateInstanceMethod = Resolvers.ResolveMethod(
ScriptableObjectType, assembly, Log,
md => md.Name == "CreateInstance" && md.HasGenericParameters,
ref WeavingFailed);
NetworkBehaviourDirtyBitsReference = Resolvers.ResolveProperty(NetworkBehaviourType, assembly, "syncVarDirtyBits");
TypeReference NetworkWriterPoolType = Import(typeof(NetworkWriterPool));
GetPooledWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, assembly, Log, "GetWriter", ref WeavingFailed);
RecycleWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, assembly, Log, "Recycle", ref WeavingFailed);
NetworkClientConnectionReference = Resolvers.ResolveMethod(NetworkClientType, assembly, Log, "get_connection", ref WeavingFailed);
generatedSyncVarSetter = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter", ref WeavingFailed);
generatedSyncVarSetter_GameObject = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GeneratedSyncVarSetter_GameObject", ref WeavingFailed);
@ -114,9 +100,25 @@ namespace Mirror.Weaver
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkIdentity", ref WeavingFailed);
getSyncVarNetworkBehaviourReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "GetSyncVarNetworkBehaviour", ref WeavingFailed);
sendCommandInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendCommandInternal", ref WeavingFailed);
sendRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendRPCInternal", ref WeavingFailed);
sendTargetRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendTargetRPCInternal", ref WeavingFailed);
InitSyncObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "InitSyncObject", ref WeavingFailed);
TypeReference RemoteProcedureCallsType = Import(typeof(RemoteCalls.RemoteProcedureCalls));
registerCommandReference = Resolvers.ResolveMethod(RemoteProcedureCallsType, assembly, Log, "RegisterCommand", ref WeavingFailed);
registerRpcReference = Resolvers.ResolveMethod(RemoteProcedureCallsType, assembly, Log, "RegisterRpc", ref WeavingFailed);
TypeReference RemoteCallDelegateType = Import<RemoteCalls.RemoteCallDelegate>();
RemoteCallDelegateConstructor = Resolvers.ResolveMethod(RemoteCallDelegateType, assembly, Log, ".ctor", ref WeavingFailed);
TypeReference ScriptableObjectType = Import<ScriptableObject>();
ScriptableObjectCreateInstanceMethod = Resolvers.ResolveMethod(
ScriptableObjectType, assembly, Log,
md => md.Name == "CreateInstance" && md.HasGenericParameters,
ref WeavingFailed);
TypeReference unityDebug = Import(typeof(UnityEngine.Debug));
// these have multiple methods with same name, so need to check parameters too
logErrorReference = Resolvers.ResolveMethod(unityDebug, assembly, Log, md =>
@ -133,11 +135,10 @@ namespace Mirror.Weaver
TypeReference typeType = Import(typeof(Type));
getTypeFromHandleReference = Resolvers.ResolveMethod(typeType, assembly, Log, "GetTypeFromHandle", ref WeavingFailed);
sendCommandInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendCommandInternal", ref WeavingFailed);
sendRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendRPCInternal", ref WeavingFailed);
sendTargetRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "SendTargetRPCInternal", ref WeavingFailed);
InitSyncObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, assembly, Log, "InitSyncObject", ref WeavingFailed);
TypeReference NetworkWriterPoolType = Import(typeof(NetworkWriterPool));
GetWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, assembly, Log, "Get", ref WeavingFailed);
ReturnWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, assembly, Log, "Return", ref WeavingFailed);
TypeReference readerExtensions = Import(typeof(NetworkReaderExtensions));
readNetworkBehaviourGeneric = Resolvers.ResolveMethod(readerExtensions, assembly, Log, (md =>
@ -147,6 +148,7 @@ namespace Mirror.Weaver
}),
ref WeavingFailed);
// CHANGED
/*
// [InitializeOnLoadMethod]
// 'UnityEditor' is not available in builds.

View File

@ -116,7 +116,9 @@ namespace Mirror.Weaver
return GenerateCollectionWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteList), ref WeavingFailed);
}
if (variableReference.IsDerivedFrom<NetworkBehaviour>())
// handle both NetworkBehaviour and inheritors.
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
if (variableReference.IsDerivedFrom<NetworkBehaviour>() || variableReference.Is<NetworkBehaviour>())
{
return GetNetworkBehaviourWriter(variableReference);
}
@ -139,6 +141,7 @@ namespace Mirror.Weaver
{
throw new GenerateWriterException($"Cannot generate writer for {variableReference.Name}. Use a supported type or provide a custom writer", variableReference);
}
// CHANGED
/*
if (variableDefinition.HasGenericParameters)
{
@ -219,6 +222,7 @@ namespace Mirror.Weaver
if (!variable.Resolve().IsValueType)
WriteNullCheck(worker, ref WeavingFailed);
// CHANGED
if (!this.WriteAllFieldsGeneric(variable, worker, ref WeavingFailed))
return null;