mirror of
https://github.com/smyalygames/monopoly.git
synced 2025-05-18 14:24:12 +02:00
233 lines
8.1 KiB
C#
233 lines
8.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using Mono.CecilX;
|
|
|
|
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>();
|
|
|
|
public TypeDefinition generateContainerClass;
|
|
|
|
// amount of SyncVars per class. dict<className, amount>
|
|
public Dictionary<string, int> numSyncVars = new Dictionary<string, int>();
|
|
|
|
public int GetSyncVarStart(string className)
|
|
{
|
|
return numSyncVars.ContainsKey(className)
|
|
? numSyncVars[className]
|
|
: 0;
|
|
}
|
|
|
|
public void SetNumSyncVars(string className, int num)
|
|
{
|
|
numSyncVars[className] = num;
|
|
}
|
|
|
|
public WeaverLists()
|
|
{
|
|
generateContainerClass = new TypeDefinition("Mirror", "GeneratedNetworkCode",
|
|
TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Abstract | TypeAttributes.Sealed,
|
|
WeaverTypes.Import<object>());
|
|
}
|
|
}
|
|
|
|
internal static class Weaver
|
|
{
|
|
public static string InvokeRpcPrefix => "InvokeUserCode_";
|
|
|
|
public static WeaverLists WeaveLists { get; private set; }
|
|
public static AssemblyDefinition CurrentAssembly { get; private set; }
|
|
public static bool WeavingFailed { get; private set; }
|
|
public static bool GenerateLogErrors { get; set; }
|
|
|
|
// private properties
|
|
static readonly bool DebugLogEnabled = true;
|
|
|
|
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 void Error(string message, MemberReference mr)
|
|
{
|
|
Log.Error($"{message} (at {mr})");
|
|
WeavingFailed = true;
|
|
}
|
|
|
|
public static void Warning(string message, MemberReference mr)
|
|
{
|
|
Log.Warning($"{message} (at {mr})");
|
|
}
|
|
|
|
|
|
static void CheckMonoBehaviour(TypeDefinition td)
|
|
{
|
|
if (td.IsDerivedFrom<UnityEngine.MonoBehaviour>())
|
|
{
|
|
MonoBehaviourProcessor.Process(td);
|
|
}
|
|
}
|
|
|
|
static bool WeaveNetworkBehavior(TypeDefinition td)
|
|
{
|
|
if (!td.IsClass)
|
|
return false;
|
|
|
|
if (!td.IsDerivedFrom<NetworkBehaviour>())
|
|
{
|
|
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.Is<NetworkBehaviour>())
|
|
{
|
|
break;
|
|
}
|
|
|
|
try
|
|
{
|
|
behaviourClasses.Insert(0, parent);
|
|
parent = parent.BaseType.Resolve();
|
|
}
|
|
catch (AssemblyResolutionException)
|
|
{
|
|
// this can happen for plugins.
|
|
//Console.WriteLine("AssemblyResolutionException: "+ ex.ToString());
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool modified = false;
|
|
foreach (TypeDefinition behaviour in behaviourClasses)
|
|
{
|
|
modified |= new NetworkBehaviourProcessor(behaviour).Process();
|
|
}
|
|
return modified;
|
|
}
|
|
|
|
static bool WeaveModule(ModuleDefinition moduleDefinition)
|
|
{
|
|
try
|
|
{
|
|
bool modified = false;
|
|
|
|
System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
watch.Start();
|
|
foreach (TypeDefinition td in moduleDefinition.Types)
|
|
{
|
|
if (td.IsClass && td.BaseType.CanBeResolved())
|
|
{
|
|
modified |= WeaveNetworkBehavior(td);
|
|
modified |= ServerClientAttributeProcessor.Process(td);
|
|
}
|
|
}
|
|
watch.Stop();
|
|
Console.WriteLine("Weave behaviours and messages took" + watch.ElapsedMilliseconds + " milliseconds");
|
|
|
|
return modified;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Error(ex.ToString());
|
|
throw new Exception(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
static bool Weave(string assName, IEnumerable<string> dependencies)
|
|
{
|
|
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());
|
|
if (dependencies != null)
|
|
{
|
|
foreach (string path in dependencies)
|
|
{
|
|
asmResolver.AddSearchDirectory(path);
|
|
}
|
|
}
|
|
|
|
WeaverTypes.SetupTargetTypes(CurrentAssembly);
|
|
// WeaverList depends on WeaverTypes setup because it uses Import
|
|
WeaveLists = new WeaverLists();
|
|
|
|
|
|
System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
// Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
|
|
bool modified = ReaderWriterProcessor.Process(CurrentAssembly);
|
|
rwstopwatch.Stop();
|
|
Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");
|
|
|
|
ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
|
|
Console.WriteLine($"Script Module: {moduleDefinition.Name}");
|
|
|
|
modified |= WeaveModule(moduleDefinition);
|
|
|
|
if (WeavingFailed)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (modified)
|
|
{
|
|
PropertySiteProcessor.Process(moduleDefinition);
|
|
|
|
// add class that holds read/write functions
|
|
moduleDefinition.Types.Add(WeaveLists.generateContainerClass);
|
|
|
|
ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly);
|
|
|
|
// write to outputDir if specified, otherwise perform in-place write
|
|
WriterParameters writeParams = new WriterParameters { WriteSymbols = true };
|
|
CurrentAssembly.Write(writeParams);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool WeaveAssembly(string assembly, IEnumerable<string> dependencies)
|
|
{
|
|
WeavingFailed = false;
|
|
|
|
try
|
|
{
|
|
return Weave(assembly, dependencies);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error("Exception :" + e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|