mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-04-17 08:43:30 +00:00
add qnetweaver
This commit is contained in:
parent
bd111f941b
commit
c94e85af64
225
QNetWeaver/Helpers.cs
Normal file
225
QNetWeaver/Helpers.cs
Normal file
@ -0,0 +1,225 @@
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Mdb;
|
||||
using Mono.Cecil.Pdb;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
internal class Helpers
|
||||
{
|
||||
public static string UnityEngineDLLDirectoryName()
|
||||
{
|
||||
var directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
|
||||
return (directoryName == null) ? null : directoryName.Replace("file:\\", "");
|
||||
}
|
||||
|
||||
public static ISymbolReaderProvider GetSymbolReaderProvider(string inputFile)
|
||||
{
|
||||
var text = inputFile.Substring(0, inputFile.Length - 4);
|
||||
ISymbolReaderProvider result;
|
||||
if (File.Exists(text + ".pdb"))
|
||||
{
|
||||
Console.WriteLine("Symbols will be read from " + text + ".pdb");
|
||||
result = new PdbReaderProvider();
|
||||
}
|
||||
else if (File.Exists(text + ".dll.mdb"))
|
||||
{
|
||||
Console.WriteLine("Symbols will be read from " + text + ".dll.mdb");
|
||||
result = new MdbReaderProvider();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No symbols for " + inputFile);
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool InheritsFromSyncList(TypeReference typeRef)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (typeRef.IsValueType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach (var typeReference in Helpers.ResolveInheritanceHierarchy(typeRef))
|
||||
{
|
||||
if (typeReference.IsGenericInstance)
|
||||
{
|
||||
var typeDefinition = typeReference.Resolve();
|
||||
if (typeDefinition.HasGenericParameters && typeDefinition.FullName == Weaver.SyncListType.FullName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IEnumerable<TypeReference> ResolveInheritanceHierarchy(TypeReference type)
|
||||
{
|
||||
if (type.IsValueType)
|
||||
{
|
||||
yield return type;
|
||||
yield return Weaver.valueTypeType;
|
||||
yield return Weaver.objectType;
|
||||
yield break;
|
||||
}
|
||||
while (type != null && type.FullName != Weaver.objectType.FullName)
|
||||
{
|
||||
yield return type;
|
||||
try
|
||||
{
|
||||
var typeDefinition = type.Resolve();
|
||||
if (typeDefinition == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
type = typeDefinition.BaseType;
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
yield return Weaver.objectType;
|
||||
yield break;
|
||||
}
|
||||
|
||||
public static string DestinationFileFor(string outputDir, string assemblyPath)
|
||||
{
|
||||
var fileName = Path.GetFileName(assemblyPath);
|
||||
return Path.Combine(outputDir, fileName);
|
||||
}
|
||||
|
||||
public static string PrettyPrintType(TypeReference type)
|
||||
{
|
||||
string result;
|
||||
if (type.IsGenericInstance)
|
||||
{
|
||||
var genericInstanceType = (GenericInstanceType)type;
|
||||
var text = genericInstanceType.Name.Substring(0, genericInstanceType.Name.Length - 2);
|
||||
var text2 = "<";
|
||||
var text3 = ", ";
|
||||
IEnumerable<TypeReference> genericArguments = genericInstanceType.GenericArguments;
|
||||
result = text + text2 + string.Join(text3, Enumerable.ToArray<string>(Enumerable.Select<TypeReference, string>(genericArguments, new Func<TypeReference, string>(Helpers.PrettyPrintType)))) + ">";
|
||||
}
|
||||
else if (type.HasGenericParameters)
|
||||
{
|
||||
result = type.Name.Substring(0, type.Name.Length - 2) + "<" + string.Join(", ", Enumerable.ToArray<string>(Enumerable.Select<GenericParameter, string>(type.GenericParameters, (GenericParameter x) => x.Name))) + ">";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = type.Name;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ReaderParameters ReaderParameters(string assemblyPath, IEnumerable<string> extraPaths, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string unityUNetDLLPath)
|
||||
{
|
||||
var readerParameters = new ReaderParameters();
|
||||
if (assemblyResolver == null)
|
||||
{
|
||||
assemblyResolver = new DefaultAssemblyResolver();
|
||||
}
|
||||
var addSearchDirectoryHelper = new Helpers.AddSearchDirectoryHelper(assemblyResolver);
|
||||
addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));
|
||||
addSearchDirectoryHelper.AddSearchDirectory(Helpers.UnityEngineDLLDirectoryName());
|
||||
addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
|
||||
addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(unityUNetDLLPath));
|
||||
if (extraPaths != null)
|
||||
{
|
||||
foreach (var directory in extraPaths)
|
||||
{
|
||||
addSearchDirectoryHelper.AddSearchDirectory(directory);
|
||||
}
|
||||
}
|
||||
readerParameters.AssemblyResolver = assemblyResolver;
|
||||
readerParameters.SymbolReaderProvider = Helpers.GetSymbolReaderProvider(assemblyPath);
|
||||
return readerParameters;
|
||||
}
|
||||
|
||||
public static WriterParameters GetWriterParameters(ReaderParameters readParams)
|
||||
{
|
||||
var writerParameters = new WriterParameters();
|
||||
if (readParams.SymbolReaderProvider is PdbReaderProvider)
|
||||
{
|
||||
writerParameters.SymbolWriterProvider = new PdbWriterProvider();
|
||||
}
|
||||
else if (readParams.SymbolReaderProvider is MdbReaderProvider)
|
||||
{
|
||||
writerParameters.SymbolWriterProvider = new MdbWriterProvider();
|
||||
}
|
||||
return writerParameters;
|
||||
}
|
||||
|
||||
public static TypeReference MakeGenericType(TypeReference self, params TypeReference[] arguments)
|
||||
{
|
||||
if (self.GenericParameters.Count != arguments.Length)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
var genericInstanceType = new GenericInstanceType(self);
|
||||
foreach (var item in arguments)
|
||||
{
|
||||
genericInstanceType.GenericArguments.Add(item);
|
||||
}
|
||||
return genericInstanceType;
|
||||
}
|
||||
|
||||
public static MethodReference MakeHostInstanceGeneric(MethodReference self, params TypeReference[] arguments)
|
||||
{
|
||||
var methodReference = new MethodReference(self.Name, self.ReturnType, Helpers.MakeGenericType(self.DeclaringType, arguments))
|
||||
{
|
||||
HasThis = self.HasThis,
|
||||
ExplicitThis = self.ExplicitThis,
|
||||
CallingConvention = self.CallingConvention
|
||||
};
|
||||
foreach (var parameterDefinition in self.Parameters)
|
||||
{
|
||||
methodReference.Parameters.Add(new ParameterDefinition(parameterDefinition.ParameterType));
|
||||
}
|
||||
foreach (var genericParameter in self.GenericParameters)
|
||||
{
|
||||
methodReference.GenericParameters.Add(new GenericParameter(genericParameter.Name, methodReference));
|
||||
}
|
||||
return methodReference;
|
||||
}
|
||||
|
||||
private class AddSearchDirectoryHelper
|
||||
{
|
||||
public AddSearchDirectoryHelper(IAssemblyResolver assemblyResolver)
|
||||
{
|
||||
var method = assemblyResolver.GetType().GetMethod("AddSearchDirectory", (BindingFlags)20, null, new Type[]
|
||||
{
|
||||
typeof(string)
|
||||
}, null);
|
||||
if (method == null)
|
||||
{
|
||||
throw new Exception("Assembly resolver doesn't implement AddSearchDirectory method.");
|
||||
}
|
||||
this._addSearchDirectory = (Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate)Delegate.CreateDelegate(typeof(Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate), assemblyResolver, method);
|
||||
}
|
||||
|
||||
public void AddSearchDirectory(string directory)
|
||||
{
|
||||
this._addSearchDirectory(directory);
|
||||
}
|
||||
|
||||
private readonly Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate _addSearchDirectory;
|
||||
|
||||
private delegate void AddSearchDirectoryDelegate(string directory);
|
||||
}
|
||||
}
|
||||
}
|
24
QNetWeaver/Log.cs
Normal file
24
QNetWeaver/Log.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
public static void Warning(string msg)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine($"WARN : {msg}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
public static void Error(string msg)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||
Console.WriteLine($"ERR : {msg}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
}
|
169
QNetWeaver/MessageClassProcessor.cs
Normal file
169
QNetWeaver/MessageClassProcessor.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
internal class MessageClassProcessor
|
||||
{
|
||||
public MessageClassProcessor(TypeDefinition td)
|
||||
{
|
||||
Weaver.DLog(td, "MessageClassProcessor for " + td.Name, new object[0]);
|
||||
this.m_td = td;
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
Weaver.DLog(this.m_td, "MessageClassProcessor Start", new object[0]);
|
||||
Weaver.ResetRecursionCount();
|
||||
this.GenerateSerialization();
|
||||
if (!Weaver.fail)
|
||||
{
|
||||
this.GenerateDeSerialization();
|
||||
Weaver.DLog(this.m_td, "MessageClassProcessor Done", new object[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateSerialization()
|
||||
{
|
||||
Weaver.DLog(this.m_td, " MessageClass GenerateSerialization", new object[0]);
|
||||
foreach (var methodDefinition in this.m_td.Methods)
|
||||
{
|
||||
if (methodDefinition.Name == "Serialize")
|
||||
{
|
||||
Weaver.DLog(this.m_td, " Abort - is Serialize", new object[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.m_td.Fields.Count != 0)
|
||||
{
|
||||
foreach (var fieldDefinition in this.m_td.Fields)
|
||||
{
|
||||
if (fieldDefinition.FieldType.FullName == this.m_td.FullName)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_td.Name,
|
||||
" [",
|
||||
fieldDefinition.FullName,
|
||||
"]. [MessageBase] member cannot be self referencing."
|
||||
}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
var methodDefinition2 = new MethodDefinition("Serialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType);
|
||||
methodDefinition2.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType)));
|
||||
var ilprocessor = methodDefinition2.Body.GetILProcessor();
|
||||
foreach (var fieldDefinition2 in this.m_td.Fields)
|
||||
{
|
||||
if (!fieldDefinition2.IsStatic && !fieldDefinition2.IsPrivate && !fieldDefinition2.IsSpecialName)
|
||||
{
|
||||
if (fieldDefinition2.FieldType.Resolve().HasGenericParameters)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_td.Name,
|
||||
" [",
|
||||
fieldDefinition2.FieldType,
|
||||
"/",
|
||||
fieldDefinition2.FieldType.FullName,
|
||||
"]. [MessageBase] member cannot have generic parameters."
|
||||
}));
|
||||
return;
|
||||
}
|
||||
if (fieldDefinition2.FieldType.Resolve().IsInterface)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_td.Name,
|
||||
" [",
|
||||
fieldDefinition2.FieldType,
|
||||
"/",
|
||||
fieldDefinition2.FieldType.FullName,
|
||||
"]. [MessageBase] member cannot be an interface."
|
||||
}));
|
||||
return;
|
||||
}
|
||||
var writeFunc = Weaver.GetWriteFunc(fieldDefinition2.FieldType);
|
||||
if (writeFunc == null)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_td.Name,
|
||||
" unknown type [",
|
||||
fieldDefinition2.FieldType,
|
||||
"/",
|
||||
fieldDefinition2.FieldType.FullName,
|
||||
"]. [MessageBase] member variables must be basic types."
|
||||
}));
|
||||
return;
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc));
|
||||
}
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
|
||||
this.m_td.Methods.Add(methodDefinition2);
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateDeSerialization()
|
||||
{
|
||||
Weaver.DLog(this.m_td, " GenerateDeserialization", new object[0]);
|
||||
foreach (var methodDefinition in this.m_td.Methods)
|
||||
{
|
||||
if (methodDefinition.Name == "Deserialize")
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.m_td.Fields.Count != 0)
|
||||
{
|
||||
var methodDefinition2 = new MethodDefinition("Deserialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType);
|
||||
methodDefinition2.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
||||
var ilprocessor = methodDefinition2.Body.GetILProcessor();
|
||||
foreach (var fieldDefinition in this.m_td.Fields)
|
||||
{
|
||||
if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate && !fieldDefinition.IsSpecialName)
|
||||
{
|
||||
var readFunc = Weaver.GetReadFunc(fieldDefinition.FieldType);
|
||||
if (readFunc == null)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateDeSerialization for ",
|
||||
this.m_td.Name,
|
||||
" unknown type [",
|
||||
fieldDefinition.FieldType,
|
||||
"]. [SyncVar] member variables must be basic types."
|
||||
}));
|
||||
return;
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldDefinition));
|
||||
}
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
|
||||
this.m_td.Methods.Add(methodDefinition2);
|
||||
}
|
||||
}
|
||||
|
||||
private TypeDefinition m_td;
|
||||
}
|
||||
}
|
146
QNetWeaver/MonoBehaviourProcessor.cs
Normal file
146
QNetWeaver/MonoBehaviourProcessor.cs
Normal file
@ -0,0 +1,146 @@
|
||||
using Mono.Cecil;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
internal class MonoBehaviourProcessor
|
||||
{
|
||||
public MonoBehaviourProcessor(TypeDefinition td)
|
||||
{
|
||||
this.m_td = td;
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
this.ProcessSyncVars();
|
||||
this.ProcessMethods();
|
||||
}
|
||||
|
||||
private void ProcessSyncVars()
|
||||
{
|
||||
foreach (var fieldDefinition in this.m_td.Fields)
|
||||
{
|
||||
foreach (var customAttribute in fieldDefinition.CustomAttributes)
|
||||
{
|
||||
if (customAttribute.AttributeType.FullName == Weaver.SyncVarType.FullName)
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses [SyncVar] ",
|
||||
fieldDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
}
|
||||
if (Helpers.InheritsFromSyncList(fieldDefinition.FieldType))
|
||||
{
|
||||
Log.Error(string.Format("Script {0} defines field {1} with type {2}, but it's not a NetworkBehaviour", this.m_td.FullName, fieldDefinition.Name, Helpers.PrettyPrintType(fieldDefinition.FieldType)));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessMethods()
|
||||
{
|
||||
foreach (var methodDefinition in this.m_td.Methods)
|
||||
{
|
||||
foreach (var customAttribute in methodDefinition.CustomAttributes)
|
||||
{
|
||||
if (customAttribute.AttributeType.FullName == Weaver.CommandType.FullName)
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses [Command] ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
if (customAttribute.AttributeType.FullName == Weaver.ClientRpcType.FullName)
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses [ClientRpc] ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
if (customAttribute.AttributeType.FullName == Weaver.TargetRpcType.FullName)
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses [TargetRpc] ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
var text = customAttribute.Constructor.DeclaringType.ToString();
|
||||
if (text == "UnityEngine.Networking.ServerAttribute")
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses the attribute [Server] on the method ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
else if (text == "UnityEngine.Networking.ServerCallbackAttribute")
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses the attribute [ServerCallback] on the method ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
else if (text == "UnityEngine.Networking.ClientAttribute")
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses the attribute [Client] on the method ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
else if (text == "UnityEngine.Networking.ClientCallbackAttribute")
|
||||
{
|
||||
Log.Error(string.Concat(new string[]
|
||||
{
|
||||
"Script ",
|
||||
this.m_td.FullName,
|
||||
" uses the attribute [ClientCallback] on the method ",
|
||||
methodDefinition.Name,
|
||||
" but is not a NetworkBehaviour."
|
||||
}));
|
||||
Weaver.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TypeDefinition m_td;
|
||||
}
|
||||
}
|
2092
QNetWeaver/NetworkBehaviourProcessor.cs
Normal file
2092
QNetWeaver/NetworkBehaviourProcessor.cs
Normal file
File diff suppressed because it is too large
Load Diff
65
QNetWeaver/Program.cs
Normal file
65
QNetWeaver/Program.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Start!");
|
||||
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Log.Error("No args supplied!");
|
||||
}
|
||||
|
||||
var unityEngine = args[0];
|
||||
var qnetDLL = args[1];
|
||||
var unetDLL = args[2];
|
||||
var outputDirectory = args[3];
|
||||
var assembly = args[4];
|
||||
|
||||
Program.CheckDLLPath(unityEngine);
|
||||
Program.CheckDLLPath(qnetDLL);
|
||||
Program.CheckOutputDirectory(outputDirectory);
|
||||
Program.CheckAssemblyPath(assembly);
|
||||
Weaver.WeaveAssemblies(assembly, null, null, outputDirectory, unityEngine, qnetDLL, unetDLL);
|
||||
}
|
||||
|
||||
private static void CheckDLLPath(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new Exception("dll could not be located at " + path + "!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckAssemblies(IEnumerable<string> assemblyPaths)
|
||||
{
|
||||
foreach (var assemblyPath in assemblyPaths)
|
||||
{
|
||||
Program.CheckAssemblyPath(assemblyPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckAssemblyPath(string assemblyPath)
|
||||
{
|
||||
if (!File.Exists(assemblyPath))
|
||||
{
|
||||
throw new Exception("Assembly " + assemblyPath + " does not exist!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckOutputDirectory(string outputDir)
|
||||
{
|
||||
if (!Directory.Exists(outputDir))
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
QNetWeaver/Properties/AssemblyInfo.cs
Normal file
36
QNetWeaver/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("QNetWeaver")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("QNetWeaver")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("e23551f3-c095-4f50-8bf7-85bb2661859b")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
72
QNetWeaver/QNetWeaver.csproj
Normal file
72
QNetWeaver/QNetWeaver.csproj
Normal file
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E23551F3-C095-4F50-8BF7-85BB2661859B}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>QNetWeaver</RootNamespace>
|
||||
<AssemblyName>QNetWeaver</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Unity.Cecil">
|
||||
<HintPath>..\..\..\..\..\..\Program Files\Unity\Hub\Editor\2017.4.33f1\Editor\Data\Managed\Unity.Cecil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Cecil.Mdb">
|
||||
<HintPath>..\..\..\..\..\..\Program Files\Unity\Hub\Editor\2017.4.33f1\Editor\Data\Managed\Unity.Cecil.Mdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.Cecil.Pdb">
|
||||
<HintPath>..\..\..\..\..\..\Program Files\Unity\Hub\Editor\2017.4.33f1\Editor\Data\Managed\Unity.Cecil.Pdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Unity.UNetWeaver">
|
||||
<HintPath>..\..\..\..\..\..\Program Files\Unity\Hub\Editor\2017.4.33f1\Editor\Data\Managed\Unity.UNetWeaver.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Helpers.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="MessageClassProcessor.cs" />
|
||||
<Compile Include="MonoBehaviourProcessor.cs" />
|
||||
<Compile Include="NetworkBehaviourProcessor.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SyncListStructProcessor.cs" />
|
||||
<Compile Include="Weaver.cs" />
|
||||
<Compile Include="WeaverLists.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
302
QNetWeaver/SyncListStructProcessor.cs
Normal file
302
QNetWeaver/SyncListStructProcessor.cs
Normal file
@ -0,0 +1,302 @@
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
internal class SyncListStructProcessor
|
||||
{
|
||||
public SyncListStructProcessor(TypeDefinition typeDef)
|
||||
{
|
||||
Weaver.DLog(typeDef, "SyncListStructProcessor for " + typeDef.Name, new object[0]);
|
||||
this.m_TypeDef = typeDef;
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
var genericInstanceType = (GenericInstanceType)this.m_TypeDef.BaseType;
|
||||
if (genericInstanceType.GenericArguments.Count == 0)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error("SyncListStructProcessor no generic args");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_ItemType = Weaver.scriptDef.MainModule.ImportReference(genericInstanceType.GenericArguments[0]);
|
||||
Weaver.DLog(this.m_TypeDef, "SyncListStructProcessor Start item:" + this.m_ItemType.FullName, new object[0]);
|
||||
Weaver.ResetRecursionCount();
|
||||
var methodReference = this.GenerateSerialization();
|
||||
if (!Weaver.fail)
|
||||
{
|
||||
var methodReference2 = this.GenerateDeserialization();
|
||||
if (methodReference2 != null && methodReference != null)
|
||||
{
|
||||
this.GenerateReadFunc(methodReference2);
|
||||
this.GenerateWriteFunc(methodReference);
|
||||
Weaver.DLog(this.m_TypeDef, "SyncListStructProcessor Done", new object[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateReadFunc(MethodReference readItemFunc)
|
||||
{
|
||||
var text = "_ReadStruct" + this.m_TypeDef.Name + "_";
|
||||
if (this.m_TypeDef.DeclaringType != null)
|
||||
{
|
||||
text += this.m_TypeDef.DeclaringType.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
text += "None";
|
||||
}
|
||||
var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType);
|
||||
methodDefinition.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
||||
methodDefinition.Parameters.Add(new ParameterDefinition("instance", ParameterAttributes.None, this.m_TypeDef));
|
||||
methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type));
|
||||
methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type));
|
||||
methodDefinition.Body.InitLocals = true;
|
||||
var ilprocessor = methodDefinition.Body.GetILProcessor();
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkReadUInt16));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
var method = Helpers.MakeHostInstanceGeneric(Weaver.SyncListClear, new TypeReference[]
|
||||
{
|
||||
this.m_ItemType
|
||||
});
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1));
|
||||
var instruction = ilprocessor.Create(OpCodes.Nop);
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Br, instruction));
|
||||
var instruction2 = ilprocessor.Create(OpCodes.Nop);
|
||||
ilprocessor.Append(instruction2);
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, readItemFunc));
|
||||
var self = Weaver.ResolveMethod(Weaver.SyncListStructType, "AddInternal");
|
||||
var method2 = Helpers.MakeHostInstanceGeneric(self, new TypeReference[]
|
||||
{
|
||||
this.m_ItemType
|
||||
});
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Add));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_U2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1));
|
||||
ilprocessor.Append(instruction);
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Blt, instruction2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
|
||||
Weaver.RegisterReadByReferenceFunc(this.m_TypeDef.FullName, methodDefinition);
|
||||
}
|
||||
|
||||
private void GenerateWriteFunc(MethodReference writeItemFunc)
|
||||
{
|
||||
var text = "_WriteStruct" + this.m_TypeDef.GetElementType().Name + "_";
|
||||
if (this.m_TypeDef.DeclaringType != null)
|
||||
{
|
||||
text += this.m_TypeDef.DeclaringType.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
text += "None";
|
||||
}
|
||||
var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType);
|
||||
methodDefinition.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType)));
|
||||
methodDefinition.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(this.m_TypeDef)));
|
||||
methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type));
|
||||
methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type));
|
||||
methodDefinition.Body.InitLocals = true;
|
||||
var ilprocessor = methodDefinition.Body.GetILProcessor();
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
var self = Weaver.ResolveMethod(Weaver.SyncListStructType, "get_Count");
|
||||
var method = Helpers.MakeHostInstanceGeneric(self, new TypeReference[]
|
||||
{
|
||||
this.m_ItemType
|
||||
});
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriteUInt16));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1));
|
||||
var instruction = ilprocessor.Create(OpCodes.Nop);
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Br, instruction));
|
||||
var instruction2 = ilprocessor.Create(OpCodes.Nop);
|
||||
ilprocessor.Append(instruction2);
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1));
|
||||
var self2 = Weaver.ResolveMethod(Weaver.SyncListStructType, "GetItem");
|
||||
var method2 = Helpers.MakeHostInstanceGeneric(self2, new TypeReference[]
|
||||
{
|
||||
this.m_ItemType
|
||||
});
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, writeItemFunc));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Add));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_U2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1));
|
||||
ilprocessor.Append(instruction);
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Blt, instruction2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
|
||||
Weaver.RegisterWriteFunc(this.m_TypeDef.FullName, methodDefinition);
|
||||
}
|
||||
|
||||
private MethodReference GenerateSerialization()
|
||||
{
|
||||
Weaver.DLog(this.m_TypeDef, " SyncListStruct GenerateSerialization", new object[0]);
|
||||
foreach (var methodDefinition in this.m_TypeDef.Methods)
|
||||
{
|
||||
if (methodDefinition.Name == "SerializeItem")
|
||||
{
|
||||
Weaver.DLog(this.m_TypeDef, " Abort - is SerializeItem", new object[0]);
|
||||
return methodDefinition;
|
||||
}
|
||||
}
|
||||
var methodDefinition2 = new MethodDefinition("SerializeItem", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType);
|
||||
methodDefinition2.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType)));
|
||||
methodDefinition2.Parameters.Add(new ParameterDefinition("item", ParameterAttributes.None, this.m_ItemType));
|
||||
var ilprocessor = methodDefinition2.Body.GetILProcessor();
|
||||
MethodReference result;
|
||||
if (this.m_ItemType.IsGenericInstance)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error("GenerateSerialization for " + Helpers.PrettyPrintType(this.m_ItemType) + " failed. Struct passed into SyncListStruct<T> can't have generic parameters");
|
||||
result = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var fieldDefinition in this.m_ItemType.Resolve().Fields)
|
||||
{
|
||||
if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate && !fieldDefinition.IsSpecialName)
|
||||
{
|
||||
var fieldReference = Weaver.scriptDef.MainModule.ImportReference(fieldDefinition);
|
||||
var typeDefinition = fieldReference.FieldType.Resolve();
|
||||
if (typeDefinition.HasGenericParameters)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_TypeDef.Name,
|
||||
" [",
|
||||
typeDefinition,
|
||||
"/",
|
||||
typeDefinition.FullName,
|
||||
"]. UNet [MessageBase] member cannot have generic parameters."
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
if (typeDefinition.IsInterface)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_TypeDef.Name,
|
||||
" [",
|
||||
typeDefinition,
|
||||
"/",
|
||||
typeDefinition.FullName,
|
||||
"]. UNet [MessageBase] member cannot be an interface."
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
var writeFunc = Weaver.GetWriteFunc(fieldDefinition.FieldType);
|
||||
if (writeFunc == null)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateSerialization for ",
|
||||
this.m_TypeDef.Name,
|
||||
" unknown type [",
|
||||
typeDefinition,
|
||||
"/",
|
||||
typeDefinition.FullName,
|
||||
"]. UNet [MessageBase] member variables must be basic types."
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_2));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldReference));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc));
|
||||
}
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
|
||||
this.m_TypeDef.Methods.Add(methodDefinition2);
|
||||
result = methodDefinition2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MethodReference GenerateDeserialization()
|
||||
{
|
||||
Weaver.DLog(this.m_TypeDef, " GenerateDeserialization", new object[0]);
|
||||
foreach (var methodDefinition in this.m_TypeDef.Methods)
|
||||
{
|
||||
if (methodDefinition.Name == "DeserializeItem")
|
||||
{
|
||||
return methodDefinition;
|
||||
}
|
||||
}
|
||||
var methodDefinition2 = new MethodDefinition("DeserializeItem", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, this.m_ItemType);
|
||||
methodDefinition2.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
||||
var ilprocessor = methodDefinition2.Body.GetILProcessor();
|
||||
ilprocessor.Body.InitLocals = true;
|
||||
ilprocessor.Body.Variables.Add(new VariableDefinition(this.m_ItemType));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca, 0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Initobj, this.m_ItemType));
|
||||
foreach (var fieldDefinition in this.m_ItemType.Resolve().Fields)
|
||||
{
|
||||
if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate && !fieldDefinition.IsSpecialName)
|
||||
{
|
||||
var fieldReference = Weaver.scriptDef.MainModule.ImportReference(fieldDefinition);
|
||||
var typeDefinition = fieldReference.FieldType.Resolve();
|
||||
var readFunc = Weaver.GetReadFunc(fieldDefinition.FieldType);
|
||||
if (readFunc == null)
|
||||
{
|
||||
Weaver.fail = true;
|
||||
Log.Error(string.Concat(new object[]
|
||||
{
|
||||
"GenerateDeserialization for ",
|
||||
this.m_TypeDef.Name,
|
||||
" unknown type [",
|
||||
typeDefinition,
|
||||
"]. UNet [SyncVar] member variables must be basic types."
|
||||
}));
|
||||
return null;
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca, 0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldReference));
|
||||
}
|
||||
}
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0));
|
||||
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
|
||||
this.m_TypeDef.Methods.Add(methodDefinition2);
|
||||
return methodDefinition2;
|
||||
}
|
||||
|
||||
private TypeDefinition m_TypeDef;
|
||||
|
||||
private TypeReference m_ItemType;
|
||||
}
|
||||
}
|
1918
QNetWeaver/Weaver.cs
Normal file
1918
QNetWeaver/Weaver.cs
Normal file
File diff suppressed because it is too large
Load Diff
41
QNetWeaver/WeaverLists.cs
Normal file
41
QNetWeaver/WeaverLists.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using Mono.Cecil;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace QNetWeaver
|
||||
{
|
||||
internal class WeaverLists
|
||||
{
|
||||
public List<FieldDefinition> replacedFields = new List<FieldDefinition>();
|
||||
|
||||
public List<MethodDefinition> replacementProperties = new List<MethodDefinition>();
|
||||
|
||||
public List<FieldDefinition> netIdFields = new List<FieldDefinition>();
|
||||
|
||||
public List<MethodDefinition> replacedMethods = new List<MethodDefinition>();
|
||||
|
||||
public List<MethodDefinition> replacementMethods = new List<MethodDefinition>();
|
||||
|
||||
public HashSet<string> replacementMethodNames = new HashSet<string>();
|
||||
|
||||
public List<EventDefinition> replacedEvents = new List<EventDefinition>();
|
||||
|
||||
public List<MethodDefinition> replacementEvents = new List<MethodDefinition>();
|
||||
|
||||
public Dictionary<string, MethodReference> readFuncs;
|
||||
|
||||
public Dictionary<string, MethodReference> readByReferenceFuncs;
|
||||
|
||||
public Dictionary<string, MethodReference> writeFuncs;
|
||||
|
||||
public List<MethodDefinition> generatedReadFunctions = new List<MethodDefinition>();
|
||||
|
||||
public List<MethodDefinition> generatedWriteFunctions = new List<MethodDefinition>();
|
||||
|
||||
public TypeDefinition generateContainerClass;
|
||||
|
||||
public Dictionary<string, int> numSyncVars = new Dictionary<string, int>();
|
||||
}
|
||||
}
|
6
QSB.sln
6
QSB.sln
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantumUNET", "QuantumUNET\
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSBTests", "QSBTests\QSBTests.csproj", "{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QNetWeaver", "QNetWeaver\QNetWeaver.csproj", "{E23551F3-C095-4F50-8BF7-85BB2661859B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -27,6 +29,10 @@ Global
|
||||
{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -125,14 +125,10 @@ namespace QSB.Animation.Player
|
||||
|
||||
private void InitCrouchSync()
|
||||
{
|
||||
_crouchSync = gameObject.AddComponent<CrouchSync>();
|
||||
_crouchSync.Init(this, _playerController, VisibleAnimator);
|
||||
_crouchSync = GetComponent<CrouchSync>();
|
||||
_crouchSync.Init(_playerController, VisibleAnimator);
|
||||
}
|
||||
|
||||
public void SendCrouch(float value = 0) => QSBEventManager.FireEvent(EventNames.QSBCrouch, value);
|
||||
|
||||
public void HandleCrouch(float value) => _crouchSync.CrouchParam.Target = value;
|
||||
|
||||
private void SuitUp()
|
||||
{
|
||||
QSBEventManager.FireEvent(EventNames.QSBChangeAnimType, PlayerId, AnimationType.PlayerSuited);
|
||||
|
@ -1,6 +1,10 @@
|
||||
using QuantumUNET;
|
||||
using QSB.Utility;
|
||||
using QuantumUNET;
|
||||
using QuantumUNET.Transport;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB.Animation.Player
|
||||
{
|
||||
@ -8,21 +12,17 @@ namespace QSB.Animation.Player
|
||||
{
|
||||
public AnimFloatParam CrouchParam { get; } = new AnimFloatParam();
|
||||
|
||||
private const float CrouchSendInterval = 0.1f;
|
||||
private const float CrouchChargeThreshold = 0.01f;
|
||||
private const float CrouchSmoothTime = 0.05f;
|
||||
private const int CrouchLayerIndex = 1;
|
||||
|
||||
private float _sendTimer;
|
||||
private float _lastSentJumpChargeFraction;
|
||||
|
||||
private AnimationSync _animationSync;
|
||||
private PlayerCharacterController _playerController;
|
||||
private Animator _bodyAnim;
|
||||
|
||||
public void Init(AnimationSync animationSync, PlayerCharacterController playerController, Animator bodyAnim)
|
||||
[SyncVar]
|
||||
private float _crouchValue;
|
||||
|
||||
public void Init(PlayerCharacterController playerController, Animator bodyAnim)
|
||||
{
|
||||
_animationSync = animationSync;
|
||||
_playerController = playerController;
|
||||
_bodyAnim = bodyAnim;
|
||||
}
|
||||
@ -43,19 +43,8 @@ namespace QSB.Animation.Player
|
||||
{
|
||||
return;
|
||||
}
|
||||
_sendTimer += Time.unscaledDeltaTime;
|
||||
if (_sendTimer < CrouchSendInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var jumpChargeFraction = _playerController.GetJumpChargeFraction();
|
||||
if (Math.Abs(jumpChargeFraction - _lastSentJumpChargeFraction) < CrouchChargeThreshold)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_animationSync.SendCrouch(jumpChargeFraction);
|
||||
_lastSentJumpChargeFraction = jumpChargeFraction;
|
||||
_sendTimer = 0;
|
||||
_crouchValue = jumpChargeFraction;
|
||||
}
|
||||
|
||||
private void SyncRemoteCrouch()
|
||||
@ -64,6 +53,7 @@ namespace QSB.Animation.Player
|
||||
{
|
||||
return;
|
||||
}
|
||||
CrouchParam.Target = _crouchValue;
|
||||
CrouchParam.Smooth(CrouchSmoothTime);
|
||||
var jumpChargeFraction = CrouchParam.Current;
|
||||
_bodyAnim.SetLayerWeight(CrouchLayerIndex, jumpChargeFraction);
|
||||
|
@ -1,32 +0,0 @@
|
||||
using QSB.Events;
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
|
||||
namespace QSB.Animation.Player.Events
|
||||
{
|
||||
public class CrouchEvent : QSBEvent<FloatMessage>
|
||||
{
|
||||
public override EventType Type => EventType.Crouch;
|
||||
|
||||
public override void SetupListener() => GlobalMessenger<float>.AddListener(EventNames.QSBCrouch, Handler);
|
||||
public override void CloseListener() => GlobalMessenger<float>.RemoveListener(EventNames.QSBCrouch, Handler);
|
||||
|
||||
private void Handler(float value) => SendEvent(CreateMessage(value));
|
||||
|
||||
private FloatMessage CreateMessage(float value) => new FloatMessage
|
||||
{
|
||||
AboutId = LocalPlayerId,
|
||||
Value = value
|
||||
};
|
||||
|
||||
public override void OnReceiveRemote(bool server, FloatMessage message)
|
||||
{
|
||||
if (!QSBCore.HasWokenUp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var animationSync = QSBPlayerManager.GetSyncObject<AnimationSync>(message.AboutId);
|
||||
animationSync?.HandleCrouch(message.Value);
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,6 @@
|
||||
public static string QSBServerTime = "QSBServerTime";
|
||||
public static string QSBStartLift = "QSBStartLift";
|
||||
public static string QSBGeyserState = "QSBGeyserState";
|
||||
public static string QSBCrouch = "QSBAnimTrigger";
|
||||
public static string QSBOrbSlot = "QSBOrbSlot";
|
||||
public static string QSBOrbUser = "QSBOrbUser";
|
||||
public static string QSBConversation = "QSBConversation";
|
||||
|
@ -3,7 +3,6 @@
|
||||
public enum EventType
|
||||
{
|
||||
ServerTime,
|
||||
Crouch,
|
||||
PlayerState,
|
||||
PlayerStatesRequest,
|
||||
FlashlightActiveChange,
|
||||
|
@ -46,7 +46,6 @@ namespace QSB.Events
|
||||
new PlayerStatesRequestEvent(),
|
||||
new ServerSendPlayerStatesEvent(),
|
||||
new ChangeAnimTypeEvent(),
|
||||
new CrouchEvent(),
|
||||
new ServerTimeEvent(),
|
||||
new PlayerEntangledEvent(),
|
||||
new PlayerKickEvent(),
|
||||
|
@ -115,7 +115,6 @@
|
||||
<Compile Include="Animation\Player\AnimationType.cs" />
|
||||
<Compile Include="Animation\Player\Events\AnimationTriggerEvent.cs" />
|
||||
<Compile Include="Animation\Player\Events\AnimationTriggerMessage.cs" />
|
||||
<Compile Include="Animation\Player\Events\CrouchEvent.cs" />
|
||||
<Compile Include="Animation\Player\AnimatorMirror.cs" />
|
||||
<Compile Include="Animation\Player\AnimControllerPatch.cs" />
|
||||
<Compile Include="Animation\Player\AnimFloatParam.cs" />
|
||||
@ -356,9 +355,7 @@
|
||||
<Version>1.1.8</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Syncs\VariableSync\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy /e /i /y "$(TargetDir)*" "$(OwmlDir)\Mods\$(ProjectName)"
|
||||
|
@ -1,12 +1,12 @@
|
||||
using OWML.Utils;
|
||||
using QuantumUNET;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB
|
||||
{
|
||||
public class QSBNetworkLobby : NetworkBehaviour
|
||||
public class QSBNetworkLobby : QNetworkBehaviour
|
||||
{
|
||||
public bool CanEditName { get; set; }
|
||||
public string PlayerName { get; private set; }
|
||||
|
@ -57,6 +57,7 @@ namespace QSB
|
||||
SetupNetworkTransform(playerPrefab);
|
||||
playerPrefab.AddComponent<PlayerTransformSync>();
|
||||
playerPrefab.AddComponent<AnimationSync>();
|
||||
playerPrefab.AddComponent<CrouchSync>();
|
||||
playerPrefab.AddComponent<WakeUpSync>();
|
||||
playerPrefab.AddComponent<InstrumentsManager>();
|
||||
|
||||
|
@ -474,7 +474,7 @@ namespace QuantumUNET.Components
|
||||
{
|
||||
if ((num & (1U << j)) != 0U)
|
||||
{
|
||||
s_UpdateWriter.StartMessage(8);
|
||||
s_UpdateWriter.StartMessage(QMsgType.UpdateVars);
|
||||
s_UpdateWriter.Write(NetId);
|
||||
var flag = false;
|
||||
foreach (var networkBehaviour in m_NetworkBehaviours)
|
||||
|
@ -9,7 +9,6 @@ namespace QuantumUNET.Components
|
||||
public class QNetworkTransform : QNetworkBehaviour
|
||||
{
|
||||
public float SendInterval { get; set; } = 0.05f;
|
||||
public float LastSyncTime { get; private set; }
|
||||
|
||||
private float _lastClientSendTime;
|
||||
protected Vector3 _prevPosition;
|
||||
@ -26,9 +25,6 @@ namespace QuantumUNET.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStartServer()
|
||||
=> LastSyncTime = 0f;
|
||||
|
||||
public override bool OnSerialize(QNetworkWriter writer, bool initialState)
|
||||
{
|
||||
if (!initialState)
|
||||
@ -56,7 +52,6 @@ namespace QuantumUNET.Components
|
||||
}
|
||||
}
|
||||
DeserializeTransform(reader);
|
||||
LastSyncTime = Time.time;
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +172,6 @@ namespace QuantumUNET.Components
|
||||
if (netMsg.Connection.ClientOwnedObjects.Contains(networkInstanceId))
|
||||
{
|
||||
component.DeserializeTransform(netMsg.Reader);
|
||||
component.LastSyncTime = Time.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -207,8 +201,5 @@ namespace QuantumUNET.Components
|
||||
|
||||
public override float GetNetworkSendInterval()
|
||||
=> SendInterval;
|
||||
|
||||
public override void OnStartAuthority()
|
||||
=> LastSyncTime = 0f;
|
||||
}
|
||||
}
|
8
UnityProject/Assets/Chert.meta
Normal file
8
UnityProject/Assets/Chert.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63b53d3892f588e42809e7eb48ebf18c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
WeavedFiles/QSB.dll
Normal file
BIN
WeavedFiles/QSB.dll
Normal file
Binary file not shown.
BIN
WeavedFiles/QSB.dll.mdb
Normal file
BIN
WeavedFiles/QSB.dll.mdb
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user