Join and leave improvements
This commit is contained in:
@@ -18,15 +18,18 @@ namespace MegaKoop.Game.Networking
|
||||
public class LobbyGameSceneCoordinator : MonoBehaviour
|
||||
{
|
||||
private static LobbyGameSceneCoordinator Instance;
|
||||
public static LobbyGameSceneCoordinator Current => Instance;
|
||||
|
||||
[SerializeField] private string characterSceneName = "CharacterScene";
|
||||
[SerializeField] private float spawnRadius = 3f;
|
||||
[SerializeField] private float minimumSpawnSpacing = 2.5f;
|
||||
|
||||
private readonly List<LobbyPlayerInfo> pendingPlayers = new();
|
||||
private readonly Dictionary<ulong, GameObject> spawnedPlayerObjects = new();
|
||||
private string localSteamId = string.Empty;
|
||||
private bool loadPending;
|
||||
private bool hasSpawned;
|
||||
private SteamCoopNetworkManager coopNetworkManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -40,11 +43,13 @@ namespace MegaKoop.Game.Networking
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
SceneManager.sceneLoaded += HandleSceneLoaded;
|
||||
EnsureNetworkSubscription();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
SceneManager.sceneLoaded -= HandleSceneLoaded;
|
||||
UnsubscribeFromNetwork();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -113,6 +118,14 @@ namespace MegaKoop.Game.Networking
|
||||
pendingPlayers.Sort((a, b) => string.CompareOrdinal(a.SteamId ?? string.Empty, b.SteamId ?? string.Empty));
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (coopNetworkManager == null)
|
||||
{
|
||||
EnsureNetworkSubscription();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
if (!string.Equals(scene.name, characterSceneName, StringComparison.OrdinalIgnoreCase))
|
||||
@@ -125,6 +138,7 @@ namespace MegaKoop.Game.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureNetworkSubscription();
|
||||
loadPending = false;
|
||||
hasSpawned = false;
|
||||
SpawnPlayersInScene(scene);
|
||||
@@ -137,6 +151,7 @@ namespace MegaKoop.Game.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureNetworkSubscription();
|
||||
var template = FindWizardTemplate(scene);
|
||||
if (template == null)
|
||||
{
|
||||
@@ -148,6 +163,7 @@ namespace MegaKoop.Game.Networking
|
||||
|
||||
// Proactively remove any previously spawned character clones (e.g., from a duplicate coordinator)
|
||||
DespawnExistingClones(scene, template);
|
||||
spawnedPlayerObjects.Clear();
|
||||
|
||||
Vector3 basePosition = template.transform.position;
|
||||
Quaternion baseRotation = template.transform.rotation;
|
||||
@@ -168,6 +184,17 @@ namespace MegaKoop.Game.Networking
|
||||
|
||||
ConfigureCloneForPlayer(clone, info, i);
|
||||
|
||||
ulong ownerSteamId = ParseSteamId(info.SteamId);
|
||||
if (ownerSteamId == 0UL && info.IsLocal)
|
||||
{
|
||||
ownerSteamId = ParseSteamId(localSteamId);
|
||||
}
|
||||
|
||||
if (ownerSteamId != 0UL)
|
||||
{
|
||||
spawnedPlayerObjects[ownerSteamId] = clone;
|
||||
}
|
||||
|
||||
clone.SetActive(true);
|
||||
}
|
||||
}
|
||||
@@ -359,5 +386,106 @@ namespace MegaKoop.Game.Networking
|
||||
public string DisplayName;
|
||||
public bool IsLocal;
|
||||
}
|
||||
|
||||
private void EnsureNetworkSubscription()
|
||||
{
|
||||
var manager = SteamCoopNetworkManager.Instance;
|
||||
if (manager == null || manager == coopNetworkManager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnsubscribeFromNetwork();
|
||||
|
||||
coopNetworkManager = manager;
|
||||
coopNetworkManager.HostClosed += HandleHostClosed;
|
||||
coopNetworkManager.PlayerDisconnected += HandlePlayerDisconnected;
|
||||
}
|
||||
|
||||
private void UnsubscribeFromNetwork()
|
||||
{
|
||||
if (coopNetworkManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
coopNetworkManager.HostClosed -= HandleHostClosed;
|
||||
coopNetworkManager.PlayerDisconnected -= HandlePlayerDisconnected;
|
||||
coopNetworkManager = null;
|
||||
}
|
||||
|
||||
private void HandleHostClosed()
|
||||
{
|
||||
Debug.Log("[LobbyGameSceneCoordinator] Host closed session; despawning all players.");
|
||||
RemoveAllSpawnedPlayers();
|
||||
}
|
||||
|
||||
private void HandlePlayerDisconnected(ulong steamId)
|
||||
{
|
||||
RemoveSpawnedPlayer(steamId);
|
||||
}
|
||||
|
||||
private void RemoveAllSpawnedPlayers()
|
||||
{
|
||||
if (spawnedPlayerObjects.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var avatar in spawnedPlayerObjects.Values)
|
||||
{
|
||||
if (avatar != null)
|
||||
{
|
||||
Destroy(avatar);
|
||||
}
|
||||
}
|
||||
|
||||
spawnedPlayerObjects.Clear();
|
||||
hasSpawned = false;
|
||||
}
|
||||
|
||||
private void RemoveSpawnedPlayer(ulong steamId)
|
||||
{
|
||||
if (steamId == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawnedPlayerObjects.TryGetValue(steamId, out GameObject avatar))
|
||||
{
|
||||
if (avatar != null)
|
||||
{
|
||||
Destroy(avatar);
|
||||
}
|
||||
spawnedPlayerObjects.Remove(steamId);
|
||||
Debug.Log($"[LobbyGameSceneCoordinator] Removed avatar for {steamId}.");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong? keyToRemove = null;
|
||||
foreach (var kvp in spawnedPlayerObjects)
|
||||
{
|
||||
var target = kvp.Value;
|
||||
if (target == null)
|
||||
{
|
||||
keyToRemove = kvp.Key;
|
||||
continue;
|
||||
}
|
||||
|
||||
var bridge = target.GetComponent<SteamCharacterNetworkBridge>();
|
||||
if (bridge != null && bridge.OwnerSteamId == steamId)
|
||||
{
|
||||
Destroy(target);
|
||||
keyToRemove = kvp.Key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyToRemove.HasValue)
|
||||
{
|
||||
spawnedPlayerObjects.Remove(keyToRemove.Value);
|
||||
Debug.Log($"[LobbyGameSceneCoordinator] Removed avatar for {steamId} (fallback search).");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user