121 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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;
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|     }
 | |
| 
 | |
| 
 | |
| } |