mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-03-11 10:14:17 +00:00
use Serialize/Deserialize in weaver
This commit is contained in:
parent
c6c475c344
commit
ff779b2895
@ -269,7 +269,8 @@ namespace Mirror.Weaver
|
||||
GenerateNullCheck(worker, ref WeavingFailed);
|
||||
|
||||
CreateNew(variable, worker, td, ref WeavingFailed);
|
||||
ReadAllFields(variable, worker, ref WeavingFailed);
|
||||
if (!ReadFromDeserialize(td, worker))
|
||||
ReadAllFields(variable, worker, ref WeavingFailed);
|
||||
|
||||
worker.Emit(OpCodes.Ldloc_0);
|
||||
worker.Emit(OpCodes.Ret);
|
||||
@ -317,12 +318,10 @@ namespace Mirror.Weaver
|
||||
// Log.Error($"{variable.Name} can't be deserialized because it has no default constructor. Don't use {variable.Name} in [SyncVar]s, Rpcs, Cmds, etc.", variable);
|
||||
// WeavingFailed = true;
|
||||
// return;
|
||||
var resolvedVariable = variable.Resolve();
|
||||
var anyCtor = resolvedVariable.Methods.First(m => m.IsConstructor);
|
||||
var anyCtor = td.Methods.First(m => m.IsConstructor);
|
||||
ctor = new MethodDefinition(anyCtor.Name, anyCtor.Attributes, anyCtor.ReturnType);
|
||||
var ctorWorker = ctor.Body.GetILProcessor();
|
||||
ctorWorker.Emit(OpCodes.Ret);
|
||||
resolvedVariable.Methods.Add(ctor);
|
||||
ctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
|
||||
td.Methods.Add(ctor);
|
||||
}
|
||||
|
||||
MethodReference ctorRef = assembly.MainModule.ImportReference(ctor);
|
||||
@ -332,6 +331,42 @@ namespace Mirror.Weaver
|
||||
}
|
||||
}
|
||||
|
||||
// try to use Deserialize if this is a message
|
||||
bool ReadFromDeserialize(TypeDefinition klass, ILProcessor worker)
|
||||
{
|
||||
if (!klass.IsDerivedFrom<NetworkMessage>())
|
||||
return false;
|
||||
|
||||
foreach (var method in klass.Methods)
|
||||
{
|
||||
if (method.Name != "Deserialize")
|
||||
continue;
|
||||
|
||||
if (method.Parameters.Count != 1)
|
||||
continue;
|
||||
|
||||
if (!method.Parameters[0].ParameterType.Is<NetworkWriter>())
|
||||
continue;
|
||||
|
||||
if (!method.ReturnType.Is(typeof(void)))
|
||||
continue;
|
||||
|
||||
if (method.HasGenericParameters)
|
||||
continue;
|
||||
|
||||
// todo does this even work?
|
||||
Log.Error($"read using {method}", klass);
|
||||
// mismatched ldloca/ldloc for struct/class combinations is invalid IL, which causes crash at runtime
|
||||
var opcode = klass.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc;
|
||||
worker.Emit(opcode, 0); // the klass
|
||||
worker.Emit(OpCodes.Ldarg_0); // the reader
|
||||
worker.Emit(OpCodes.Callvirt, method);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadAllFields(TypeReference variable, ILProcessor worker, ref bool WeavingFailed)
|
||||
{
|
||||
foreach (FieldDefinition field in variable.FindAllPublicFields())
|
||||
|
@ -216,8 +216,9 @@ namespace Mirror.Weaver
|
||||
if (!variable.Resolve().IsValueType)
|
||||
WriteNullCheck(worker, ref WeavingFailed);
|
||||
|
||||
if (!WriteAllFields(variable, worker, ref WeavingFailed))
|
||||
return null;
|
||||
if (!WriteFromSerialize(variable.Resolve(), worker))
|
||||
if (!WriteAllFields(variable, worker, ref WeavingFailed))
|
||||
return null;
|
||||
|
||||
worker.Emit(OpCodes.Ret);
|
||||
return writerFunc;
|
||||
@ -247,6 +248,40 @@ namespace Mirror.Weaver
|
||||
worker.Emit(OpCodes.Call, GetWriteFunc(weaverTypes.Import<bool>(), ref WeavingFailed));
|
||||
}
|
||||
|
||||
// try to use Serialize if this is a message
|
||||
bool WriteFromSerialize(TypeDefinition klass, ILProcessor worker)
|
||||
{
|
||||
if (!klass.IsDerivedFrom<NetworkMessage>())
|
||||
return false;
|
||||
|
||||
foreach (var method in klass.Methods)
|
||||
{
|
||||
if (method.Name != "Serialize")
|
||||
continue;
|
||||
|
||||
if (method.Parameters.Count != 1)
|
||||
continue;
|
||||
|
||||
if (!method.Parameters[0].ParameterType.Is<NetworkReader>())
|
||||
continue;
|
||||
|
||||
if (!method.ReturnType.Is(typeof(void)))
|
||||
continue;
|
||||
|
||||
if (method.HasGenericParameters)
|
||||
continue;
|
||||
|
||||
// todo does this even work?
|
||||
Log.Error($"write using {method}", klass);
|
||||
worker.Emit(OpCodes.Ldarg_1); // the klass
|
||||
worker.Emit(OpCodes.Ldarg_0); // the writer
|
||||
worker.Emit(OpCodes.Callvirt, method);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find all fields in type and write them
|
||||
bool WriteAllFields(TypeReference variable, ILProcessor worker, ref bool WeavingFailed)
|
||||
{
|
||||
|
@ -196,6 +196,9 @@ namespace QSB.Messaging
|
||||
/// </summary>
|
||||
public abstract class QSBMessageRaw : NetworkMessage
|
||||
{
|
||||
public virtual void Serialize(NetworkWriter writer) { }
|
||||
public virtual void Deserialize(NetworkReader reader) { }
|
||||
|
||||
public abstract void OnReceive();
|
||||
public override string ToString() => GetType().Name;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user