mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-01-30 03:32:47 +00:00
update weaver
This commit is contained in:
parent
2ca7046480
commit
613a2704b7
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user