This repository has been archived on 2023-09-13. You can view files and clone it, but cannot push or open issues or pull requests.
station_obscurum_unity/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs

121 lines
4.7 KiB
C#
Raw Normal View History

2023-05-31 17:32:21 +02:00
using FishNet.CodeGenerating.Helping.Extension;
using FishNet.CodeGenerating.Processing;
using FishNet.Object.Synchronizing;
using FishNet.Object.Synchronizing.Internal;
using MonoFN.Cecil;
using MonoFN.Cecil.Rocks;
using System;
using System.Collections.Generic;
namespace FishNet.CodeGenerating.Helping
{
internal class CreatedSyncVarGenerator : CodegenBase
{
private readonly Dictionary<string, CreatedSyncVar> _createdSyncVars = new Dictionary<string, CreatedSyncVar>();
#region Relfection references.
private TypeReference _syncBase_TypeRef;
internal TypeReference SyncVar_TypeRef;
private MethodReference _syncVar_Constructor_MethodRef;
#endregion
#region Const.
private const string GETVALUE_NAME = "GetValue";
private const string SETVALUE_NAME = "SetValue";
#endregion
/* //feature add and test the dirty boolean changes
* eg... instead of base.Dirty()
* do if (!base.Dirty()) return false;
* See synclist for more info. */
/// <summary>
/// Imports references needed by this helper.
/// </summary>
/// <param name="moduleDef"></param>
/// <returns></returns>
public override bool ImportReferences()
{
SyncVar_TypeRef = base.ImportReference(typeof(SyncVar<>));
MethodDefinition svConstructor = SyncVar_TypeRef.GetFirstConstructor(base.Session, true);
_syncVar_Constructor_MethodRef = base.ImportReference(svConstructor);
Type syncBaseType = typeof(SyncBase);
_syncBase_TypeRef = base.ImportReference(syncBaseType);
return true;
}
/// <summary>
/// Gets and optionally creates data for SyncVar<typeOfField>
/// </summary>
/// <param name="dataTr"></param>
/// <returns></returns>
internal CreatedSyncVar GetCreatedSyncVar(FieldDefinition originalFd, bool createMissing)
{
TypeReference dataTr = originalFd.FieldType;
TypeDefinition dataTd = dataTr.CachedResolve(base.Session);
string typeHash = dataTr.FullName + dataTr.IsArray.ToString();
if (_createdSyncVars.TryGetValue(typeHash, out CreatedSyncVar createdSyncVar))
{
return createdSyncVar;
}
else
{
if (!createMissing)
return null;
base.ImportReference(dataTd);
GenericInstanceType syncVarGit = SyncVar_TypeRef.MakeGenericInstanceType(new TypeReference[] { dataTr });
TypeReference genericDataTr = syncVarGit.GenericArguments[0];
//Make sure can serialize.
bool canSerialize = base.GetClass<GeneralHelper>().HasSerializerAndDeserializer(genericDataTr, true);
if (!canSerialize)
{
base.LogError($"SyncVar {originalFd.Name} data type {genericDataTr.FullName} does not support serialization. Use a supported type or create a custom serializer.");
return null;
}
//Set needed methods from syncbase.
MethodReference setSyncIndexMr;
MethodReference genericSyncVarCtor = _syncVar_Constructor_MethodRef.MakeHostInstanceGeneric(base.Session, syncVarGit);
if (!base.GetClass<NetworkBehaviourSyncProcessor>().SetSyncBaseMethods(_syncBase_TypeRef.CachedResolve(base.Session), out setSyncIndexMr, out _))
return null;
MethodReference setValueMr = null;
MethodReference getValueMr = null;
foreach (MethodDefinition md in SyncVar_TypeRef.CachedResolve(base.Session).Methods)
{
//GetValue.
if (md.Name == GETVALUE_NAME)
{
MethodReference mr = base.ImportReference(md);
getValueMr = mr.MakeHostInstanceGeneric(base.Session, syncVarGit);
}
//SetValue.
else if (md.Name == SETVALUE_NAME)
{
MethodReference mr = base.ImportReference(md);
setValueMr = mr.MakeHostInstanceGeneric(base.Session, syncVarGit);
}
}
if (setValueMr == null || getValueMr == null)
return null;
CreatedSyncVar csv = new CreatedSyncVar(syncVarGit, dataTd, getValueMr, setValueMr, setSyncIndexMr, null, genericSyncVarCtor);
_createdSyncVars.Add(typeHash, csv);
return csv;
}
}
}
}