Skip to content

Commit b4b00df

Browse files
author
FirstGearGames
committed
4.6.6
- Fixed UniversalTickSmoother moving incorrectly with non-Vector3.one scales. - Fixed despawning root NetworkObjects with pooling causing nested NetworkObjects to not respawn automatically. - Fixed conditional NullReferenceCondition in SceneCondition. - Fixed nested runtime NetworkObjects not having their parent unset when their runtime parent was pooled. - Fixed possible NullReferenceException within generated comparers for reference types. - Fixed prediction reconciles corrupting class instance memory. - Fixed NetworkTransform.ComponentConfiguration incorrectly making rigidbodies kinematic. - Fixed limited memory leak on server related to predicted spawning. - Fixed failed Predicted Spawns potentially pooling on clients, when expected to destroy. - Fixed DefualtObjectPool now calls ResetState on nested NetworkObjects as well. - Fixed possibility of nested NetworkObjects with modified InitializationOrder initializing before their parents. - Fixed nested NetworkObjects not spawning when pooling. - Improved logging for NetworkObject ObjectId fetching. - Improved UniversalTickSmoother.SetSmootherProperties now allows specifying if for owner or spectator. - Improved reduced NetworkBehaviour memory allocations. - Improved Predicition attributed methods no longer need to be private. - Improved ReserializenetworkObjects now uses Configuration settings when searching for prefabs. - Added LoadSceneParameters to supported automatically serialized types. - Added ObjectPool.AddPrefabObjects which returns added objects (#863). - Added DefaultObjectPool.ClearPool(NetworkObject) to clear cache for specified NetworkObject type. - Changed reverted NetworkObjects despawning when disabled. - Changed restructured file paths; this may require you to delete FishNet before importing this version. - Changed Tugboat.StopSocketsOnThread now defaulted to false.
1 parent eef15ff commit b4b00df

File tree

99 files changed

+8996
-7888
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+8996
-7888
lines changed

Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using UnityEngine;
8+
using UnityEngine.SceneManagement;
89

910
namespace FishNet.CodeGenerating.Helping.Extension
1011
{
@@ -100,6 +101,9 @@ public static IEnumerable<PropertyDefinition> FindAllPublicProperties(this TypeD
100101
/// </summary>
101102
private static bool IsExcluded(TypeDefinition typeDef, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null)
102103
{
104+
if (typeDef.FullName == typeof(LoadSceneParameters).FullName)
105+
return false;
106+
103107
if (excludedBaseTypes != null)
104108
{
105109
foreach (System.Type t in excludedBaseTypes)

Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,58 @@ void CreateGenericInstanceComparer()
11881188
void CreateClassOrStructComparer()
11891189
{
11901190
//Class or struct.
1191-
Instruction exitMethodInst = processor.Create(OpCodes.Ldc_I4_0);
1191+
Instruction falseLdcInst = processor.Create(OpCodes.Ldc_I4_0);
1192+
1193+
//Non-value type null check.
1194+
if (!dataTr.IsValueType)
1195+
{
1196+
GeneralHelper gh = base.GetClass<GeneralHelper>();
1197+
1198+
Instruction checkNullAndNotNullInst = Instruction.Create(OpCodes.Nop);
1199+
1200+
VariableDefinition isNullV0 = gh.CreateVariable(comparerMd, typeof(bool));
1201+
VariableDefinition isNullV1 = gh.CreateVariable(comparerMd, typeof(bool));
1202+
1203+
//isNull0 = (value0 == null);
1204+
processor.Emit(OpCodes.Ldarg, v0Pd);
1205+
processor.Emit(OpCodes.Ldnull);
1206+
processor.Emit(OpCodes.Ceq);
1207+
processor.Emit(OpCodes.Stloc, isNullV0);
1208+
//isNull1 = (value1 == null);
1209+
processor.Emit(OpCodes.Ldarg, v1Pd);
1210+
processor.Emit(OpCodes.Ldnull);
1211+
processor.Emit(OpCodes.Ceq);
1212+
processor.Emit(OpCodes.Stloc, isNullV1);
1213+
1214+
//If (isNull0 && isNull1) return true;
1215+
processor.Emit(OpCodes.Ldloc, isNullV0);
1216+
processor.Emit(OpCodes.Ldloc, isNullV1);
1217+
processor.Emit(OpCodes.And);
1218+
processor.Emit(OpCodes.Brfalse, checkNullAndNotNullInst);
1219+
processor.Emit(OpCodes.Ldc_I4_1);
1220+
processor.Emit(OpCodes.Ret);
1221+
//Skip past ret here.
1222+
processor.Append(checkNullAndNotNullInst);
1223+
1224+
//bool isNullOpposing = (isNull0 != isNull1);
1225+
VariableDefinition isNullOpposingVd = gh.CreateVariable(comparerMd, typeof(bool));
1226+
processor.Emit(OpCodes.Ldloc, isNullV0);
1227+
processor.Emit(OpCodes.Ldloc, isNullV1);
1228+
processor.Emit(OpCodes.Ceq);
1229+
processor.Emit(OpCodes.Ldc_I4_0);
1230+
processor.Emit(OpCodes.Ceq);
1231+
processor.Emit(OpCodes.Stloc, isNullOpposingVd);
1232+
1233+
1234+
Instruction checkPropertiesInst = Instruction.Create(OpCodes.Nop);
1235+
//if (isNullOpposing) return false;
1236+
processor.Emit(OpCodes.Ldloc, isNullOpposingVd);
1237+
processor.Emit(OpCodes.Brfalse, checkPropertiesInst);
1238+
processor.Emit(OpCodes.Ldc_I4_0);
1239+
processor.Emit(OpCodes.Ret);
1240+
//Skip past ret here.
1241+
processor.Append(checkPropertiesInst);
1242+
}
11921243

11931244
//Fields.
11941245
foreach (FieldDefinition fieldDef in dataTr.FindAllSerializableFields(base.Session, null, WriterProcessor.EXCLUDED_ASSEMBLY_PREFIXES))
@@ -1203,7 +1254,7 @@ void CreateClassOrStructComparer()
12031254
processor.Emit(OpCodes.Ldfld, fr);
12041255
FinishTypeReferenceCompare(fieldDef.FieldType);
12051256
}
1206-
1257+
12071258
//Properties.
12081259
foreach (PropertyDefinition propertyDef in dataTr.FindAllSerializableProperties(base.Session, null, WriterProcessor.EXCLUDED_ASSEMBLY_PREFIXES))
12091260
{
@@ -1217,14 +1268,14 @@ void CreateClassOrStructComparer()
12171268
processor.Emit(OpCodes.Call, getMr);
12181269
FinishTypeReferenceCompare(propertyDef.PropertyType);
12191270
}
1220-
1271+
12211272
//Return true;
12221273
processor.Emit(OpCodes.Ldc_I4_1);
12231274
processor.Emit(OpCodes.Ret);
1224-
processor.Append(exitMethodInst);
1275+
processor.Append(falseLdcInst);
12251276
processor.Emit(OpCodes.Ret);
12261277

1227-
1278+
12281279
void FinishTypeReferenceCompare(TypeReference tr)
12291280
{
12301281
/* If a class or struct see if it already has a comparer
@@ -1240,7 +1291,7 @@ void FinishTypeReferenceCompare(TypeReference tr)
12401291
{
12411292
MethodDefinition cMd = CreateEqualityComparer(tr);
12421293
processor.Emit(OpCodes.Call, cMd);
1243-
processor.Emit(OpCodes.Brfalse, exitMethodInst);
1294+
processor.Emit(OpCodes.Brfalse, falseLdcInst);
12441295
}
12451296
//Call existing.
12461297
else
@@ -1255,14 +1306,14 @@ void FinishTypeReferenceCompare(TypeReference tr)
12551306
{
12561307
MethodReference mr = base.ImportReference(cMd);
12571308
processor.Emit(OpCodes.Call, mr);
1258-
processor.Emit(OpCodes.Brfalse, exitMethodInst);
1309+
processor.Emit(OpCodes.Brfalse, falseLdcInst);
12591310
}
12601311
}
12611312
}
12621313
//Value types do not need to check custom comparers.
12631314
else
12641315
{
1265-
processor.Emit(OpCodes.Bne_Un, exitMethodInst);
1316+
processor.Emit(OpCodes.Bne_Un, falseLdcInst);
12661317
}
12671318
}
12681319
}

Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ internal class NetworkBehaviourHelper : CodegenBase
3333
public MethodReference Replicate_Replay_Start_MethodRef;
3434
public MethodReference Replicate_Current_MethodRef;
3535
public MethodReference Reconcile_Client_MethodRef;
36-
public MethodReference Reconcile_Client_Local_MethodRef;
36+
public MethodReference Reconcile_Current_MethodRef;
3737
public MethodReference ClearReplicateCache_Internal_MethodRef;
3838
public MethodReference Replicate_Replay_MethodRef;
3939
public MethodReference Reconcile_Reader_MethodRef;
@@ -136,10 +136,10 @@ public override bool ImportReferences()
136136
Reconcile_Reader_MethodRef = base.ImportReference(mi);
137137
else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Server))
138138
Reconcile_Server_MethodRef = base.ImportReference(mi);
139-
else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Client))
139+
else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Client))
140140
Reconcile_Client_MethodRef = base.ImportReference(mi);
141-
else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Client_Local))
142-
Reconcile_Client_Local_MethodRef = base.ImportReference(mi);
141+
else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Current))
142+
Reconcile_Current_MethodRef = base.ImportReference(mi);
143143
else if (mi.Name == nameof(NetworkBehaviour.ClearReplicateCache_Internal))
144144
ClearReplicateCache_Internal_MethodRef = base.ImportReference(mi);
145145
}

Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
using FishNet.CodeGenerating.Processing;
66
using FishNet.CodeGenerating.Processing.Rpc;
77
using FishNet.Configuring;
8-
using FishNet.Editing.Upgrading;
9-
using FishNet.Serializing.Helping;
108
using MonoFN.Cecil;
119
using MonoFN.Cecil.Cil;
1210
using System;
@@ -122,8 +120,6 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
122120
}
123121
else
124122
{
125-
TryLogV3ToV4Helpers(session);
126-
127123
MemoryStream pe = new();
128124
MemoryStream pdb = new();
129125
WriterParameters writerParameters = new()
@@ -136,24 +132,7 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
136132
return new(new(pe.ToArray(), pdb.ToArray()), session.Diagnostics);
137133
}
138134
}
139-
140-
/// <summary>
141-
/// Logs warning if v3 to v4 helpers are enabled.
142-
/// </summary>
143-
private void TryLogV3ToV4Helpers(CodegenSession session)
144-
{
145-
#if !FISHNET_DISABLE_V3TOV4_HELPERS
146-
/* There is no way to check if this has run already once per codegen
147-
* so the only option is to print per session, which means
148-
* a print will occur every time an assembly compiles. This means
149-
* several prints will potentially occur per script change.
150-
*
151-
* However, these warnings typically only print when all errors are gone.
152-
* When this is true the user may go ahead and disable this warning
153-
* as instructed. */
154-
session.LogWarning(UpgradeFromV3ToV4Menu.EnabledWarning);
155-
#endif
156-
}
135+
157136

158137
/// <summary>
159138
/// Makees methods public scope which use CodegenMakePublic attribute.

Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -263,18 +263,21 @@ bool CheckCreateReconcile(MethodDefinition reconcileMd)
263263
}
264264
}
265265

266-
base.LogError($"{reconcileMd.DeclaringType.Name} implements {crName} but does not call reconcile method {reconcileMd.Name}.");
266+
base.LogError($"{reconcileMd.DeclaringType.Name} implements {crName} but does not call reconcile method {reconcileMd.Name}. If you are calling CreateReconcile from another type please make a new method to call in {reconcileMd.DeclaringType.Name}, which in return calls CreateReconcile.");
267267
//Fallthrough.
268268
return false;
269269
}
270270
}
271271

272272
bool MethodIsPrivate(MethodDefinition md)
273273
{
274-
bool isPrivate = md.Attributes.HasFlag(MethodAttributes.Private);
275-
if (!isPrivate)
276-
base.LogError($"Method {md.Name} within {typeDef.Name} is a prediction method and must be private.");
277-
return isPrivate;
274+
//Do we actually need private checks anymore?
275+
return true;
276+
277+
// bool isPrivate = md.Attributes.HasFlag(MethodAttributes.Private);
278+
// if (!isPrivate)
279+
// base.LogError($"Method {md.Name} within {typeDef.Name} is a prediction method and must be private.");
280+
// return isPrivate;
278281
}
279282

280283
bool AlreadyFound(MethodDefinition md)
@@ -382,7 +385,7 @@ internal bool Process(TypeDefinition typeDef)
382385
private bool TickFieldIsNonSerializable(TypeDefinition dataTd, bool replicate)
383386
{
384387
string methodName = (replicate) ? IReplicateData_GetTick_MethodRef.Name : IReconcileData_GetTick_MethodRef.Name;
385-
MethodDefinition getMd = dataTd.GetMethod(methodName);
388+
MethodDefinition getMd = dataTd.GetMethodDefinitionInAnyBase(base.Session, methodName);
386389

387390
//Try to find ldFld.
388391
Instruction ldFldInst = null;
@@ -398,18 +401,16 @@ private bool TickFieldIsNonSerializable(TypeDefinition dataTd, bool replicate)
398401
//If ldFld not found.
399402
if (ldFldInst == null)
400403
{
401-
base.LogError($"{dataTd.FullName} method {getMd.Name} does not return a field type for the Tick. Make a new private field of uint type and return it's value within {getMd.Name}.");
404+
base.LogError($"{dataTd.FullName} method {getMd.Name} does not return a field type for the Tick. Make a new private or protected field of uint type and return it's value within {getMd.Name}.");
402405
return false;
403406
}
404-
//Make sure the field is private.
405-
else
407+
408+
//Make sure the field is correct accessibility
409+
FieldDefinition fd = (FieldDefinition)ldFldInst.Operand;
410+
if (!fd.Attributes.HasFlag(FieldAttributes.Private) && !fd.Attributes.HasFlag(FieldAttributes.Family))
406411
{
407-
FieldDefinition fd = (FieldDefinition)ldFldInst.Operand;
408-
if (!fd.Attributes.HasFlag(FieldAttributes.Private))
409-
{
410-
base.LogError($"{dataTd.FullName} method {getMd.Name} returns a tick field but it's not marked as private. Make the field {fd.Name} private.");
411-
return false;
412-
}
412+
base.LogError($"{dataTd.FullName} method {getMd.Name} returns a tick field it does not have the correct accessibility. Make the field {fd.Name} private or protected.");
413+
return false;
413414
}
414415

415416
//All checks pass.
@@ -1014,24 +1015,23 @@ private void ServerCreateReconcile(MethodDefinition reconcileMd, CreatedPredicti
10141015
NetworkBehaviourHelper nbh = base.GetClass<NetworkBehaviourHelper>();
10151016
GenericInstanceMethod methodGim;
10161017

1017-
/* Reconcile_Client_Local. */
1018-
methodGim = nbh.Reconcile_Client_Local_MethodRef.MakeGenericMethod(new TypeReference[] { reconcileDataPd.ParameterType });
1019-
1020-
processor.Emit(OpCodes.Ldarg_0);
1021-
processor.Emit(OpCodes.Ldarg_0);
1022-
processor.Emit(OpCodes.Ldfld, predictionFields.LocalReconciles);
1023-
processor.Emit(OpCodes.Ldarg, reconcileDataPd);
1024-
processor.Emit(OpCodes.Call, methodGim);
1025-
1026-
/* Reconcile_Server. */
1027-
methodGim = nbh.Reconcile_Server_MethodRef.MakeGenericMethod(new TypeReference[] { reconcileDataPd.ParameterType });
1018+
/* Reconcile_Current. */
1019+
methodGim = nbh.Reconcile_Current_MethodRef.MakeGenericMethod(new TypeReference[] { reconcileDataPd.ParameterType });
10281020

1021+
//Hash.
10291022
processor.Emit(OpCodes.Ldarg_0);
10301023
processor.Emit(OpCodes.Ldc_I4, (int)rpcCount);
1024+
//Last reconcile data.
10311025
processor.Emit(OpCodes.Ldarg_0);
10321026
processor.Emit(OpCodes.Ldflda, predictionFields.LastReadReconcile);
1027+
//Reconciles history (local reconciles).
1028+
processor.Emit(OpCodes.Ldarg_0);
1029+
processor.Emit(OpCodes.Ldfld, predictionFields.LocalReconciles);
1030+
//Data.
10331031
processor.Emit(OpCodes.Ldarg, reconcileDataPd);
1032+
//Channel.
10341033
processor.Emit(OpCodes.Ldarg, channelPd);
1034+
10351035
processor.Emit(OpCodes.Call, methodGim);
10361036

10371037
rpcCount++;

0 commit comments

Comments
 (0)