Skip to content

Commit

Permalink
feat: Users may provide custom serializers for any type (#1153)
Browse files Browse the repository at this point in the history
* feat: Users may provide custom serializers for any type

* Relax rules for rpc parameters to support user provided serializers

* Improve error messages

* Fixed component types

* Adjusted tests
  • Loading branch information
paulpach authored and miwarnec committed Oct 19, 2019
1 parent ae5c92b commit 9cb309e
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 105 deletions.
12 changes: 0 additions & 12 deletions Assets/Mirror/Editor/Weaver/Processors/MessageClassProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,6 @@ static void GenerateSerialization(TypeDefinition td)
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
continue;

if (field.FieldType.Resolve().HasGenericParameters && !field.FieldType.FullName.StartsWith("System.ArraySegment`1", System.StringComparison.Ordinal))
{
Weaver.Error($"{field} cannot have generic type {field.FieldType}. Consider creating a class that derives the generic type");
return;
}

if (field.FieldType.Resolve().IsInterface)
{
Weaver.Error($"{field} has unsupported type. Use a concrete class instead of interface {field.FieldType}");
return;
}

MethodReference writeFunc = Writers.GetWriteFunc(field.FieldType);
if (writeFunc != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,31 +684,13 @@ public static bool ProcessMethodsValidateParameters(MethodReference md, CustomAt
Weaver.Error($"{md} cannot have optional parameters");
return false;
}
if (p.ParameterType.Resolve().IsAbstract)
{
Weaver.Error($"{md} has invalid parameter {p}. Use concrete type instead of abstract type {p.ParameterType}");
return false;
}
if (p.ParameterType.IsByReference)
{
Weaver.Error($"{md} has invalid parameter {p}. Use supported type instead of reference type {p.ParameterType}");
return false;
}
// TargetRPC is an exception to this rule and can have a NetworkConnection as first parameter
if (p.ParameterType.FullName == Weaver.NetworkConnectionType.FullName &&
!(ca.AttributeType.FullName == Weaver.TargetRpcType.FullName && i == 0))
{
Weaver.Error($"{md} has invalid parameer {p}. Cannot pass NeworkConnections");
return false;
}
if (p.ParameterType.Resolve().IsDerivedFrom(Weaver.ComponentType))
{
if (p.ParameterType.FullName != Weaver.NetworkIdentityType.FullName)
{
Weaver.Error($"{md} has invalid parameter {p}. Cannot pass components in remote method calls");
return false;
}
}
}
return true;
}
Expand Down
24 changes: 0 additions & 24 deletions Assets/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,36 +294,12 @@ public static void ProcessSyncVars(TypeDefinition td, List<FieldDefinition> sync
{
TypeDefinition resolvedField = fd.FieldType.Resolve();

if (resolvedField.IsDerivedFrom(Weaver.NetworkBehaviourType))
{
Weaver.Error($"{fd} has invalid type. SyncVars cannot be NetworkBehaviours");
return;
}

if (resolvedField.IsDerivedFrom(Weaver.ScriptableObjectType))
{
Weaver.Error($"{fd} has invalid type. SyncVars cannot be scriptable objects");
return;
}

if ((fd.Attributes & FieldAttributes.Static) != 0)
{
Weaver.Error($"{fd} cannot be static");
return;
}

if (resolvedField.HasGenericParameters)
{
Weaver.Error($"{fd} has invalid type. SyncVars cannot have generic parameters");
return;
}

if (resolvedField.IsInterface)
{
Weaver.Error($"{fd} has invalid type. Use a concrete type instead of interface {fd.FieldType}");
return;
}

if (fd.FieldType.IsArray)
{
Weaver.Error($"{fd} has invalid type. Use SyncLists instead of arrays");
Expand Down
23 changes: 21 additions & 2 deletions Assets/Mirror/Editor/Weaver/Readers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,30 @@ public static MethodReference GetReadFunc(TypeReference variable, int recursionC
Weaver.Error($"{variable} is not a supported type");
return null;
}

if (td.IsDerivedFrom(Weaver.ScriptableObjectType))
{
Weaver.Error($"Cannot generate reader for scriptable object {variable}. Use a supported type or provide a custom reader");
return null;
}
if (td.IsDerivedFrom(Weaver.ComponentType))
{
Weaver.Error($"Cannot generate reader for component type {variable}. Use a supported type or provide a custom reader");
return null;
}
if (variable.IsByReference)
{
// error??
Weaver.Error($"{variable} is not a supported reference type");
Weaver.Error($"Cannot pass type {variable} by reference");
return null;
}
if (td.HasGenericParameters && !td.FullName.StartsWith("System.ArraySegment`1", System.StringComparison.Ordinal))
{
Weaver.Error($"Cannot generate reader for generic variable {variable}. Use a concrete type or provide a custom reader");
return null;
}
if (td.IsInterface)
{
Weaver.Error($"Cannot generate reader for interface variable {variable}. Use a concrete type or provide a custom reader");
return null;
}

Expand Down
41 changes: 28 additions & 13 deletions Assets/Mirror/Editor/Weaver/Writers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,37 @@ public static MethodReference GetWriteFunc(TypeReference variable, int recursion
if (variable.IsByReference)
{
// error??
Weaver.Error($"{variable} has unsupported type. Use one of Mirror supported types instead");
Weaver.Error($"Cannot pass {variable} by reference");
return null;
}
TypeDefinition td = variable.Resolve();
if (td == null)
{
Weaver.Error($"{variable} is not a supported type. Use a supported type or provide a custom writer");
return null;
}
if (td.IsDerivedFrom(Weaver.ScriptableObjectType))
{
Weaver.Error($"Cannot generate writer for scriptable object {variable}. Use a supported type or provide a custom writer");
return null;
}
if (td.IsDerivedFrom(Weaver.ComponentType))
{
Weaver.Error($"Cannot generate writer for component type {variable}. Use a supported type or provide a custom writer");
return null;
}
if (td.HasGenericParameters && !td.FullName.StartsWith("System.ArraySegment`1", System.StringComparison.Ordinal))
{
Weaver.Error($"Cannot generate writer for generic type {variable}. Use a concrete type or provide a custom writer");
return null;
}
if (td.IsInterface)
{
Weaver.Error($"Cannot generate writer for interface {variable}. Use a concrete type or provide a custom writer");
return null;
}


MethodDefinition newWriterFunc;

if (variable.IsArray)
Expand Down Expand Up @@ -112,18 +139,6 @@ static MethodDefinition GenerateStructWriterFunction(TypeReference variable, int
if (field.IsStatic || field.IsPrivate)
continue;

if (field.FieldType.Resolve().HasGenericParameters)
{
Weaver.Error($"{field} has unsupported type. Create a derived class instead of using generics");
return null;
}

if (field.FieldType.Resolve().IsInterface)
{
Weaver.Error($"{field} has unsupported type. Use a concrete class instead of an interface");
return null;
}

MethodReference writeFunc = GetWriteFunc(field.FieldType, recursionCount + 1);
if (writeFunc != null)
{
Expand Down

0 comments on commit 9cb309e

Please sign in to comment.