diff --git a/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs index 96853e876..b4a39696f 100644 --- a/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Factory/Foundation/FoundationBuildUpdateProcessor.cs @@ -15,8 +15,6 @@ class FoundationBuildUpdateProcessor : PacketProcessor HOST -> CLIENT CODE - PlanetData planet = GameMain.galaxy.PlanetById(packet.PlanetId); PlanetFactory factory = IsHost ? GameMain.data.GetOrCreateFactory(planet) : planet?.factory; if (factory != null) @@ -57,6 +55,11 @@ public override void ProcessPacket(FoundationBuildUpdatePacket packet, NebulaCon } } } + + if (IsHost) + { + Multiplayer.Session.Network.SendPacketToStar(packet, planet.star.id); + } } } } diff --git a/NebulaNetwork/PlayerManager.cs b/NebulaNetwork/PlayerManager.cs index fd7dc23b8..f19431910 100644 --- a/NebulaNetwork/PlayerManager.cs +++ b/NebulaNetwork/PlayerManager.cs @@ -15,7 +15,7 @@ namespace NebulaNetwork { public class PlayerManager : IPlayerManager { - sealed class ThreadSafe + private sealed class ThreadSafe { internal readonly Dictionary pendingPlayers = new Dictionary(); internal readonly Dictionary syncingPlayers = new Dictionary(); @@ -27,26 +27,34 @@ sealed class ThreadSafe private readonly ThreadSafe threadSafe = new ThreadSafe(); private int highestPlayerID = 0; - public Locker GetPendingPlayers(out Dictionary pendingPlayers) => - threadSafe.pendingPlayers.GetLocked(out pendingPlayers); + public Locker GetPendingPlayers(out Dictionary pendingPlayers) + { + return threadSafe.pendingPlayers.GetLocked(out pendingPlayers); + } - public Locker GetSyncingPlayers(out Dictionary syncingPlayers) => - threadSafe.syncingPlayers.GetLocked(out syncingPlayers); + public Locker GetSyncingPlayers(out Dictionary syncingPlayers) + { + return threadSafe.syncingPlayers.GetLocked(out syncingPlayers); + } - public Locker GetConnectedPlayers(out Dictionary connectedPlayers) => - threadSafe.connectedPlayers.GetLocked(out connectedPlayers); + public Locker GetConnectedPlayers(out Dictionary connectedPlayers) + { + return threadSafe.connectedPlayers.GetLocked(out connectedPlayers); + } - public Locker GetSavedPlayerData(out Dictionary savedPlayerData) => - threadSafe.savedPlayerData.GetLocked(out savedPlayerData); + public Locker GetSavedPlayerData(out Dictionary savedPlayerData) + { + return threadSafe.savedPlayerData.GetLocked(out savedPlayerData); + } public IPlayerData[] GetAllPlayerDataIncludingHost() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { int i = 0; - var result = new IPlayerData[1 + connectedPlayers.Count]; + IPlayerData[] result = new IPlayerData[1 + connectedPlayers.Count]; result[i++] = Multiplayer.Session.LocalPlayer.Data; - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { result[i++] = kvp.Value.Data; } @@ -57,7 +65,7 @@ public IPlayerData[] GetAllPlayerDataIncludingHost() public INebulaPlayer GetPlayer(INebulaConnection conn) { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { if (connectedPlayers.TryGetValue(conn, out INebulaPlayer player)) { @@ -70,7 +78,7 @@ public INebulaPlayer GetPlayer(INebulaConnection conn) public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) { - using (GetSyncingPlayers(out var syncingPlayers)) + using (GetSyncingPlayers(out Dictionary syncingPlayers)) { if (syncingPlayers.TryGetValue(conn, out INebulaPlayer player)) { @@ -83,9 +91,9 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendPacketToAllPlayers(T packet) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { INebulaPlayer player = kvp.Value; player.SendPacket(packet); @@ -96,11 +104,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendPacketToLocalStar(T packet) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalStarId == GameMain.data.localStar?.id) { player.SendPacket(packet); @@ -111,11 +119,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendPacketToLocalPlanet(T packet) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalPlanetId == GameMain.data.mainPlayer.planetId) { player.SendPacket(packet); @@ -126,11 +134,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendPacketToPlanet(T packet, int planetId) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalPlanetId == planetId) { player.SendPacket(packet); @@ -141,11 +149,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendPacketToStar(T packet, int starId) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalStarId == starId) { player.SendPacket(packet); @@ -156,11 +164,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendPacketToStarExcept(T packet, int starId, INebulaConnection exclude) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalStarId == starId && player != GetPlayer(exclude)) { player.SendPacket(packet); @@ -171,11 +179,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn) public void SendRawPacketToStar(byte[] rawPacket, int starId, INebulaConnection sender) { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalStarId == starId && player.Connection != sender) { ((NebulaPlayer)player).SendRawPacket(rawPacket); @@ -186,11 +194,11 @@ public void SendRawPacketToStar(byte[] rawPacket, int starId, INebulaConnection public void SendRawPacketToPlanet(byte[] rawPacket, int planetId, INebulaConnection sender) { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player.Data.LocalPlanetId == planetId && player.Connection != sender) { ((NebulaPlayer)player).SendRawPacket(rawPacket); @@ -201,11 +209,11 @@ public void SendRawPacketToPlanet(byte[] rawPacket, int planetId, INebulaConnect public void SendPacketToOtherPlayers(T packet, INebulaPlayer sender) where T : class, new() { - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { - var player = kvp.Value; + INebulaPlayer player = kvp.Value; if (player != sender) { player.SendPacket(packet); @@ -224,7 +232,7 @@ public INebulaPlayer PlayerConnected(INebulaConnection conn) PlayerData playerData = new PlayerData(playerId, -1, playerColor, position: new Double3(birthPlanet.uPosition.x, birthPlanet.uPosition.y, birthPlanet.uPosition.z)); INebulaPlayer newPlayer = new NebulaPlayer((NebulaConnection)conn, playerData); - using (GetPendingPlayers(out var pendingPlayers)) + using (GetPendingPlayers(out Dictionary pendingPlayers)) { pendingPlayers.Add(conn, newPlayer); } @@ -234,49 +242,87 @@ public INebulaPlayer PlayerConnected(INebulaConnection conn) public void PlayerDisconnected(INebulaConnection conn) { - using (GetConnectedPlayers(out var connectedPlayers)) + INebulaPlayer player; + bool playerWasSyncing = false; + int syncCount = -1; + + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - if (connectedPlayers.TryGetValue(conn, out INebulaPlayer player)) + if (connectedPlayers.TryGetValue(conn, out player)) { - SendPacketToOtherPlayers(new PlayerDisconnected(player.Id), player); - Multiplayer.Session.World.DestroyRemotePlayerModel(player.Id); connectedPlayers.Remove(conn); - using (threadSafe.availablePlayerIds.GetLocked(out var availablePlayerIds)) + } + } + + using (GetPendingPlayers(out Dictionary pendingPlayers)) + { + if (player == null) + { + if (pendingPlayers.TryGetValue(conn, out player)) { - availablePlayerIds.Enqueue(player.Id); + pendingPlayers.Remove(conn); } - Multiplayer.Session.Statistics.UnRegisterPlayer(player.Id); + } + } - //Notify players about queued building plans for drones - int[] DronePlans = Multiplayer.Session.Drones.GetPlayerDronePlans(player.Id); - if (DronePlans != null && DronePlans.Length > 0 && player.Data.LocalPlanetId > 0) + using (GetSyncingPlayers(out Dictionary syncingPlayers)) + { + if (player == null) + { + if (syncingPlayers.TryGetValue(conn, out player)) { - Multiplayer.Session.Network.SendPacketToPlanet(new RemoveDroneOrdersPacket(DronePlans), player.Data.LocalPlanetId); - //Remove it also from host queue, if host is on the same planet - if (GameMain.mainPlayer.planetId == player.Data.LocalPlanetId) + syncingPlayers.Remove(conn); + playerWasSyncing = true; + syncCount = syncingPlayers.Count; + } + } + } + + if (player != null) + { + SendPacketToOtherPlayers(new PlayerDisconnected(player.Id), player); + Multiplayer.Session.World.DestroyRemotePlayerModel(player.Id); + using (threadSafe.availablePlayerIds.GetLocked(out Queue availablePlayerIds)) + { + availablePlayerIds.Enqueue(player.Id); + } + Multiplayer.Session.Statistics.UnRegisterPlayer(player.Id); + + //Notify players about queued building plans for drones + int[] DronePlans = Multiplayer.Session.Drones.GetPlayerDronePlans(player.Id); + if (DronePlans != null && DronePlans.Length > 0 && player.Data.LocalPlanetId > 0) + { + Multiplayer.Session.Network.SendPacketToPlanet(new RemoveDroneOrdersPacket(DronePlans), player.Data.LocalPlanetId); + //Remove it also from host queue, if host is on the same planet + if (GameMain.mainPlayer.planetId == player.Data.LocalPlanetId) + { + for (int i = 0; i < DronePlans.Length; i++) { - for (int i = 0; i < DronePlans.Length; i++) - { - GameMain.mainPlayer.mecha.droneLogic.serving.Remove(DronePlans[i]); - } + GameMain.mainPlayer.mecha.droneLogic.serving.Remove(DronePlans[i]); } } } - else + + if (playerWasSyncing && syncCount == 0) { - Log.Warn($"PlayerDisconnected NOT CALLED!"); + Multiplayer.Session.Network.SendPacket(new SyncComplete()); + Multiplayer.Session.World.OnAllPlayersSyncCompleted(); } - - // TODO: Should probably also handle playing that disconnect during "pending" or "syncing" steps. + } + else + { + Log.Warn($"PlayerDisconnected NOT CALLED!"); } } public ushort GetNextAvailablePlayerId() { - using (threadSafe.availablePlayerIds.GetLocked(out var availablePlayerIds)) + using (threadSafe.availablePlayerIds.GetLocked(out Queue availablePlayerIds)) { if (availablePlayerIds.Count > 0) + { return availablePlayerIds.Dequeue(); + } } return (ushort)Interlocked.Increment(ref highestPlayerID); // this is truncated to ushort.MaxValue @@ -288,7 +334,7 @@ public void UpdateMechaData(IMechaData mechaData, INebulaConnection conn) { return; } - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { if (connectedPlayers.TryGetValue(conn, out INebulaPlayer player)) { @@ -301,9 +347,9 @@ public void UpdateMechaData(IMechaData mechaData, INebulaConnection conn) public void SendTechRefundPackagesToClients(int techId) { //send players their contributions back - using (GetConnectedPlayers(out var connectedPlayers)) + using (GetConnectedPlayers(out Dictionary connectedPlayers)) { - foreach (var kvp in connectedPlayers) + foreach (KeyValuePair kvp in connectedPlayers) { INebulaPlayer curPlayer = kvp.Value; long techProgress = ((NebulaPlayer)curPlayer).ReleaseResearchProgress();