Skip to content

Commit 6b3c905

Browse files
committed
Added support for dynamically added NetworkPrefabs
1 parent 658f496 commit 6b3c905

11 files changed

Lines changed: 117 additions & 54 deletions

File tree

MLAPI-Editor/NetworkingManagerEditor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private void OnEnable()
6666
};
6767

6868
networkPrefabsList.drawHeaderCallback = (Rect rect) => {
69-
EditorGUI.LabelField(rect, "NetworkedPrefabs (Auto Sorted)");
69+
EditorGUI.LabelField(rect, "NetworkedPrefabs");
7070
};
7171

7272
channelsList = new ReorderableList(serializedObject, serializedObject.FindProperty("NetworkConfig").FindPropertyRelative("Channels"), true, true, true, true);

MLAPI/Data/AttributeMessageMode.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
namespace MLAPI.Configuration
77
{
88
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
9-
public enum AttributeMessageMode
9+
public enum HashSize
1010
{
11-
WovenTwoByte,
12-
WovenFourByte,
13-
WovenEightByte
11+
VarIntTwoBytes,
12+
VarIntFourBytes,
13+
VarIntEightBytes
1414
}
1515
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
1616
}

MLAPI/Data/NetworkConfig.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ public class NetworkConfig
5555
/// </summary>
5656
[HideInInspector]
5757
public List<NetworkedPrefab> NetworkedPrefabs = new List<NetworkedPrefab>();
58-
internal Dictionary<string, int> NetworkPrefabIds;
59-
internal Dictionary<int, string> NetworkPrefabNames;
6058
/// <summary>
6159
/// The default player prefab
6260
/// </summary>
@@ -125,9 +123,18 @@ public class NetworkConfig
125123
/// </summary>
126124
public bool EnableTimeResync = false;
127125
/// <summary>
128-
/// Decides how many bytes to use for Attribute messaging. Leave this to 2 bytes unless you are facing hash collisions
126+
/// Wheter or not the MLAPI should check for differences in the prefabs at connection.
127+
/// If you dynamically add prefabs at runtime, turn this OFF
129128
/// </summary>
130-
public AttributeMessageMode AttributeMessageMode = AttributeMessageMode.WovenTwoByte;
129+
public bool ForceSamePrefabs = true;
130+
/// <summary>
131+
/// Decides how many bytes to use for Rpc messaging. Leave this to 2 bytes unless you are facing hash collisions
132+
/// </summary>
133+
public HashSize RpcHashSize = HashSize.VarIntTwoBytes;
134+
/// <summary>
135+
/// Decides how many bytes to use for Prefab names. Leave this to 2 bytes unless you are facing hash collisions
136+
/// </summary>
137+
public HashSize PrefabHashSize = HashSize.VarIntTwoBytes;
131138
/// <summary>
132139
/// Wheter or not to enable encryption
133140
/// </summary>
@@ -166,7 +173,6 @@ public byte[] ServerX509CertificateBytes
166173
private void Sort()
167174
{
168175
Channels = Channels.OrderBy(x => x.Name).ToList();
169-
NetworkedPrefabs = NetworkedPrefabs.OrderBy(x => x.name).ToList();
170176
RegisteredScenes.Sort();
171177
}
172178

@@ -220,8 +226,8 @@ public string ToBase64()
220226
writer.WriteBool(config.SignKeyExchange);
221227
writer.WriteBool(config.EnableSceneSwitching);
222228
writer.WriteBool(config.EnableTimeResync);
223-
writer.WriteBits((byte)config.AttributeMessageMode, 3);
224-
stream.ZeroLastByteGarbageBits();
229+
writer.WriteBits((byte)config.RpcHashSize, 3);
230+
stream.PadStream();
225231

226232
return Convert.ToBase64String(stream.ToArray());
227233
}
@@ -301,7 +307,7 @@ public void FromBase64(string base64, bool createDummyObject = false)
301307
config.SignKeyExchange = reader.ReadBool();
302308
config.EnableSceneSwitching = reader.ReadBool();
303309
config.EnableTimeResync = reader.ReadBool();
304-
config.AttributeMessageMode = (AttributeMessageMode)reader.ReadBits(3);
310+
config.RpcHashSize = (HashSize)reader.ReadBits(3);
305311
}
306312
}
307313
}
@@ -341,20 +347,23 @@ public ulong GetConfig(bool cache = true)
341347
}
342348
}
343349

344-
if (HandleObjectSpawning)
350+
if (HandleObjectSpawning && ForceSamePrefabs)
345351
{
346-
for (int i = 0; i < NetworkedPrefabs.Count; i++)
352+
List<NetworkedPrefab> sortedPrefabList = NetworkedPrefabs.OrderBy(x => x.hash).ToList();
353+
for (int i = 0; i < sortedPrefabList.Count; i++)
347354
{
348-
writer.WriteString(NetworkedPrefabs[i].name);
355+
writer.WriteUInt64Packed(sortedPrefabList[i].hash);
349356
}
350357
}
351358

359+
writer.WriteBool(ForceSamePrefabs);
352360
writer.WriteBool(HandleObjectSpawning);
353361
writer.WriteBool(EnableEncryption);
354362
writer.WriteBool(EnableSceneSwitching);
355363
writer.WriteBool(SignKeyExchange);
356-
writer.WriteBits((byte)AttributeMessageMode, 3);
357-
stream.ZeroLastByteGarbageBits();
364+
writer.WriteBits((byte)RpcHashSize, 3);
365+
writer.WriteBits((byte)PrefabHashSize, 3);
366+
stream.PadStream();
358367

359368
if (cache)
360369
{

MLAPI/Data/NetworkedPrefab.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,24 @@ internal string name
2727
else return prefab.GetComponent<NetworkedObject>().NetworkedPrefabName;
2828
}
2929
}
30+
31+
internal ulong hash
32+
{
33+
get
34+
{
35+
if (prefab == null)
36+
{
37+
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("NetworkedPrefab is not assigned");
38+
return 0;
39+
}
40+
else if (prefab.GetComponent<NetworkedObject>() == null)
41+
{
42+
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("The NetworkedPrefab " + prefab.name + " does not have a NetworkedObject");
43+
return 0;
44+
}
45+
else return prefab.GetComponent<NetworkedObject>().NetworkedPrefabHash;
46+
}
47+
}
3048
/// <summary>
3149
/// The gameobject of the prefab
3250
/// </summary>

MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,13 +401,13 @@ internal void HandleNetworkedVarUpdate(Stream stream, uint clientId)
401401

402402
private ulong HashMethodName(string name)
403403
{
404-
AttributeMessageMode mode = NetworkingManager.singleton.NetworkConfig.AttributeMessageMode;
404+
HashSize mode = NetworkingManager.singleton.NetworkConfig.RpcHashSize;
405405

406-
if (mode == AttributeMessageMode.WovenTwoByte)
406+
if (mode == HashSize.VarIntTwoBytes)
407407
return name.GetStableHash16();
408-
if (mode == AttributeMessageMode.WovenFourByte)
408+
if (mode == HashSize.VarIntFourBytes)
409409
return name.GetStableHash32();
410-
if (mode == AttributeMessageMode.WovenEightByte)
410+
if (mode == HashSize.VarIntEightBytes)
411411
return name.GetStableHash64();
412412

413413
return 0;

MLAPI/MonoBehaviours/Core/NetworkedObject.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ internal set
5555
/// </summary>
5656
public string NetworkedPrefabName = string.Empty;
5757
/// <summary>
58+
/// The hash used to identify the NetworkedPrefab, a hash of the NetworkedPrefabName
59+
/// </summary>
60+
public ulong NetworkedPrefabHash => SpawnManager.GetPrefabHash(NetworkedPrefabName);
61+
/// <summary>
5862
/// Gets if this object is a player object
5963
/// </summary>
6064
public bool isPlayerObject { get; internal set; }

MLAPI/MonoBehaviours/Core/NetworkingManager.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ private void OnValidate()
199199
//Sort lists
200200
if (NetworkConfig.Channels != null)
201201
NetworkConfig.Channels = NetworkConfig.Channels.OrderBy(x => x.Name).ToList();
202-
if (NetworkConfig.NetworkedPrefabs != null)
203-
NetworkConfig.NetworkedPrefabs = NetworkConfig.NetworkedPrefabs.OrderBy(x => x.name).ToList();
204202
if (NetworkConfig.RegisteredScenes != null)
205203
NetworkConfig.RegisteredScenes.Sort();
206204

@@ -289,9 +287,6 @@ private object Init(bool server)
289287

290288
if (NetworkConfig.HandleObjectSpawning)
291289
{
292-
NetworkConfig.NetworkPrefabIds = new Dictionary<string, int>();
293-
NetworkConfig.NetworkPrefabNames = new Dictionary<int, string>();
294-
NetworkConfig.NetworkedPrefabs = NetworkConfig.NetworkedPrefabs.OrderBy(x => x.name).ToList();
295290
HashSet<string> networkedPrefabName = new HashSet<string>();
296291
for (int i = 0; i < NetworkConfig.NetworkedPrefabs.Count; i++)
297292
{
@@ -300,8 +295,6 @@ private object Init(bool server)
300295
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("Duplicate NetworkedPrefabName " + NetworkConfig.NetworkedPrefabs[i].name);
301296
continue;
302297
}
303-
NetworkConfig.NetworkPrefabIds.Add(NetworkConfig.NetworkedPrefabs[i].name, i);
304-
NetworkConfig.NetworkPrefabNames.Add(i, NetworkConfig.NetworkedPrefabs[i].name);
305298
networkedPrefabName.Add(NetworkConfig.NetworkedPrefabs[i].name);
306299
}
307300
}
@@ -558,7 +551,7 @@ public void StartHost(Vector3? pos = null, Quaternion? rot = null, int prefabId
558551

559552
if (NetworkConfig.HandleObjectSpawning)
560553
{
561-
prefabId = prefabId == -1 ? NetworkConfig.NetworkPrefabIds[NetworkConfig.PlayerPrefabName] : prefabId;
554+
prefabId = prefabId == -1 ? SpawnManager.GetNetworkedPrefabIndexOfName(NetworkConfig.PlayerPrefabName) : prefabId;
562555
SpawnManager.CreateSpawnedObject(prefabId, 0, hostClientId, true, pos.GetValueOrDefault(), rot.GetValueOrDefault(), null, false, false);
563556
}
564557

@@ -1016,7 +1009,7 @@ internal void HandleApproval(uint clientId, int prefabId, bool approved, Vector3
10161009
NetworkedObject netObject = null;
10171010
if(NetworkConfig.HandleObjectSpawning)
10181011
{
1019-
prefabId = prefabId == -1 ? NetworkConfig.NetworkPrefabIds[NetworkConfig.PlayerPrefabName] : prefabId;
1012+
prefabId = prefabId == -1 ? SpawnManager.GetNetworkedPrefabIndexOfName(NetworkConfig.PlayerPrefabName) : prefabId;
10201013
netObject = SpawnManager.CreateSpawnedObject(prefabId, 0, clientId, true, position, rotation, null, false, false);
10211014
ConnectedClients[clientId].PlayerObject = netObject;
10221015
}
@@ -1052,7 +1045,7 @@ internal void HandleApproval(uint clientId, int prefabId, bool approved, Vector3
10521045
writer.WriteBool(pair.Value.isPlayerObject);
10531046
writer.WriteUInt32Packed(pair.Value.NetworkId);
10541047
writer.WriteUInt32Packed(pair.Value.OwnerClientId);
1055-
writer.WriteInt32Packed(NetworkConfig.NetworkPrefabIds[pair.Value.NetworkedPrefabName]);
1048+
writer.WriteUInt64Packed(pair.Value.NetworkedPrefabHash);
10561049
writer.WriteBool(pair.Value.gameObject.activeInHierarchy);
10571050
writer.WriteBool(pair.Value.sceneObject == null ? true : pair.Value.sceneObject.Value);
10581051

@@ -1091,7 +1084,7 @@ internal void HandleApproval(uint clientId, int prefabId, bool approved, Vector3
10911084
writer.WriteBool(true);
10921085
writer.WriteUInt32Packed(ConnectedClients[clientId].PlayerObject.GetComponent<NetworkedObject>().NetworkId);
10931086
writer.WriteUInt32Packed(clientId);
1094-
writer.WriteInt32Packed(prefabId);
1087+
writer.WriteUInt64Packed(NetworkingManager.singleton.NetworkConfig.NetworkedPrefabs[prefabId].hash);
10951088
writer.WriteBool(false);
10961089

10971090
writer.WriteSinglePacked(ConnectedClients[clientId].PlayerObject.transform.position.x);

MLAPI/NetworkingManagerComponents/Binary/BitStream.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -440,13 +440,14 @@ public byte[] ToArray()
440440
}
441441

442442
/// <summary>
443-
/// Sets the unused bits of the last byte to 0s
443+
/// Writes zeros to fill the last byte
444444
/// </summary>
445-
public void ZeroLastByteGarbageBits()
445+
public void PadStream()
446446
{
447-
if (BitAligned) return;
448-
449-
target[Length] &= (byte)~(0xFF << (int)(BitLength % 8));
447+
while (!BitAligned)
448+
{
449+
WriteBit(false);
450+
}
450451
}
451452

452453
/// <summary>

MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ internal static void HandleConnectionApproved(uint clientId, Stream stream, int
228228
bool isPlayerObject = reader.ReadBool();
229229
uint networkId = reader.ReadUInt32Packed();
230230
uint ownerId = reader.ReadUInt32Packed();
231-
int prefabId = reader.ReadInt32Packed();
231+
ulong prefabHash = reader.ReadUInt64Packed();
232232
bool isActive = reader.ReadBool();
233233
bool sceneObject = reader.ReadBool();
234234

@@ -240,7 +240,7 @@ internal static void HandleConnectionApproved(uint clientId, Stream stream, int
240240
float yRot = reader.ReadSinglePacked();
241241
float zRot = reader.ReadSinglePacked();
242242

243-
NetworkedObject netObject = SpawnManager.CreateSpawnedObject(prefabId, networkId, ownerId, isPlayerObject,
243+
NetworkedObject netObject = SpawnManager.CreateSpawnedObject(SpawnManager.GetNetworkedPrefabIndexOfHash(prefabHash), networkId, ownerId, isPlayerObject,
244244
new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot), stream, false, true);
245245
netObject.sceneObject = sceneObject;
246246
netObject.gameObject.SetActive(isActive);
@@ -267,7 +267,7 @@ internal static void HandleAddObject(uint clientId, Stream stream, int channelId
267267
bool isPlayerObject = reader.ReadBool();
268268
uint networkId = reader.ReadUInt32Packed();
269269
uint ownerId = reader.ReadUInt32Packed();
270-
int prefabId = reader.ReadInt32Packed();
270+
ulong prefabHash = reader.ReadUInt64Packed();
271271
bool sceneObject = reader.ReadBool();
272272

273273
float xPos = reader.ReadSinglePacked();
@@ -285,7 +285,8 @@ internal static void HandleAddObject(uint clientId, Stream stream, int channelId
285285
netManager.ConnectedClients.Add(ownerId, new NetworkedClient() { ClientId = ownerId });
286286
netManager.ConnectedClientsList.Add(netManager.ConnectedClients[ownerId]);
287287
}
288-
NetworkedObject netObject = SpawnManager.CreateSpawnedObject(prefabId, networkId, ownerId, isPlayerObject,
288+
289+
NetworkedObject netObject = SpawnManager.CreateSpawnedObject(SpawnManager.GetNetworkedPrefabIndexOfHash(prefabHash), networkId, ownerId, isPlayerObject,
289290
new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot), stream, hasPayload, true);
290291

291292
netObject.sceneObject = sceneObject;
@@ -386,7 +387,7 @@ internal static void HandleAddObjects(uint clientId, Stream stream, int channelI
386387
bool isPlayerObject = reader.ReadBool();
387388
uint networkId = reader.ReadUInt32Packed();
388389
uint ownerId = reader.ReadUInt32Packed();
389-
int prefabId = reader.ReadInt32Packed();
390+
ulong prefabHash = reader.ReadUInt64Packed();
390391
bool sceneObject = reader.ReadBool();
391392

392393
float xPos = reader.ReadSinglePacked();
@@ -402,7 +403,7 @@ internal static void HandleAddObjects(uint clientId, Stream stream, int channelI
402403
netManager.ConnectedClients.Add(ownerId, new NetworkedClient() { ClientId = ownerId });
403404
netManager.ConnectedClientsList.Add(netManager.ConnectedClients[ownerId]);
404405
}
405-
NetworkedObject netObject = SpawnManager.CreateSpawnedObject(prefabId, networkId, ownerId, isPlayerObject,
406+
NetworkedObject netObject = SpawnManager.CreateSpawnedObject(SpawnManager.GetNetworkedPrefabIndexOfHash(prefabHash), networkId, ownerId, isPlayerObject,
406407
new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot), stream, false, true);
407408
netObject.sceneObject = sceneObject;
408409
}

MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Send.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal static partial class InternalMessageHandler
88
{
99
internal static void Send(uint clientId, byte messageType, string channelName, BitStream messageStream, SecuritySendFlags flags, bool skipQueue = false)
1010
{
11-
messageStream.ZeroLastByteGarbageBits();
11+
messageStream.PadStream();
1212

1313
if (NetworkingManager.singleton.isServer && clientId == NetworkingManager.singleton.ServerClientId) return;
1414

@@ -38,7 +38,7 @@ internal static void Send(byte messageType, string channelName, BitStream messag
3838
}
3939
else
4040
{
41-
messageStream.ZeroLastByteGarbageBits();
41+
messageStream.PadStream();
4242

4343
using (BitStream stream = MessageManager.WrapMessage(messageType, 0, messageStream, flags))
4444
{
@@ -71,7 +71,7 @@ internal static void Send(byte messageType, string channelName, uint clientIdToI
7171
}
7272
else
7373
{
74-
messageStream.ZeroLastByteGarbageBits();
74+
messageStream.PadStream();
7575

7676
using (BitStream stream = MessageManager.WrapMessage(messageType, 0, messageStream, flags))
7777
{

0 commit comments

Comments
 (0)