mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
feature(synclist): allow SyncList of primitive types (#622)
* feature(synclist): allow SyncList of primitive types As it turns out this never really worked: ```cs class SyncListByte : SyncList<byte> {}; ``` You had to write your own serializeItem / deserialize item for native types. This change lifts the restriction, now you can use a synclist of anything that mirror can serialize/deserialize * fix: fix unit tests error messages
This commit is contained in:
parent
aa5e5a104f
commit
6f19489721
@ -60,39 +60,17 @@ static MethodReference GenerateSerialization(TypeDefinition td, TypeReference it
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (FieldDefinition field in itemType.Resolve().Fields)
|
MethodReference writeFunc = Weaver.GetWriteFunc(itemType);
|
||||||
|
if (writeFunc != null)
|
||||||
{
|
{
|
||||||
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
|
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
||||||
continue;
|
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
|
||||||
|
serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
|
||||||
FieldReference importedField = Weaver.CurrentAssembly.MainModule.ImportReference(field);
|
}
|
||||||
TypeDefinition ft = importedField.FieldType.Resolve();
|
else
|
||||||
|
{
|
||||||
if (ft.HasGenericParameters)
|
Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + itemType + "/" + itemType.FullName + "]. [SyncList] member variables must be basic types.");
|
||||||
{
|
return null;
|
||||||
Weaver.Error("GenerateSerialization for " + td.Name + " [" + ft + "/" + ft.FullName + "]. [SyncList] member cannot have generic parameters.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ft.IsInterface)
|
|
||||||
{
|
|
||||||
Weaver.Error("GenerateSerialization for " + td.Name + " [" + ft + "/" + ft.FullName + "]. [SyncList] member cannot be an interface.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodReference writeFunc = Weaver.GetWriteFunc(field.FieldType);
|
|
||||||
if (writeFunc != null)
|
|
||||||
{
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldfld, importedField));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + ft + "/" + ft.FullName + "]. [SyncList] member variables must be basic types.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||||
|
|
||||||
@ -109,50 +87,31 @@ static MethodReference GenerateDeserialization(TypeDefinition td, TypeReference
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodDefinition serializeFunc = new MethodDefinition("DeserializeItem", MethodAttributes.Public |
|
MethodDefinition deserializeFunction = new MethodDefinition("DeserializeItem", MethodAttributes.Public |
|
||||||
MethodAttributes.Virtual |
|
MethodAttributes.Virtual |
|
||||||
MethodAttributes.Public |
|
MethodAttributes.Public |
|
||||||
MethodAttributes.HideBySig,
|
MethodAttributes.HideBySig,
|
||||||
itemType);
|
itemType);
|
||||||
|
|
||||||
serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
deserializeFunction.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
||||||
|
|
||||||
ILProcessor serWorker = serializeFunc.Body.GetILProcessor();
|
ILProcessor serWorker = deserializeFunction.Body.GetILProcessor();
|
||||||
|
|
||||||
serWorker.Body.InitLocals = true;
|
MethodReference readerFunc = Weaver.GetReadFunc(itemType);
|
||||||
serWorker.Body.Variables.Add(new VariableDefinition(itemType));
|
if (readerFunc != null)
|
||||||
|
|
||||||
// init item instance
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Initobj, itemType));
|
|
||||||
|
|
||||||
foreach (FieldDefinition field in itemType.Resolve().Fields)
|
|
||||||
{
|
{
|
||||||
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
|
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
||||||
continue;
|
serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
|
||||||
|
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||||
FieldReference importedField = Weaver.CurrentAssembly.MainModule.ImportReference(field);
|
}
|
||||||
TypeDefinition ft = importedField.FieldType.Resolve();
|
else
|
||||||
|
{
|
||||||
MethodReference readerFunc = Weaver.GetReadFunc(field.FieldType);
|
Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + itemType + "]. [SyncList] member variables must be basic types.");
|
||||||
if (readerFunc != null)
|
return null;
|
||||||
{
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Stfld, importedField));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + ft + "]. [SyncList] member variables must be basic types.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
|
|
||||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
|
||||||
|
|
||||||
td.Methods.Add(serializeFunc);
|
td.Methods.Add(deserializeFunction);
|
||||||
return serializeFunc;
|
return deserializeFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,6 +263,13 @@ public void SyncListMissingParamlessCtor()
|
|||||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
||||||
Assert.That(m_weaverErrors[0], Does.Match("Missing parameter-less constructor"));
|
Assert.That(m_weaverErrors[0], Does.Match("Missing parameter-less constructor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SyncListByteValid() {
|
||||||
|
Assert.That(CompilationFinishedHook.WeaveFailed, Is.False);
|
||||||
|
Assert.That(m_weaverErrors.Count, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region SyncListStruct tests
|
#region SyncListStruct tests
|
||||||
@ -285,25 +292,25 @@ public void SyncListStructGenericGeneric()
|
|||||||
public void SyncListStructMemberGeneric()
|
public void SyncListStructMemberGeneric()
|
||||||
{
|
{
|
||||||
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
||||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
Assert.That(m_weaverErrors.Count, Is.EqualTo(2));
|
||||||
Assert.That(m_weaverErrors[0], Does.Match("member cannot have generic parameters"));
|
Assert.That(m_weaverErrors[0], Is.EqualTo("Mirror.Weaver error: WriteReadFunc for potato [MirrorTest.MirrorTestPlayer/MyGenericStruct`1<System.Single>/MirrorTest.MirrorTestPlayer/MyGenericStruct`1<System.Single>]. Cannot have generic parameters."));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void SyncListStructMemberInterface()
|
public void SyncListStructMemberInterface()
|
||||||
{
|
{
|
||||||
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
||||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
Assert.That(m_weaverErrors.Count, Is.EqualTo(2));
|
||||||
Assert.That(m_weaverErrors[0], Does.Match("member cannot be an interface"));
|
Assert.That(m_weaverErrors[0], Is.EqualTo( "Mirror.Weaver error: WriteReadFunc for potato [MirrorTest.MirrorTestPlayer/IPotato/MirrorTest.MirrorTestPlayer/IPotato]. Cannot be an interface."));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void SyncListStructMemberBasicType()
|
public void SyncListStructMemberBasicType()
|
||||||
{
|
{
|
||||||
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
||||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(2));
|
Assert.That(m_weaverErrors.Count, Is.EqualTo(3));
|
||||||
Assert.That(m_weaverErrors[0], Does.Match("please make sure to use a valid type"));
|
Assert.That(m_weaverErrors[0], Does.Match("please make sure to use a valid type"));
|
||||||
Assert.That(m_weaverErrors[1], Does.Match("member variables must be basic types"));
|
Assert.That(m_weaverErrors[1], Does.Match("Mirror.Weaver error: WriteReadFunc for nonbasicpotato type System.Object no supported"));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user