From cf44edc19ac1da88571d3fc7b7f3ebc7578fa69c Mon Sep 17 00:00:00 2001 From: Marek Sorokin Date: Mon, 27 Oct 2025 14:34:26 +0100 Subject: [PATCH] online fix --- Game/Scripts/Networking/NetworkIdAllocator.cs | 17 ++++++- Game/Scripts/Networking/NetworkIdentity.cs | 47 ++++++++++++++++++- .../SteamEnemySpawnerNetworkBridge.cs | 14 +++++- Game/Scripts/Runtime/Pooling/ObjectPooler.cs | 6 +++ 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/Game/Scripts/Networking/NetworkIdAllocator.cs b/Game/Scripts/Networking/NetworkIdAllocator.cs index c41aef3..53f9d72 100644 --- a/Game/Scripts/Networking/NetworkIdAllocator.cs +++ b/Game/Scripts/Networking/NetworkIdAllocator.cs @@ -9,6 +9,7 @@ namespace MegaKoop.Game.Networking private const int EnemyIdRange = 10000; private static int nextEnemyId = EnemyIdStart; + private static readonly System.Collections.Generic.HashSet ActiveEnemyIds = new(); [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void ResetOnLoad() @@ -19,6 +20,7 @@ namespace MegaKoop.Game.Networking public static void Reset() { nextEnemyId = EnemyIdStart; + ActiveEnemyIds.Clear(); } public static int AllocateEnemyId() @@ -30,7 +32,7 @@ namespace MegaKoop.Game.Networking const int maxAttempts = EnemyIdRange; int attempts = 0; - while ((NetworkIdRegistry.IsIdRegistered(nextEnemyId) || NetworkIdRegistry.IsIdReserved(nextEnemyId)) && attempts < maxAttempts) + while ((ActiveEnemyIds.Contains(nextEnemyId) || NetworkIdRegistry.IsIdRegistered(nextEnemyId) || NetworkIdRegistry.IsIdReserved(nextEnemyId)) && attempts < maxAttempts) { AdvanceEnemyCursor(); attempts++; @@ -38,6 +40,7 @@ namespace MegaKoop.Game.Networking int allocated = nextEnemyId; AdvanceEnemyCursor(); + ActiveEnemyIds.Add(allocated); return allocated; } @@ -51,6 +54,18 @@ namespace MegaKoop.Game.Networking { nextEnemyId = id + 1; } + if (id >= EnemyIdStart) + { + ActiveEnemyIds.Add(id); + } + } + + public static void ReleaseEnemyId(int id) + { + if (id >= EnemyIdStart) + { + ActiveEnemyIds.Remove(id); + } } private static void AdvanceEnemyCursor() diff --git a/Game/Scripts/Networking/NetworkIdentity.cs b/Game/Scripts/Networking/NetworkIdentity.cs index a1bfae2..9d46e44 100644 --- a/Game/Scripts/Networking/NetworkIdentity.cs +++ b/Game/Scripts/Networking/NetworkIdentity.cs @@ -22,7 +22,15 @@ namespace MegaKoop.Game.Networking private void OnDestroy() { - NetworkIdRegistry.Unregister(networkId); + if (networkId != 0) + { + if (NetworkIdAllocator.IsEnemyId(networkId)) + { + NetworkIdAllocator.ReleaseEnemyId(networkId); + } + NetworkIdRegistry.Unregister(networkId); + networkId = 0; + } } private void Register() @@ -32,6 +40,11 @@ namespace MegaKoop.Game.Networking return; } + if (NetworkIdAllocator.IsEnemyId(networkId)) + { + NetworkIdAllocator.SyncEnemyCursor(networkId); + } + if (!NetworkIdRegistry.TryRegister(this)) { Debug.LogError($"[NetworkIdentity] Failed to register {name} with ID {networkId}. " + @@ -68,11 +81,21 @@ namespace MegaKoop.Game.Networking // Unregister old ID if it was registered if (networkId != 0) { + if (NetworkIdAllocator.IsEnemyId(networkId)) + { + NetworkIdAllocator.ReleaseEnemyId(networkId); + } + NetworkIdRegistry.Unregister(networkId); } networkId = id; - + + if (NetworkIdAllocator.IsEnemyId(networkId)) + { + NetworkIdAllocator.SyncEnemyCursor(networkId); + } + // Register with new ID if (!NetworkIdRegistry.TryRegister(this)) { @@ -85,5 +108,25 @@ namespace MegaKoop.Game.Networking /// Gets the current network ID without triggering registration. /// public int GetNetworkId() => networkId; + + /// + /// Clears the current network ID and unregisters without emitting duplicate warnings. + /// + public void ClearNetworkId() + { + if (networkId == 0) + { + return; + } + + int id = networkId; + NetworkIdRegistry.Unregister(id); + if (NetworkIdAllocator.IsEnemyId(id)) + { + NetworkIdAllocator.ReleaseEnemyId(id); + } + + networkId = 0; + } } } diff --git a/Game/Scripts/Networking/SteamEnemySpawnerNetworkBridge.cs b/Game/Scripts/Networking/SteamEnemySpawnerNetworkBridge.cs index 2bc33f2..e88e283 100644 --- a/Game/Scripts/Networking/SteamEnemySpawnerNetworkBridge.cs +++ b/Game/Scripts/Networking/SteamEnemySpawnerNetworkBridge.cs @@ -279,6 +279,19 @@ namespace MegaKoop.Game.Networking hasPendingRemoteSpawn = false; return; } + EnemyDefinitionRegistry.Register(definition); + + if (pendingRemoteSpawn.NetworkId != 0 && NetworkIdentity.TryGet(pendingRemoteSpawn.NetworkId, out var existingIdentity) && existingIdentity != null) + { + var existingInstance = existingIdentity.gameObject; + if (existingInstance != null) + { + existingInstance.SetActive(true); + existingInstance.transform.SetPositionAndRotation(pendingRemoteSpawn.Position + definition.PrefabPivotOffset, pendingRemoteSpawn.Rotation); + hasPendingRemoteSpawn = false; + } + return; + } bool success = spawner != null && spawner.TrySpawn(definition, pendingRemoteSpawn.Position); if (success) @@ -348,7 +361,6 @@ namespace MegaKoop.Game.Networking var identity = instance.GetComponent(); if (identity != null && pendingRemoteSpawn.NetworkId != 0 && identity.NetworkId != pendingRemoteSpawn.NetworkId) { - NetworkIdAllocator.SyncEnemyCursor(pendingRemoteSpawn.NetworkId); identity.SetNetworkId(pendingRemoteSpawn.NetworkId); } } diff --git a/Game/Scripts/Runtime/Pooling/ObjectPooler.cs b/Game/Scripts/Runtime/Pooling/ObjectPooler.cs index 2707327..8c854b8 100644 --- a/Game/Scripts/Runtime/Pooling/ObjectPooler.cs +++ b/Game/Scripts/Runtime/Pooling/ObjectPooler.cs @@ -4,6 +4,7 @@ using Game.Scripts.Runtime.Abstractions; using Game.Scripts.Runtime.Data; using UnityEngine; using Unity.Netcode; +using MegaKoop.Game.Networking; namespace Game.Scripts.Runtime.Pooling { @@ -144,6 +145,8 @@ namespace Game.Scripts.Runtime.Pooling { Destroy(netObj); } + var identity = instance.GetComponent(); + identity?.ClearNetworkId(); bucket.Available.Enqueue(instance); item.Handle?.NotifyDespawned(); InstanceDespawned?.Invoke(instance, item.Definition); @@ -183,6 +186,9 @@ namespace Game.Scripts.Runtime.Pooling go.name = $"{definition.Prefab.name}_Pooled"; go.SetActive(false); + var identity = go.GetComponent(); + identity?.ClearNetworkId(); + var handle = go.GetComponent(); if (handle == null) {