Skip to content

Commit

Permalink
feat: Custom readers and writers
Browse files Browse the repository at this point in the history
  • Loading branch information
paulpach committed Apr 15, 2019
1 parent c73ed24 commit 92b3e98
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 1 deletion.
6 changes: 6 additions & 0 deletions Assets/Mirror/Editor/Weaver/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Mono.Cecil;

namespace Mirror.Weaver
Expand Down Expand Up @@ -112,5 +113,10 @@ public static bool CanBeResolved(this TypeReference parent)
}
return true;
}

public static bool HasAttributte(this ICustomAttributeProvider attributeProvider, string typeName )
{
return attributeProvider.CustomAttributes.Any(attr => attr.AttributeType.FullName == typeName);
}
}
}
56 changes: 55 additions & 1 deletion Assets/Mirror/Editor/Weaver/Readers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ public static MethodReference GetReadFunc(TypeReference variable, int recursionC
{
return GetReadFunc(td.GetEnumUnderlyingType(), recursionCount);
}
else if (GetCustomReader(td, out MethodReference customReaderFunc))
{
readFuncs[variable.FullName] = customReaderFunc;
return customReaderFunc;
}
else
{
newReaderFunc = GenerateStructReadFunction(variable, recursionCount);
Expand All @@ -112,6 +117,54 @@ public static MethodReference GetReadFunc(TypeReference variable, int recursionC
return newReaderFunc;
}

/*
* Finds OnDeserialize functions provided by the user, and uses them as readers
* For example:
*
* class ScriptableQuest
* {
* public static Dictionary<int, ScriptableQuest> quests = new Dictionary<int, ScriptableQuest>();
*
* [NetworkReader]
* public static ScriptableQuest OnDeserialize(NetworkReader reader)
* {
* int id = reader.ReadInt32();
* return quests[id];
* }
* }
*/
static bool GetCustomReader(TypeDefinition td, out MethodReference newReaderFunc)
{
newReaderFunc = default;

foreach (MethodDefinition md in td.Methods)
{
if (md.IsStatic && md.HasAttributte("Mirror.NetworkReaderAttribute"))
{
if (md.Parameters.Count != 1)
{
Weaver.Error($"{md.FullName} should be static and receive only a NetworkReader");
return false;
}

if (md.Parameters[0].ParameterType.FullName != Weaver.NetworkReaderDef.FullName)
{
Weaver.Error($"{md.FullName} should be static and receive only a NetworkReader");
return false;
}
if (md.ReturnType.Resolve() != td)
{
Weaver.Error($"{md.FullName} should be static and return ${td.FullName}");
return false;
}

newReaderFunc = Weaver.CurrentAssembly.MainModule.ImportReference(md);
return true;
}
}
return false;
}

static void RegisterReadFunc(string name, MethodDefinition newReaderFunc)
{
readFuncs[name] = newReaderFunc;
Expand Down Expand Up @@ -295,4 +348,5 @@ static MethodDefinition GenerateStructReadFunction(TypeReference variable, int r

}

}
}

59 changes: 59 additions & 0 deletions Assets/Mirror/Editor/Weaver/Writers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ public static MethodReference GetWriteFunc(TypeReference variable, int recursion
{
return GetWriteFunc(variable.Resolve().GetEnumUnderlyingType(), recursionCount);
}
else if (GetCustomWriter(variable.Resolve(), out MethodReference customWriterFunc))
{
writeFuncs[variable.FullName] = customWriterFunc;
return customWriterFunc;
}
else
{
newWriterFunc = GenerateStructWriterFunction(variable, recursionCount);
Expand All @@ -106,6 +111,60 @@ public static MethodReference GetWriteFunc(TypeReference variable, int recursion
return newWriterFunc;
}

/*
* Finds OnSerialize functions provided by the user, and uses them as readers
* For example:
*
* class ScriptableQuest
* {
* public int Id { get; set; }
*
* [NetworkWriter]
* public static void OnSerialize(NetworkWriter writer, ScripableQuest quest)
* {
* writer.Write(quest.Id);
* }
* }
*/
static bool GetCustomWriter(TypeDefinition td, out MethodReference newWriterFunc)
{
newWriterFunc = default;

foreach (MethodDefinition md in td.Methods)
{
if (md.IsStatic && md.HasAttributte("Mirror.NetworkWriterAttribute"))
{
if (md.Parameters.Count != 2)
{
Weaver.Error($"{md.FullName} should be static and receive NetworkWriter and ${td.FullName}");
return false;
}

if (md.Parameters[0].ParameterType.FullName != Weaver.NetworkWriterDef.FullName)
{
Weaver.Error($"{md.FullName} should be static and receive NetworkWriter and ${td.FullName}");
return false;
}

if (md.Parameters[1].ParameterType.FullName != td.FullName)
{
Weaver.Error($"{md.FullName} should be static and receive NetworkWriter and ${td.FullName}");
return false;
}

if (md.ReturnType.Resolve().FullName != Weaver.voidType.FullName)
{
Weaver.Error($"{md.FullName} should be void static");
return false;
}

newWriterFunc = Weaver.CurrentAssembly.MainModule.ImportReference(md);
return true;
}
}
return false;
}

static void RegisterWriteFunc(string name, MethodDefinition newWriterFunc)
{
writeFuncs[name] = newWriterFunc;
Expand Down
6 changes: 6 additions & 0 deletions Assets/Mirror/Runtime/CustomAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,10 @@ public class ClientCallbackAttribute : Attribute {}

// For Scene property Drawer
public class SceneAttribute : PropertyAttribute {}

[AttributeUsage(AttributeTargets.Method)]
public class NetworkWriterAttribute : Attribute { }

[AttributeUsage(AttributeTargets.Method)]
public class NetworkReaderAttribute : Attribute { }
}

0 comments on commit 92b3e98

Please sign in to comment.