mirror of
https://github.com/Steffo99/better-tee.git
synced 2024-11-27 00:54:20 +00:00
599 lines
27 KiB
C#
599 lines
27 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using System.Linq;
|
||
|
using Mono.CecilX;
|
||
|
using Mono.CecilX.Cil;
|
||
|
|
||
|
namespace Mirror.Weaver
|
||
|
{
|
||
|
// This data is flushed each time - if we are run multiple times in the same process/domain
|
||
|
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>();
|
||
|
|
||
|
// [Command]/[ClientRpc] functions that should be replaced. dict<originalMethodFullName, replacement>
|
||
|
public Dictionary<string, MethodDefinition> replaceMethods = new Dictionary<string, MethodDefinition>();
|
||
|
|
||
|
// [SyncEvent] invoke functions that should be replaced. dict<originalEventName, replacement>
|
||
|
public Dictionary<string, MethodDefinition> replaceEvents = new Dictionary<string, MethodDefinition>();
|
||
|
|
||
|
public List<MethodDefinition> generatedReadFunctions = new List<MethodDefinition>();
|
||
|
public List<MethodDefinition> generatedWriteFunctions = new List<MethodDefinition>();
|
||
|
|
||
|
public TypeDefinition generateContainerClass;
|
||
|
|
||
|
// amount of SyncVars per class. dict<className, amount>
|
||
|
public Dictionary<string, int> numSyncVars = new Dictionary<string, int>();
|
||
|
}
|
||
|
|
||
|
class Weaver
|
||
|
{
|
||
|
public static WeaverLists WeaveLists { get; private set; }
|
||
|
public static AssemblyDefinition CurrentAssembly { get; private set; }
|
||
|
public static ModuleDefinition CorLibModule { get; private set; }
|
||
|
public static AssemblyDefinition UnityAssembly { get; private set; }
|
||
|
public static AssemblyDefinition NetAssembly { get; private set; }
|
||
|
public static bool WeavingFailed { get; private set; }
|
||
|
public static bool GenerateLogErrors { get; set; }
|
||
|
|
||
|
// private properties
|
||
|
static readonly bool DebugLogEnabled = true;
|
||
|
|
||
|
// Network types
|
||
|
public static TypeReference NetworkBehaviourType;
|
||
|
public static TypeReference NetworkBehaviourType2;
|
||
|
public static TypeReference MonoBehaviourType;
|
||
|
public static TypeReference ScriptableObjectType;
|
||
|
public static TypeReference NetworkConnectionType;
|
||
|
|
||
|
public static TypeReference MessageBaseType;
|
||
|
public static TypeReference SyncListType;
|
||
|
public static TypeReference SyncSetType;
|
||
|
public static TypeReference SyncDictionaryType;
|
||
|
|
||
|
public static MethodReference NetworkBehaviourDirtyBitsReference;
|
||
|
public static MethodReference GetPooledWriterReference;
|
||
|
public static MethodReference RecycleWriterReference;
|
||
|
public static TypeReference NetworkClientType;
|
||
|
public static TypeReference NetworkServerType;
|
||
|
|
||
|
public static TypeReference NetworkReaderType;
|
||
|
|
||
|
public static TypeReference NetworkWriterType;
|
||
|
|
||
|
public static TypeReference NetworkIdentityType;
|
||
|
public static TypeReference IEnumeratorType;
|
||
|
|
||
|
public static TypeReference ClientSceneType;
|
||
|
public static MethodReference ReadyConnectionReference;
|
||
|
|
||
|
public static TypeReference ComponentType;
|
||
|
|
||
|
public static TypeReference CmdDelegateReference;
|
||
|
public static MethodReference CmdDelegateConstructor;
|
||
|
|
||
|
public static MethodReference NetworkServerGetActive;
|
||
|
public static MethodReference NetworkServerGetLocalClientActive;
|
||
|
public static MethodReference NetworkClientGetActive;
|
||
|
public static MethodReference getBehaviourIsServer;
|
||
|
|
||
|
// custom attribute types
|
||
|
public static TypeReference SyncVarType;
|
||
|
public static TypeReference CommandType;
|
||
|
public static TypeReference ClientRpcType;
|
||
|
public static TypeReference TargetRpcType;
|
||
|
public static TypeReference SyncEventType;
|
||
|
public static TypeReference SyncObjectType;
|
||
|
public static MethodReference InitSyncObjectReference;
|
||
|
|
||
|
// array segment
|
||
|
public static TypeReference ArraySegmentType;
|
||
|
public static MethodReference ArraySegmentConstructorReference;
|
||
|
public static MethodReference ArraySegmentArrayReference;
|
||
|
public static MethodReference ArraySegmentOffsetReference;
|
||
|
public static MethodReference ArraySegmentCountReference;
|
||
|
|
||
|
// system types
|
||
|
public static TypeReference voidType;
|
||
|
public static TypeReference singleType;
|
||
|
public static TypeReference doubleType;
|
||
|
public static TypeReference boolType;
|
||
|
public static TypeReference int64Type;
|
||
|
public static TypeReference uint64Type;
|
||
|
public static TypeReference int32Type;
|
||
|
public static TypeReference uint32Type;
|
||
|
public static TypeReference objectType;
|
||
|
public static TypeReference typeType;
|
||
|
public static TypeReference gameObjectType;
|
||
|
public static TypeReference transformType;
|
||
|
|
||
|
public static MethodReference setSyncVarReference;
|
||
|
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;
|
||
|
public static MethodReference getTypeReference;
|
||
|
public static MethodReference getTypeFromHandleReference;
|
||
|
public static MethodReference logErrorReference;
|
||
|
public static MethodReference logWarningReference;
|
||
|
public static MethodReference sendCommandInternal;
|
||
|
public static MethodReference sendRpcInternal;
|
||
|
public static MethodReference sendTargetRpcInternal;
|
||
|
public static MethodReference sendEventInternal;
|
||
|
|
||
|
public static void DLog(TypeDefinition td, string fmt, params object[] args)
|
||
|
{
|
||
|
if (!DebugLogEnabled)
|
||
|
return;
|
||
|
|
||
|
Console.WriteLine("[" + td.Name + "] " + string.Format(fmt, args));
|
||
|
}
|
||
|
|
||
|
// display weaver error
|
||
|
// and mark process as failed
|
||
|
public static void Error(string message)
|
||
|
{
|
||
|
Log.Error(message);
|
||
|
WeavingFailed = true;
|
||
|
}
|
||
|
|
||
|
public static int GetSyncVarStart(string className)
|
||
|
{
|
||
|
return WeaveLists.numSyncVars.ContainsKey(className)
|
||
|
? WeaveLists.numSyncVars[className]
|
||
|
: 0;
|
||
|
}
|
||
|
|
||
|
public static void SetNumSyncVars(string className, int num)
|
||
|
{
|
||
|
WeaveLists.numSyncVars[className] = num;
|
||
|
}
|
||
|
|
||
|
internal static void ConfirmGeneratedCodeClass()
|
||
|
{
|
||
|
if (WeaveLists.generateContainerClass == null)
|
||
|
{
|
||
|
WeaveLists.generateContainerClass = new TypeDefinition("Mirror", "GeneratedNetworkCode",
|
||
|
TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.AutoClass,
|
||
|
objectType);
|
||
|
|
||
|
const MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
|
||
|
MethodDefinition method = new MethodDefinition(".ctor", methodAttributes, voidType);
|
||
|
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
|
||
|
method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, Resolvers.ResolveMethod(objectType, CurrentAssembly, ".ctor")));
|
||
|
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
|
||
|
|
||
|
WeaveLists.generateContainerClass.Methods.Add(method);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool ProcessNetworkBehaviourType(TypeDefinition td)
|
||
|
{
|
||
|
if (!NetworkBehaviourProcessor.WasProcessed(td))
|
||
|
{
|
||
|
DLog(td, "Found NetworkBehaviour " + td.FullName);
|
||
|
|
||
|
NetworkBehaviourProcessor proc = new NetworkBehaviourProcessor(td);
|
||
|
proc.Process();
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static void SetupUnityTypes()
|
||
|
{
|
||
|
gameObjectType = UnityAssembly.MainModule.GetType("UnityEngine.GameObject");
|
||
|
transformType = UnityAssembly.MainModule.GetType("UnityEngine.Transform");
|
||
|
|
||
|
NetworkClientType = NetAssembly.MainModule.GetType("Mirror.NetworkClient");
|
||
|
NetworkServerType = NetAssembly.MainModule.GetType("Mirror.NetworkServer");
|
||
|
|
||
|
SyncVarType = NetAssembly.MainModule.GetType("Mirror.SyncVarAttribute");
|
||
|
CommandType = NetAssembly.MainModule.GetType("Mirror.CommandAttribute");
|
||
|
ClientRpcType = NetAssembly.MainModule.GetType("Mirror.ClientRpcAttribute");
|
||
|
TargetRpcType = NetAssembly.MainModule.GetType("Mirror.TargetRpcAttribute");
|
||
|
SyncEventType = NetAssembly.MainModule.GetType("Mirror.SyncEventAttribute");
|
||
|
SyncObjectType = NetAssembly.MainModule.GetType("Mirror.SyncObject");
|
||
|
}
|
||
|
|
||
|
static void SetupCorLib()
|
||
|
{
|
||
|
AssemblyNameReference name = AssemblyNameReference.Parse("mscorlib");
|
||
|
ReaderParameters parameters = new ReaderParameters
|
||
|
{
|
||
|
AssemblyResolver = CurrentAssembly.MainModule.AssemblyResolver
|
||
|
};
|
||
|
CorLibModule = CurrentAssembly.MainModule.AssemblyResolver.Resolve(name, parameters).MainModule;
|
||
|
}
|
||
|
|
||
|
static TypeReference ImportCorLibType(string fullName)
|
||
|
{
|
||
|
TypeDefinition type = CorLibModule.GetType(fullName) ?? CorLibModule.ExportedTypes.First(t => t.FullName == fullName).Resolve();
|
||
|
if (type != null)
|
||
|
{
|
||
|
return CurrentAssembly.MainModule.ImportReference(type);
|
||
|
}
|
||
|
Error("Failed to import mscorlib type: " + fullName + " because Resolve failed. (Might happen when trying to Resolve in NetStandard dll, see also: https://github.com/vis2k/Mirror/issues/791)");
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
static void SetupTargetTypes()
|
||
|
{
|
||
|
// system types
|
||
|
SetupCorLib();
|
||
|
voidType = ImportCorLibType("System.Void");
|
||
|
singleType = ImportCorLibType("System.Single");
|
||
|
doubleType = ImportCorLibType("System.Double");
|
||
|
boolType = ImportCorLibType("System.Boolean");
|
||
|
int64Type = ImportCorLibType("System.Int64");
|
||
|
uint64Type = ImportCorLibType("System.UInt64");
|
||
|
int32Type = ImportCorLibType("System.Int32");
|
||
|
uint32Type = ImportCorLibType("System.UInt32");
|
||
|
objectType = ImportCorLibType("System.Object");
|
||
|
typeType = ImportCorLibType("System.Type");
|
||
|
IEnumeratorType = ImportCorLibType("System.Collections.IEnumerator");
|
||
|
|
||
|
ArraySegmentType = ImportCorLibType("System.ArraySegment`1");
|
||
|
ArraySegmentArrayReference = Resolvers.ResolveProperty(ArraySegmentType, CurrentAssembly, "Array");
|
||
|
ArraySegmentCountReference = Resolvers.ResolveProperty(ArraySegmentType, CurrentAssembly, "Count");
|
||
|
ArraySegmentOffsetReference = Resolvers.ResolveProperty(ArraySegmentType, CurrentAssembly, "Offset");
|
||
|
ArraySegmentConstructorReference = Resolvers.ResolveMethod(ArraySegmentType, CurrentAssembly, ".ctor");
|
||
|
|
||
|
|
||
|
NetworkReaderType = NetAssembly.MainModule.GetType("Mirror.NetworkReader");
|
||
|
NetworkWriterType = NetAssembly.MainModule.GetType("Mirror.NetworkWriter");
|
||
|
|
||
|
NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, CurrentAssembly, "get_active");
|
||
|
NetworkServerGetLocalClientActive = Resolvers.ResolveMethod(NetworkServerType, CurrentAssembly, "get_localClientActive");
|
||
|
NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, CurrentAssembly, "get_active");
|
||
|
|
||
|
CmdDelegateReference = NetAssembly.MainModule.GetType("Mirror.NetworkBehaviour/CmdDelegate");
|
||
|
CmdDelegateConstructor = Resolvers.ResolveMethod(CmdDelegateReference, CurrentAssembly, ".ctor");
|
||
|
CurrentAssembly.MainModule.ImportReference(gameObjectType);
|
||
|
CurrentAssembly.MainModule.ImportReference(transformType);
|
||
|
|
||
|
TypeReference networkIdentityTmp = NetAssembly.MainModule.GetType("Mirror.NetworkIdentity");
|
||
|
NetworkIdentityType = CurrentAssembly.MainModule.ImportReference(networkIdentityTmp);
|
||
|
|
||
|
NetworkBehaviourType = NetAssembly.MainModule.GetType("Mirror.NetworkBehaviour");
|
||
|
NetworkBehaviourType2 = CurrentAssembly.MainModule.ImportReference(NetworkBehaviourType);
|
||
|
NetworkConnectionType = NetAssembly.MainModule.GetType("Mirror.NetworkConnection");
|
||
|
|
||
|
MonoBehaviourType = UnityAssembly.MainModule.GetType("UnityEngine.MonoBehaviour");
|
||
|
ScriptableObjectType = UnityAssembly.MainModule.GetType("UnityEngine.ScriptableObject");
|
||
|
|
||
|
NetworkConnectionType = NetAssembly.MainModule.GetType("Mirror.NetworkConnection");
|
||
|
NetworkConnectionType = CurrentAssembly.MainModule.ImportReference(NetworkConnectionType);
|
||
|
|
||
|
MessageBaseType = NetAssembly.MainModule.GetType("Mirror.MessageBase");
|
||
|
SyncListType = NetAssembly.MainModule.GetType("Mirror.SyncList`1");
|
||
|
SyncSetType = NetAssembly.MainModule.GetType("Mirror.SyncSet`1");
|
||
|
SyncDictionaryType = NetAssembly.MainModule.GetType("Mirror.SyncDictionary`2");
|
||
|
|
||
|
NetworkBehaviourDirtyBitsReference = Resolvers.ResolveProperty(NetworkBehaviourType, CurrentAssembly, "syncVarDirtyBits");
|
||
|
TypeDefinition NetworkWriterPoolType = NetAssembly.MainModule.GetType("Mirror.NetworkWriterPool");
|
||
|
GetPooledWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, CurrentAssembly, "GetWriter");
|
||
|
RecycleWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, CurrentAssembly, "Recycle");
|
||
|
|
||
|
ComponentType = UnityAssembly.MainModule.GetType("UnityEngine.Component");
|
||
|
ClientSceneType = NetAssembly.MainModule.GetType("Mirror.ClientScene");
|
||
|
ReadyConnectionReference = Resolvers.ResolveMethod(ClientSceneType, CurrentAssembly, "get_readyConnection");
|
||
|
|
||
|
getBehaviourIsServer = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "get_isServer");
|
||
|
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SetSyncVar");
|
||
|
setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "setSyncVarHookGuard");
|
||
|
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "getSyncVarHookGuard");
|
||
|
|
||
|
setSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SetSyncVarGameObject");
|
||
|
getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "GetSyncVarGameObject");
|
||
|
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SetSyncVarNetworkIdentity");
|
||
|
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "GetSyncVarNetworkIdentity");
|
||
|
registerCommandDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "RegisterCommandDelegate");
|
||
|
registerRpcDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "RegisterRpcDelegate");
|
||
|
registerEventDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "RegisterEventDelegate");
|
||
|
getTypeReference = Resolvers.ResolveMethod(objectType, CurrentAssembly, "GetType");
|
||
|
getTypeFromHandleReference = Resolvers.ResolveMethod(typeType, CurrentAssembly, "GetTypeFromHandle");
|
||
|
logErrorReference = Resolvers.ResolveMethod(UnityAssembly.MainModule.GetType("UnityEngine.Debug"), CurrentAssembly, "LogError");
|
||
|
logWarningReference = Resolvers.ResolveMethod(UnityAssembly.MainModule.GetType("UnityEngine.Debug"), CurrentAssembly, "LogWarning");
|
||
|
sendCommandInternal = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SendCommandInternal");
|
||
|
sendRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SendRPCInternal");
|
||
|
sendTargetRpcInternal = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SendTargetRPCInternal");
|
||
|
sendEventInternal = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SendEventInternal");
|
||
|
|
||
|
SyncObjectType = CurrentAssembly.MainModule.ImportReference(SyncObjectType);
|
||
|
InitSyncObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "InitSyncObject");
|
||
|
}
|
||
|
|
||
|
public static bool IsNetworkBehaviour(TypeDefinition td)
|
||
|
{
|
||
|
return td.IsDerivedFrom(NetworkBehaviourType);
|
||
|
}
|
||
|
|
||
|
public static bool IsValidTypeToGenerate(TypeDefinition variable)
|
||
|
{
|
||
|
// a valid type is a simple class or struct. so we generate only code for types we dont know, and if they are not inside
|
||
|
// this assembly it must mean that we are trying to serialize a variable outside our scope. and this will fail.
|
||
|
// no need to report an error here, the caller will report a better error
|
||
|
string assembly = CurrentAssembly.MainModule.Name;
|
||
|
return variable.Module.Name == assembly;
|
||
|
}
|
||
|
|
||
|
static void CheckMonoBehaviour(TypeDefinition td)
|
||
|
{
|
||
|
if (td.IsDerivedFrom(MonoBehaviourType))
|
||
|
{
|
||
|
MonoBehaviourProcessor.Process(td);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool CheckNetworkBehaviour(TypeDefinition td)
|
||
|
{
|
||
|
if (!td.IsClass)
|
||
|
return false;
|
||
|
|
||
|
if (!IsNetworkBehaviour(td))
|
||
|
{
|
||
|
CheckMonoBehaviour(td);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// process this and base classes from parent to child order
|
||
|
|
||
|
List<TypeDefinition> behaviourClasses = new List<TypeDefinition>();
|
||
|
|
||
|
TypeDefinition parent = td;
|
||
|
while (parent != null)
|
||
|
{
|
||
|
if (parent.FullName == NetworkBehaviourType.FullName)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
try
|
||
|
{
|
||
|
behaviourClasses.Insert(0, parent);
|
||
|
parent = parent.BaseType.Resolve();
|
||
|
}
|
||
|
catch (AssemblyResolutionException)
|
||
|
{
|
||
|
// this can happen for plugins.
|
||
|
//Console.WriteLine("AssemblyResolutionException: "+ ex.ToString());
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool didWork = false;
|
||
|
foreach (TypeDefinition behaviour in behaviourClasses)
|
||
|
{
|
||
|
didWork |= ProcessNetworkBehaviourType(behaviour);
|
||
|
}
|
||
|
return didWork;
|
||
|
}
|
||
|
|
||
|
static bool CheckMessageBase(TypeDefinition td)
|
||
|
{
|
||
|
if (!td.IsClass)
|
||
|
return false;
|
||
|
|
||
|
bool didWork = false;
|
||
|
|
||
|
// are ANY parent classes MessageBase
|
||
|
TypeReference parent = td.BaseType;
|
||
|
while (parent != null)
|
||
|
{
|
||
|
if (parent.FullName == MessageBaseType.FullName)
|
||
|
{
|
||
|
MessageClassProcessor.Process(td);
|
||
|
didWork = true;
|
||
|
break;
|
||
|
}
|
||
|
try
|
||
|
{
|
||
|
parent = parent.Resolve().BaseType;
|
||
|
}
|
||
|
catch (AssemblyResolutionException)
|
||
|
{
|
||
|
// this can happen for plugins.
|
||
|
//Console.WriteLine("AssemblyResolutionException: "+ ex.ToString());
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// check for embedded types
|
||
|
foreach (TypeDefinition embedded in td.NestedTypes)
|
||
|
{
|
||
|
didWork |= CheckMessageBase(embedded);
|
||
|
}
|
||
|
|
||
|
return didWork;
|
||
|
}
|
||
|
|
||
|
static bool CheckSyncList(TypeDefinition td)
|
||
|
{
|
||
|
if (!td.IsClass)
|
||
|
return false;
|
||
|
|
||
|
bool didWork = false;
|
||
|
|
||
|
// are ANY parent classes SyncListStruct
|
||
|
TypeReference parent = td.BaseType;
|
||
|
while (parent != null)
|
||
|
{
|
||
|
if (parent.FullName.StartsWith(SyncListType.FullName, StringComparison.Ordinal))
|
||
|
{
|
||
|
SyncListProcessor.Process(td);
|
||
|
didWork = true;
|
||
|
break;
|
||
|
}
|
||
|
if (parent.FullName.StartsWith(SyncSetType.FullName, StringComparison.Ordinal))
|
||
|
{
|
||
|
SyncListProcessor.Process(td);
|
||
|
didWork = true;
|
||
|
break;
|
||
|
}
|
||
|
if (parent.FullName.StartsWith(SyncDictionaryType.FullName, StringComparison.Ordinal))
|
||
|
{
|
||
|
SyncDictionaryProcessor.Process(td);
|
||
|
didWork = true;
|
||
|
break;
|
||
|
}
|
||
|
try
|
||
|
{
|
||
|
parent = parent.Resolve().BaseType;
|
||
|
}
|
||
|
catch (AssemblyResolutionException)
|
||
|
{
|
||
|
// this can happen for pluins.
|
||
|
//Console.WriteLine("AssemblyResolutionException: "+ ex.ToString());
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// check for embedded types
|
||
|
foreach (TypeDefinition embedded in td.NestedTypes)
|
||
|
{
|
||
|
didWork |= CheckSyncList(embedded);
|
||
|
}
|
||
|
|
||
|
return didWork;
|
||
|
}
|
||
|
|
||
|
static bool Weave(string assName, IEnumerable<string> dependencies, string unityEngineDLLPath, string mirrorNetDLLPath, string outputDir)
|
||
|
{
|
||
|
using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
|
||
|
using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver }))
|
||
|
{
|
||
|
asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName));
|
||
|
asmResolver.AddSearchDirectory(Helpers.UnityEngineDLLDirectoryName());
|
||
|
asmResolver.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
|
||
|
asmResolver.AddSearchDirectory(Path.GetDirectoryName(mirrorNetDLLPath));
|
||
|
if (dependencies != null)
|
||
|
{
|
||
|
foreach (string path in dependencies)
|
||
|
{
|
||
|
asmResolver.AddSearchDirectory(path);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetupTargetTypes();
|
||
|
System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||
|
ReaderWriterProcessor.ProcessReadersAndWriters(CurrentAssembly);
|
||
|
rwstopwatch.Stop();
|
||
|
Console.WriteLine("Find all reader and writers took " + rwstopwatch.ElapsedMilliseconds + " milliseconds");
|
||
|
|
||
|
ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
|
||
|
Console.WriteLine("Script Module: {0}", moduleDefinition.Name);
|
||
|
|
||
|
// Process each NetworkBehaviour
|
||
|
bool didWork = false;
|
||
|
|
||
|
// We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first.
|
||
|
for (int pass = 0; pass < 2; pass++)
|
||
|
{
|
||
|
System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
|
||
|
foreach (TypeDefinition td in moduleDefinition.Types)
|
||
|
{
|
||
|
if (td.IsClass && td.BaseType.CanBeResolved())
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
if (pass == 0)
|
||
|
{
|
||
|
didWork |= CheckSyncList(td);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
didWork |= CheckNetworkBehaviour(td);
|
||
|
didWork |= CheckMessageBase(td);
|
||
|
}
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
Error(ex.ToString());
|
||
|
throw ex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (WeavingFailed)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
watch.Stop();
|
||
|
Console.WriteLine("Pass: " + pass + " took " + watch.ElapsedMilliseconds + " milliseconds");
|
||
|
}
|
||
|
|
||
|
if (didWork)
|
||
|
{
|
||
|
// this must be done for ALL code, not just NetworkBehaviours
|
||
|
try
|
||
|
{
|
||
|
PropertySiteProcessor.ProcessSitesModule(CurrentAssembly.MainModule);
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
Log.Error("ProcessPropertySites exception: " + e);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (WeavingFailed)
|
||
|
{
|
||
|
//Log.Error("Failed phase II.");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// write to outputDir if specified, otherwise perform in-place write
|
||
|
WriterParameters writeParams = new WriterParameters { WriteSymbols = true };
|
||
|
if (outputDir != null)
|
||
|
{
|
||
|
CurrentAssembly.Write(Helpers.DestinationFileFor(outputDir, assName), writeParams);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CurrentAssembly.Write(writeParams);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public static bool WeaveAssemblies(IEnumerable<string> assemblies, IEnumerable<string> dependencies, string outputDir, string unityEngineDLLPath, string mirrorNetDLLPath)
|
||
|
{
|
||
|
WeavingFailed = false;
|
||
|
WeaveLists = new WeaverLists();
|
||
|
|
||
|
using (UnityAssembly = AssemblyDefinition.ReadAssembly(unityEngineDLLPath))
|
||
|
using (NetAssembly = AssemblyDefinition.ReadAssembly(mirrorNetDLLPath))
|
||
|
{
|
||
|
SetupUnityTypes();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
foreach (string ass in assemblies)
|
||
|
{
|
||
|
if (!Weave(ass, dependencies, unityEngineDLLPath, mirrorNetDLLPath, outputDir))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
Log.Error("Exception :" + e);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|