Skip to content

Commit

Permalink
Merge pull request #436 from PhantomGamers/patch-reform-fix
Browse files Browse the repository at this point in the history
Fixes
  • Loading branch information
hubastard authored Sep 10, 2021
2 parents 12952b3 + fe4c12d commit 264a5a0
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ class FoundationBuildUpdateProcessor : PacketProcessor<FoundationBuildUpdatePack

public override void ProcessPacket(FoundationBuildUpdatePacket packet, NebulaConnection conn)
{
// TODO: MISSING CLIENT -> HOST -> CLIENT CODE

PlanetData planet = GameMain.galaxy.PlanetById(packet.PlanetId);
PlanetFactory factory = IsHost ? GameMain.data.GetOrCreateFactory(planet) : planet?.factory;
if (factory != null)
Expand Down Expand Up @@ -57,6 +55,11 @@ public override void ProcessPacket(FoundationBuildUpdatePacket packet, NebulaCon
}
}
}

if (IsHost)
{
Multiplayer.Session.Network.SendPacketToStar(packet, planet.star.id);
}
}
}
}
178 changes: 112 additions & 66 deletions NebulaNetwork/PlayerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace NebulaNetwork
{
public class PlayerManager : IPlayerManager
{
sealed class ThreadSafe
private sealed class ThreadSafe
{
internal readonly Dictionary<INebulaConnection, INebulaPlayer> pendingPlayers = new Dictionary<INebulaConnection, INebulaPlayer>();
internal readonly Dictionary<INebulaConnection, INebulaPlayer> syncingPlayers = new Dictionary<INebulaConnection, INebulaPlayer>();
Expand All @@ -27,26 +27,34 @@ sealed class ThreadSafe
private readonly ThreadSafe threadSafe = new ThreadSafe();
private int highestPlayerID = 0;

public Locker GetPendingPlayers(out Dictionary<INebulaConnection, INebulaPlayer> pendingPlayers) =>
threadSafe.pendingPlayers.GetLocked(out pendingPlayers);
public Locker GetPendingPlayers(out Dictionary<INebulaConnection, INebulaPlayer> pendingPlayers)
{
return threadSafe.pendingPlayers.GetLocked(out pendingPlayers);
}

public Locker GetSyncingPlayers(out Dictionary<INebulaConnection, INebulaPlayer> syncingPlayers) =>
threadSafe.syncingPlayers.GetLocked(out syncingPlayers);
public Locker GetSyncingPlayers(out Dictionary<INebulaConnection, INebulaPlayer> syncingPlayers)
{
return threadSafe.syncingPlayers.GetLocked(out syncingPlayers);
}

public Locker GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers) =>
threadSafe.connectedPlayers.GetLocked(out connectedPlayers);
public Locker GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers)
{
return threadSafe.connectedPlayers.GetLocked(out connectedPlayers);
}

public Locker GetSavedPlayerData(out Dictionary<string, IPlayerData> savedPlayerData) =>
threadSafe.savedPlayerData.GetLocked(out savedPlayerData);
public Locker GetSavedPlayerData(out Dictionary<string, IPlayerData> savedPlayerData)
{
return threadSafe.savedPlayerData.GetLocked(out savedPlayerData);
}

public IPlayerData[] GetAllPlayerDataIncludingHost()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> 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<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
result[i++] = kvp.Value.Data;
}
Expand All @@ -57,7 +65,7 @@ public IPlayerData[] GetAllPlayerDataIncludingHost()

public INebulaPlayer GetPlayer(INebulaConnection conn)
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
if (connectedPlayers.TryGetValue(conn, out INebulaPlayer player))
{
Expand All @@ -70,7 +78,7 @@ public INebulaPlayer GetPlayer(INebulaConnection conn)

public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)
{
using (GetSyncingPlayers(out var syncingPlayers))
using (GetSyncingPlayers(out Dictionary<INebulaConnection, INebulaPlayer> syncingPlayers))
{
if (syncingPlayers.TryGetValue(conn, out INebulaPlayer player))
{
Expand All @@ -83,9 +91,9 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)

public void SendPacketToAllPlayers<T>(T packet) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
INebulaPlayer player = kvp.Value;
player.SendPacket(packet);
Expand All @@ -96,11 +104,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)

public void SendPacketToLocalStar<T>(T packet) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalStarId == GameMain.data.localStar?.id)
{
player.SendPacket(packet);
Expand All @@ -111,11 +119,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)

public void SendPacketToLocalPlanet<T>(T packet) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalPlanetId == GameMain.data.mainPlayer.planetId)
{
player.SendPacket(packet);
Expand All @@ -126,11 +134,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)

public void SendPacketToPlanet<T>(T packet, int planetId) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalPlanetId == planetId)
{
player.SendPacket(packet);
Expand All @@ -141,11 +149,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)

public void SendPacketToStar<T>(T packet, int starId) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalStarId == starId)
{
player.SendPacket(packet);
Expand All @@ -156,11 +164,11 @@ public INebulaPlayer GetSyncingPlayer(INebulaConnection conn)

public void SendPacketToStarExcept<T>(T packet, int starId, INebulaConnection exclude) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalStarId == starId && player != GetPlayer(exclude))
{
player.SendPacket(packet);
Expand All @@ -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<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalStarId == starId && player.Connection != sender)
{
((NebulaPlayer)player).SendRawPacket(rawPacket);
Expand All @@ -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<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player.Data.LocalPlanetId == planetId && player.Connection != sender)
{
((NebulaPlayer)player).SendRawPacket(rawPacket);
Expand All @@ -201,11 +209,11 @@ public void SendRawPacketToPlanet(byte[] rawPacket, int planetId, INebulaConnect

public void SendPacketToOtherPlayers<T>(T packet, INebulaPlayer sender) where T : class, new()
{
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
var player = kvp.Value;
INebulaPlayer player = kvp.Value;
if (player != sender)
{
player.SendPacket(packet);
Expand All @@ -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<INebulaConnection, INebulaPlayer> pendingPlayers))
{
pendingPlayers.Add(conn, newPlayer);
}
Expand All @@ -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<INebulaConnection, INebulaPlayer> 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<INebulaConnection, INebulaPlayer> 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<INebulaConnection, INebulaPlayer> 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<ushort> 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<ushort> availablePlayerIds))
{
if (availablePlayerIds.Count > 0)
{
return availablePlayerIds.Dequeue();
}
}

return (ushort)Interlocked.Increment(ref highestPlayerID); // this is truncated to ushort.MaxValue
Expand All @@ -288,7 +334,7 @@ public void UpdateMechaData(IMechaData mechaData, INebulaConnection conn)
{
return;
}
using (GetConnectedPlayers(out var connectedPlayers))
using (GetConnectedPlayers(out Dictionary<INebulaConnection, INebulaPlayer> connectedPlayers))
{
if (connectedPlayers.TryGetValue(conn, out INebulaPlayer player))
{
Expand All @@ -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<INebulaConnection, INebulaPlayer> connectedPlayers))
{
foreach (var kvp in connectedPlayers)
foreach (KeyValuePair<INebulaConnection, INebulaPlayer> kvp in connectedPlayers)
{
INebulaPlayer curPlayer = kvp.Value;
long techProgress = ((NebulaPlayer)curPlayer).ReleaseResearchProgress();
Expand Down

0 comments on commit 264a5a0

Please sign in to comment.