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;
|
||||
}
|
||||
|
||||
foreach (FieldDefinition field in itemType.Resolve().Fields)
|
||||
MethodReference writeFunc = Weaver.GetWriteFunc(itemType);
|
||||
if (writeFunc != null)
|
||||
{
|
||||
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
|
||||
continue;
|
||||
|
||||
FieldReference importedField = Weaver.CurrentAssembly.MainModule.ImportReference(field);
|
||||
TypeDefinition ft = importedField.FieldType.Resolve();
|
||||
|
||||
if (ft.HasGenericParameters)
|
||||
{
|
||||
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.Ldarg_1));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + itemType + "/" + itemType.FullName + "]. [SyncList] member variables must be basic types.");
|
||||
return null;
|
||||
}
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
|
||||
@ -109,50 +87,31 @@ static MethodReference GenerateDeserialization(TypeDefinition td, TypeReference
|
||||
return m;
|
||||
}
|
||||
|
||||
MethodDefinition serializeFunc = new MethodDefinition("DeserializeItem", MethodAttributes.Public |
|
||||
MethodDefinition deserializeFunction = new MethodDefinition("DeserializeItem", MethodAttributes.Public |
|
||||
MethodAttributes.Virtual |
|
||||
MethodAttributes.Public |
|
||||
MethodAttributes.HideBySig,
|
||||
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;
|
||||
serWorker.Body.Variables.Add(new VariableDefinition(itemType));
|
||||
|
||||
// init item instance
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Initobj, itemType));
|
||||
|
||||
foreach (FieldDefinition field in itemType.Resolve().Fields)
|
||||
MethodReference readerFunc = Weaver.GetReadFunc(itemType);
|
||||
if (readerFunc != null)
|
||||
{
|
||||
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
|
||||
continue;
|
||||
|
||||
FieldReference importedField = Weaver.CurrentAssembly.MainModule.ImportReference(field);
|
||||
TypeDefinition ft = importedField.FieldType.Resolve();
|
||||
|
||||
MethodReference readerFunc = Weaver.GetReadFunc(field.FieldType);
|
||||
if (readerFunc != 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.Ldarg_1));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + itemType + "]. [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);
|
||||
return serializeFunc;
|
||||
td.Methods.Add(deserializeFunction);
|
||||
return deserializeFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,6 +263,13 @@ public void SyncListMissingParamlessCtor()
|
||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
||||
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
|
||||
|
||||
#region SyncListStruct tests
|
||||
@ -285,25 +292,25 @@ public void SyncListStructGenericGeneric()
|
||||
public void SyncListStructMemberGeneric()
|
||||
{
|
||||
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
||||
Assert.That(m_weaverErrors[0], Does.Match("member cannot have generic parameters"));
|
||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(2));
|
||||
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]
|
||||
public void SyncListStructMemberInterface()
|
||||
{
|
||||
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
||||
Assert.That(m_weaverErrors[0], Does.Match("member cannot be an interface"));
|
||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(2));
|
||||
Assert.That(m_weaverErrors[0], Is.EqualTo( "Mirror.Weaver error: WriteReadFunc for potato [MirrorTest.MirrorTestPlayer/IPotato/MirrorTest.MirrorTestPlayer/IPotato]. Cannot be an interface."));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SyncListStructMemberBasicType()
|
||||
{
|
||||
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[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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user