Skip to content

Commit 7ea9f9d

Browse files
fix: Regression between comb-server and NGO network variables (#2974)
* fix: Regression between comb-server and NGO network variables * Ensure read logic is mirrored * Ensure read logic is fully mirrored * fix and update Removing the read variable type from the typed serializers. Did a little legacy code (POC DA work) clean up in the WriteNetworkVariableData and SetNetworkVariableData methods. Also added additional information in the error logging to more easily track down where any issues might be occurring. * fix length safety needed to be moved into a nested if. --------- Co-authored-by: NoelStephensUnity <[email protected]>
1 parent 5b93ce6 commit 7ea9f9d

File tree

7 files changed

+91
-97
lines changed

7 files changed

+91
-97
lines changed

com.unity.netcode.gameobjects/Runtime/Core/NetworkBehaviour.cs

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,26 +1112,38 @@ internal void MarkVariablesDirty(bool dirty)
11121112
/// </remarks>
11131113
internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClientId)
11141114
{
1115+
// Create any values that require accessing the NetworkManager locally (it is expensive to access it in NetworkBehaviour)
11151116
var networkManager = NetworkManager;
1116-
if (networkManager.DistributedAuthorityMode)
1117+
var distributedAuthority = networkManager.DistributedAuthorityMode;
1118+
var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety;
1119+
1120+
// Always write the NetworkVariable count even if zero for distributed authority (used by comb server)
1121+
if (distributedAuthority)
11171122
{
11181123
writer.WriteValueSafe((ushort)NetworkVariableFields.Count);
11191124
}
11201125

1126+
// Exit early if there are no NetworkVariables
11211127
if (NetworkVariableFields.Count == 0)
11221128
{
11231129
return;
11241130
}
11251131

1126-
// DANGO-TODO: Made some modifications here that overlap/won't play nice with EnsureNetworkVariableLenghtSafety.
1127-
// Worth either merging or more cleanly separating these codepaths.
11281132
for (int j = 0; j < NetworkVariableFields.Count; j++)
11291133
{
1130-
// Note: In distributed authority mode, all clients can read
1134+
// Client-Server: Try to write values only for clients that have read permissions.
1135+
// Distributed Authority: All clients have read permissions, always try to write the value.
11311136
if (NetworkVariableFields[j].CanClientRead(targetClientId))
11321137
{
1133-
if (networkManager.DistributedAuthorityMode || networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
1138+
// Write additional NetworkVariable information when length safety is enabled or when in distributed authority mode
1139+
if (ensureLengthSafety || distributedAuthority)
11341140
{
1141+
// Write the type being serialized for distributed authority (only for comb-server)
1142+
if (distributedAuthority)
1143+
{
1144+
writer.WriteValueSafe(NetworkVariableFields[j].Type);
1145+
}
1146+
11351147
var writePos = writer.Position;
11361148
// Note: This value can't be packed because we don't know how large it will be in advance
11371149
// we reserve space for it, then write the data, then come back and fill in the space
@@ -1143,18 +1155,19 @@ internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClie
11431155
NetworkVariableFields[j].WriteField(writer);
11441156
var size = writer.Position - startPos;
11451157
writer.Seek(writePos);
1158+
// Write the NetworkVariable value
11461159
writer.WriteValueSafe((ushort)size);
11471160
writer.Seek(startPos + size);
11481161
}
1149-
else
1162+
else // Client-Server Only: Should only ever be invoked when using a client-server NetworkTopology
11501163
{
1164+
// Write the NetworkVariable value
11511165
NetworkVariableFields[j].WriteField(writer);
11521166
}
11531167
}
1154-
else
1168+
else if (ensureLengthSafety)
11551169
{
1156-
// Only if EnsureNetworkVariableLengthSafety, otherwise just skip
1157-
if (networkManager.DistributedAuthorityMode || networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
1170+
// Client-Server Only: If the client cannot read this field, then skip it but write a 0 for this NetworkVariable's position
11581171
{
11591172
writer.WriteValueSafe((ushort)0);
11601173
}
@@ -1172,73 +1185,78 @@ internal void WriteNetworkVariableData(FastBufferWriter writer, ulong targetClie
11721185
/// </remarks>
11731186
internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId)
11741187
{
1188+
// Stack cache any values that requires accessing the NetworkManager (it is expensive to access it in NetworkBehaviour)
11751189
var networkManager = NetworkManager;
1176-
if (networkManager.DistributedAuthorityMode)
1190+
var distributedAuthority = networkManager.DistributedAuthorityMode;
1191+
var ensureLengthSafety = networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety;
1192+
1193+
// Always read the NetworkVariable count when in distributed authority (sanity check if comb-server matches what client has locally)
1194+
if (distributedAuthority)
11771195
{
11781196
reader.ReadValueSafe(out ushort variableCount);
11791197
if (variableCount != NetworkVariableFields.Count)
11801198
{
1181-
Debug.LogError("NetworkVariable count mismatch.");
1199+
Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}] NetworkVariable count mismatch! (Read: {variableCount} vs. Expected: {NetworkVariableFields.Count})");
11821200
return;
11831201
}
11841202
}
11851203

1204+
// Exit early if nothing else to read
11861205
if (NetworkVariableFields.Count == 0)
11871206
{
11881207
return;
11891208
}
11901209

1191-
// DANGO-TODO: Made some modifications here that overlap/won't play nice with EnsureNetworkVariableLenghtSafety.
1192-
// Worth either merging or more cleanly separating these codepaths.
11931210
for (int j = 0; j < NetworkVariableFields.Count; j++)
11941211
{
11951212
var varSize = (ushort)0;
11961213
var readStartPos = 0;
1197-
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
1214+
// Client-Server: Clients that only have read permissions will try to read the value
1215+
// Distributed Authority: All clients have read permissions, always try to read the value
1216+
if (NetworkVariableFields[j].CanClientRead(clientId))
11981217
{
1199-
reader.ReadValueSafe(out varSize);
1200-
if (varSize == 0)
1218+
if (ensureLengthSafety || distributedAuthority)
12011219
{
1202-
continue;
1220+
// Read the type being serialized and discard it (for now) when in a distributed authority network topology (only used by comb-server)
1221+
if (distributedAuthority)
1222+
{
1223+
reader.ReadValueSafe(out NetworkVariableType _);
1224+
}
1225+
1226+
reader.ReadValueSafe(out varSize);
1227+
if (varSize == 0)
1228+
{
1229+
Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] Expected non-zero size readable NetworkVariable! (Skipping)");
1230+
continue;
1231+
}
1232+
readStartPos = reader.Position;
12031233
}
1204-
readStartPos = reader.Position;
12051234
}
1206-
else // If the client cannot read this field, then skip it
1207-
if (!NetworkVariableFields[j].CanClientRead(clientId))
1235+
else // Client-Server Only: If the client cannot read this field, then skip it
12081236
{
1209-
if (networkManager.DistributedAuthorityMode)
1237+
// If skipping and length safety, then fill in a 0 size for this one spot
1238+
if (ensureLengthSafety)
12101239
{
12111240
reader.ReadValueSafe(out ushort size);
12121241
if (size != 0)
12131242
{
1214-
Debug.LogError("Expected zero size");
1243+
Debug.LogError($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] Expected zero size for non-readable NetworkVariable when EnsureNetworkVariableLengthSafety is enabled! (Skipping)");
12151244
}
12161245
}
12171246
continue;
12181247
}
12191248

1220-
if (networkManager.DistributedAuthorityMode)
1221-
{
1222-
reader.ReadValueSafe(out ushort size);
1223-
var start_marker = reader.Position;
1224-
NetworkVariableFields[j].ReadField(reader);
1225-
if (reader.Position - start_marker != size)
1226-
{
1227-
Debug.LogError("Mismatched network variable size");
1228-
}
1229-
}
1230-
else
1231-
{
1232-
NetworkVariableFields[j].ReadField(reader);
1233-
}
1249+
// Read the NetworkVarible value
1250+
NetworkVariableFields[j].ReadField(reader);
12341251

1235-
if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
1252+
// When EnsureNetworkVariableLengthSafety or DistributedAuthorityMode always do a bounds check
1253+
if (ensureLengthSafety || distributedAuthority)
12361254
{
12371255
if (reader.Position > (readStartPos + varSize))
12381256
{
12391257
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
12401258
{
1241-
NetworkLog.LogWarning($"Var data read too far. {reader.Position - (readStartPos + varSize)} bytes.");
1259+
NetworkLog.LogWarning($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] NetworkVariable data read too big. {reader.Position - (readStartPos + varSize)} bytes.");
12421260
}
12431261

12441262
reader.Seek(readStartPos + varSize);
@@ -1247,7 +1265,7 @@ internal void SetNetworkVariableData(FastBufferReader reader, ulong clientId)
12471265
{
12481266
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
12491267
{
1250-
NetworkLog.LogWarning($"Var data read too little. {(readStartPos + varSize) - reader.Position} bytes.");
1268+
NetworkLog.LogWarning($"[{name}][NetworkObjectId: {NetworkObjectId}][NetworkBehaviourId: {NetworkBehaviourId}][{NetworkVariableFields[j].Name}] NetworkVariable data read too small. {(readStartPos + varSize) - reader.Position} bytes.");
12511269
}
12521270

12531271
reader.Seek(readStartPos + varSize);

com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class NetworkList<T> : NetworkVariableBase where T : unmanaged, IEquatabl
2424
/// The callback to be invoked when the list gets changed
2525
/// </summary>
2626
public event OnListChangedDelegate OnListChanged;
27+
internal override NetworkVariableType Type => NetworkVariableType.NetworkList;
2728

2829
/// <summary>
2930
/// Constructor method for <see cref="NetworkList"/>
@@ -132,7 +133,6 @@ public override void WriteField(FastBufferWriter writer)
132133
{
133134
if (m_NetworkManager.DistributedAuthorityMode)
134135
{
135-
SerializationTools.WriteType(writer, NetworkVariableType.NetworkList);
136136
writer.WriteValueSafe(NetworkVariableSerialization<T>.Serializer.Type);
137137
if (NetworkVariableSerialization<T>.Serializer.Type == NetworkVariableType.Unmanaged)
138138
{
@@ -158,7 +158,6 @@ public override void ReadField(FastBufferReader reader)
158158
m_List.Clear();
159159
if (m_NetworkManager.DistributedAuthorityMode)
160160
{
161-
reader.ReadValueSafe(out NetworkVariableType _);
162161
SerializationTools.ReadType(reader, NetworkVariableSerialization<T>.Serializer);
163162
// Collection item type is used by the DA server, drop value here.
164163
if (NetworkVariableSerialization<T>.Serializer.Type == NetworkVariableType.Unmanaged)

com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public override void OnInitialize()
4545
NetworkVariableSerialization<T>.Duplicate(m_InternalValue, ref m_PreviousValue);
4646
}
4747

48+
internal override NetworkVariableType Type => NetworkVariableType.Value;
49+
4850
/// <summary>
4951
/// Constructor for <see cref="NetworkVariable{T}"/>
5052
/// </summary>

com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public abstract class NetworkVariableBase : IDisposable
3434
private protected NetworkBehaviour m_NetworkBehaviour;
3535

3636
private NetworkManager m_InternalNetworkManager;
37+
38+
internal virtual NetworkVariableType Type => NetworkVariableType.Unknown;
39+
3740
private protected NetworkManager m_NetworkManager
3841
{
3942
get
@@ -308,7 +311,6 @@ internal ulong OwnerClientId()
308311
/// </summary>
309312
/// <param name="reader">The stream to read the state from</param>
310313
public abstract void ReadField(FastBufferReader reader);
311-
312314
/// <summary>
313315
/// Reads delta from the reader and applies them to the internal value
314316
/// </summary>

com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableTypes.cs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,27 @@ namespace Unity.Netcode
1414
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1515
internal enum NetworkVariableType : byte
1616
{
17-
/// <summary>
18-
/// For any type that is not known at runtime
19-
/// </summary>
20-
Unknown = 0,
2117
/// <summary>
2218
/// Value
2319
/// Used for all of the basic NetworkVariables that contain a single value
2420
/// </summary>
25-
Value = 1,
26-
21+
Value = 0,
22+
/// <summary>
23+
/// For any type that is not known at runtime
24+
/// </summary>
25+
Unknown = 1,
2726
/// <summary>
2827
/// NetworkList
2928
/// </summary>
3029
NetworkList = 2,
3130

3231
// The following types are valid types inside of NetworkVariable collections
33-
Short = 3,
34-
UShort = 4,
35-
Int = 5,
36-
UInt = 6,
37-
Long = 7,
38-
ULong = 8,
39-
Unmanaged = 9,
32+
Short = 11,
33+
UShort = 12,
34+
Int = 13,
35+
UInt = 14,
36+
Long = 15,
37+
ULong = 16,
38+
Unmanaged = 17,
4039
}
4140
}

0 commit comments

Comments
 (0)