Fix crash in OrderManager

This commit is contained in:
teinarss
2021-05-21 18:19:58 +02:00
committed by Paul Chote
parent acccb01c76
commit d10c592987
3 changed files with 41 additions and 25 deletions

View File

@@ -491,6 +491,20 @@ namespace OpenRA
{
var shellmap = ChooseShellmap();
// Add a spectator client for the local player,
// who is controlling the map via scripted orders
OrderManager.LobbyInfo.Clients.Add(new Session.Client
{
Index = OrderManager.Connection.LocalClientId,
Name = Settings.Player.Name,
PreferredColor = Settings.Player.Color,
Color = Settings.Player.Color,
Faction = "Random",
SpawnPoint = 0,
Team = 0,
State = Session.ClientState.Ready
});
using (new PerfTimer("StartGame"))
{
StartGame(shellmap, WorldType.Shellmap);

View File

@@ -22,9 +22,6 @@ namespace OpenRA.Network
{
readonly SyncReport syncReport;
// These are the clients who we expect to receive orders / sync from before we can simulate the next tick
readonly HashSet<int> activeClients = new HashSet<int>();
readonly Dictionary<int, Queue<byte[]>> pendingPackets = new Dictionary<int, Queue<byte[]>>();
public Session LobbyInfo = new Session();
@@ -52,7 +49,6 @@ namespace OpenRA.Network
readonly List<Order> localOrders = new List<Order>();
readonly List<Order> localImmediateOrders = new List<Order>();
readonly List<(int ClientId, byte[] Packet)> immediatePackets = new List<(int ClientId, byte[] Packet)>();
readonly List<ChatLine> chatCache = new List<ChatLine>();
@@ -83,6 +79,10 @@ namespace OpenRA.Network
if (GameStarted)
return;
foreach (var client in LobbyInfo.Clients)
if (!client.IsBot)
pendingPackets.Add(client.Index, new Queue<byte[]>());
// Generating sync reports is expensive, so only do it if we have
// other players to compare against if a desync did occur
generateSyncReport = !(Connection is ReplayConnection) && LobbyInfo.GlobalSettings.EnableSyncReports;
@@ -132,9 +132,13 @@ namespace OpenRA.Network
Connection.Receive(
(clientId, packet) =>
{
// HACK: The shellmap relies on ticking a disposed OM
if (disposed && World.Type != WorldType.Shellmap)
return;
var frame = BitConverter.ToInt32(packet, 0);
if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect)
activeClients.Remove(clientId);
pendingPackets.Remove(clientId);
else if (packet.Length > 4 && packet[4] == (byte)OrderType.SyncHash)
{
if (packet.Length != 4 + Order.SyncHashOrderLength)
@@ -146,27 +150,24 @@ namespace OpenRA.Network
CheckSync(packet);
}
else if (frame == 0)
immediatePackets.Add((clientId, packet));
{
foreach (var o in packet.ToOrderList(World))
{
UnitOrders.ProcessOrder(this, World, clientId, o);
// A mod switch or other event has pulled the ground from beneath us
if (disposed)
return;
}
}
else
{
activeClients.Add(clientId);
pendingPackets.GetOrAdd(clientId).Enqueue(packet);
if (pendingPackets.TryGetValue(clientId, out var queue))
queue.Enqueue(packet);
else
Log.Write("debug", $"Received packet from disconnected client '{clientId}'");
}
});
foreach (var p in immediatePackets)
{
foreach (var o in p.Packet.ToOrderList(World))
{
UnitOrders.ProcessOrder(this, World, p.ClientId, o);
// A mod switch or other event has pulled the ground from beneath us
if (disposed)
return;
}
}
immediatePackets.Clear();
}
Dictionary<int, byte[]> syncForFrame = new Dictionary<int, byte[]>();
@@ -187,7 +188,7 @@ namespace OpenRA.Network
syncForFrame.Add(frame, packet);
}
public bool IsReadyForNextFrame => GameStarted && activeClients.All(client => pendingPackets[client].Count > 0);
public bool IsReadyForNextFrame => GameStarted && pendingPackets.All(p => p.Value.Count > 0);
public void Tick()
{
@@ -201,10 +202,10 @@ namespace OpenRA.Network
var clientOrders = new List<ClientOrder>();
foreach (var clientId in activeClients)
foreach (var (clientId, clientPackets) in pendingPackets)
{
// The IsReadyForNextFrame check above guarantees that all clients have sent a packet
var frameData = pendingPackets[clientId].Dequeue();
var frameData = clientPackets.Dequeue();
// Orders are synchronised by sending an initial FramesAhead set of empty packets
// and then making sure that we enqueue and process exactly one packet for each player each tick.

View File

@@ -153,6 +153,7 @@ namespace OpenRA.Network
public bool IsReady => State == ClientState.Ready;
public bool IsInvalid => State == ClientState.Invalid;
public bool IsObserver => Slot == null;
public bool IsBot => Bot != null;
// Linked to the online player database
public string Fingerprint;