feature: SyncList now support structs (#614)

Previously, if you wanted a synclist of structures,  you would do:  SyncListSTRUCT<MyStruct>
Now you can use SyncList<MyStruct>
SyncListSTRUCT is left there, but obsolete
This commit is contained in:
Paul Pacheco 2019-03-20 06:45:46 -05:00 committed by vis2k
parent 22640b5e62
commit 9d043182bf
10 changed files with 27 additions and 26 deletions

View File

@ -1,10 +1,10 @@
// this class generates OnSerialize/OnDeserialize for SyncListStructs // this class generates OnSerialize/OnDeserialize for SyncLists
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
namespace Mirror.Weaver namespace Mirror.Weaver
{ {
static class SyncListStructProcessor static class SyncListProcessor
{ {
public static void Process(TypeDefinition td) public static void Process(TypeDefinition td)
{ {
@ -12,12 +12,12 @@ public static void Process(TypeDefinition td)
GenericInstanceType gt = (GenericInstanceType)td.BaseType; GenericInstanceType gt = (GenericInstanceType)td.BaseType;
if (gt.GenericArguments.Count == 0) if (gt.GenericArguments.Count == 0)
{ {
Weaver.Error("SyncListStructProcessor no generic args"); Weaver.Error("SyncListProcessor no generic args");
return; return;
} }
TypeReference itemType = Weaver.CurrentAssembly.MainModule.ImportReference(gt.GenericArguments[0]); TypeReference itemType = Weaver.CurrentAssembly.MainModule.ImportReference(gt.GenericArguments[0]);
Weaver.DLog(td, "SyncListStructProcessor Start item:" + itemType.FullName); Weaver.DLog(td, "SyncListProcessor Start item:" + itemType.FullName);
Weaver.ResetRecursionCount(); Weaver.ResetRecursionCount();
MethodReference writeItemFunc = GenerateSerialization(td, itemType); MethodReference writeItemFunc = GenerateSerialization(td, itemType);
@ -31,7 +31,7 @@ public static void Process(TypeDefinition td)
if (readItemFunc == null || writeItemFunc == null) if (readItemFunc == null || writeItemFunc == null)
return; return;
Weaver.DLog(td, "SyncListStructProcessor Done"); Weaver.DLog(td, "SyncListProcessor Done");
} }
// serialization of individual element // serialization of individual element
@ -56,7 +56,7 @@ static MethodReference GenerateSerialization(TypeDefinition td, TypeReference it
if (itemType.IsGenericInstance) if (itemType.IsGenericInstance)
{ {
Weaver.Error("GenerateSerialization for " + Helpers.PrettyPrintType(itemType) + " failed. Struct passed into SyncListStruct<T> can't have generic parameters"); Weaver.Error("GenerateSerialization for " + Helpers.PrettyPrintType(itemType) + " failed. Struct passed into SyncList<T> can't have generic parameters");
return null; return null;
} }
@ -70,13 +70,13 @@ static MethodReference GenerateSerialization(TypeDefinition td, TypeReference it
if (ft.HasGenericParameters) if (ft.HasGenericParameters)
{ {
Weaver.Error("GenerateSerialization for " + td.Name + " [" + ft + "/" + ft.FullName + "]. [SyncListStruct] member cannot have generic parameters."); Weaver.Error("GenerateSerialization for " + td.Name + " [" + ft + "/" + ft.FullName + "]. [SyncList] member cannot have generic parameters.");
return null; return null;
} }
if (ft.IsInterface) if (ft.IsInterface)
{ {
Weaver.Error("GenerateSerialization for " + td.Name + " [" + ft + "/" + ft.FullName + "]. [SyncListStruct] member cannot be an interface."); Weaver.Error("GenerateSerialization for " + td.Name + " [" + ft + "/" + ft.FullName + "]. [SyncList] member cannot be an interface.");
return null; return null;
} }
@ -90,7 +90,7 @@ static MethodReference GenerateSerialization(TypeDefinition td, TypeReference it
} }
else else
{ {
Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + ft + "/" + ft.FullName + "]. [SyncListStruct] member variables must be basic types."); Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + ft + "/" + ft.FullName + "]. [SyncList] member variables must be basic types.");
return null; return null;
} }
} }
@ -144,7 +144,7 @@ static MethodReference GenerateDeserialization(TypeDefinition td, TypeReference
} }
else else
{ {
Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + ft + "]. [SyncListStruct] member variables must be basic types."); Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + ft + "]. [SyncList] member variables must be basic types.");
return null; return null;
} }
} }

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 93397916cae0248bc9294f863fa49f81 guid: 4f3445268e45d437fac325837aff3246
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -63,7 +63,7 @@ class Weaver
public static TypeReference NetworkConnectionType; public static TypeReference NetworkConnectionType;
public static TypeReference MessageBaseType; public static TypeReference MessageBaseType;
public static TypeReference SyncListStructType; public static TypeReference SyncListType;
public static MethodReference NetworkBehaviourDirtyBitsReference; public static MethodReference NetworkBehaviourDirtyBitsReference;
public static TypeReference NetworkClientType; public static TypeReference NetworkClientType;
@ -1124,7 +1124,7 @@ static void SetupTargetTypes()
NetworkConnectionType = CurrentAssembly.MainModule.ImportReference(NetworkConnectionType); NetworkConnectionType = CurrentAssembly.MainModule.ImportReference(NetworkConnectionType);
MessageBaseType = NetAssembly.MainModule.GetType("Mirror.MessageBase"); MessageBaseType = NetAssembly.MainModule.GetType("Mirror.MessageBase");
SyncListStructType = NetAssembly.MainModule.GetType("Mirror.SyncListSTRUCT`1"); SyncListType = NetAssembly.MainModule.GetType("Mirror.SyncList`1");
NetworkBehaviourDirtyBitsReference = Resolvers.ResolveProperty(NetworkBehaviourType, CurrentAssembly, "syncVarDirtyBits"); NetworkBehaviourDirtyBitsReference = Resolvers.ResolveProperty(NetworkBehaviourType, CurrentAssembly, "syncVarDirtyBits");
@ -1347,7 +1347,7 @@ static bool CheckMessageBase(TypeDefinition td)
return didWork; return didWork;
} }
static bool CheckSyncListStruct(TypeDefinition td) static bool CheckSyncList(TypeDefinition td)
{ {
if (!td.IsClass) if (!td.IsClass)
return false; return false;
@ -1358,9 +1358,9 @@ static bool CheckSyncListStruct(TypeDefinition td)
TypeReference parent = td.BaseType; TypeReference parent = td.BaseType;
while (parent != null) while (parent != null)
{ {
if (parent.FullName.StartsWith(SyncListStructType.FullName)) if (parent.FullName.StartsWith(SyncListType.FullName))
{ {
SyncListStructProcessor.Process(td); SyncListProcessor.Process(td);
didWork = true; didWork = true;
break; break;
} }
@ -1379,7 +1379,7 @@ static bool CheckSyncListStruct(TypeDefinition td)
// check for embedded types // check for embedded types
foreach (TypeDefinition embedded in td.NestedTypes) foreach (TypeDefinition embedded in td.NestedTypes)
{ {
didWork |= CheckSyncListStruct(embedded); didWork |= CheckSyncList(embedded);
} }
return didWork; return didWork;
@ -1414,7 +1414,7 @@ static bool Weave(string assName, IEnumerable<string> dependencies, IAssemblyRes
{ {
if (pass == 0) if (pass == 0)
{ {
didWork |= CheckSyncListStruct(td); didWork |= CheckSyncList(td);
} }
else else
{ {

View File

@ -43,6 +43,7 @@ public class SyncListBool : SyncList<bool>
// in Unity 2019.1. // in Unity 2019.1.
// //
// TODO rename back to SyncListStruct after 2019.1! // TODO rename back to SyncListStruct after 2019.1!
[Obsolete("Use SyncList<MyStruct> instead")]
public class SyncListSTRUCT<T> : SyncList<T> where T : struct public class SyncListSTRUCT<T> : SyncList<T> where T : struct
{ {
protected override void SerializeItem(NetworkWriter writer, T item) {} protected override void SerializeItem(NetworkWriter writer, T item) {}
@ -86,8 +87,8 @@ struct Change
// so we need to skip them // so we need to skip them
int changesAhead = 0; int changesAhead = 0;
protected abstract void SerializeItem(NetworkWriter writer, T item); protected virtual void SerializeItem(NetworkWriter writer, T item) { }
protected abstract T DeserializeItem(NetworkReader reader); protected virtual T DeserializeItem(NetworkReader reader) => default(T);
public bool IsDirty => Changes.Count > 0; public bool IsDirty => Changes.Count > 0;

View File

@ -278,7 +278,7 @@ public void SyncListStructGenericGeneric()
{ {
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(1));
Assert.That(m_weaverErrors[0], Does.Match("Struct passed into SyncListStruct<T> can't have generic parameters")); Assert.That(m_weaverErrors[0], Does.Match("Struct passed into SyncList<T> can't have generic parameters"));
} }
[Test] [Test]

View File

@ -20,7 +20,7 @@ struct MyStruct
MyGenericStruct<MyPODStruct> potato; MyGenericStruct<MyPODStruct> potato;
} }
class MyStructClass : SyncListSTRUCT<MyGenericStruct<float>> {}; class MyStructClass : SyncList<MyGenericStruct<float>> {};
MyStructClass harpseals; MyStructClass harpseals;
} }

View File

@ -16,7 +16,7 @@ struct MyStruct
public object nonbasicpotato; public object nonbasicpotato;
} }
class MyStructClass : SyncListSTRUCT<MyStruct> class MyStructClass : SyncList<MyStruct>
{ {
int potatoCount; int potatoCount;
public MyStructClass(int numberOfPotatoes) public MyStructClass(int numberOfPotatoes)

View File

@ -20,7 +20,7 @@ struct MyStruct
public MyGenericStruct<float> potato; public MyGenericStruct<float> potato;
} }
class MyStructClass : SyncListSTRUCT<MyStruct> {}; class MyStructClass : SyncList<MyStruct> {};
MyStructClass harpseals; MyStructClass harpseals;
} }

View File

@ -15,7 +15,7 @@ struct MyStruct
public IPotato potato; public IPotato potato;
} }
class MyStructClass : SyncListSTRUCT<MyStruct> {}; class MyStructClass : SyncList<MyStruct> {};
MyStructClass harpseals; MyStructClass harpseals;
} }

View File

@ -11,7 +11,7 @@ struct MyStruct
float floatingpotato; float floatingpotato;
double givemetwopotatoes; double givemetwopotatoes;
} }
class MyStructClass : SyncListSTRUCT<MyStruct> {}; class MyStructClass : SyncList<MyStruct> {};
MyStructClass Foo; MyStructClass Foo;
} }
} }