Fix crash in OrderManager
This commit is contained in:
@@ -491,6 +491,20 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
var shellmap = ChooseShellmap();
|
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"))
|
using (new PerfTimer("StartGame"))
|
||||||
{
|
{
|
||||||
StartGame(shellmap, WorldType.Shellmap);
|
StartGame(shellmap, WorldType.Shellmap);
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ namespace OpenRA.Network
|
|||||||
{
|
{
|
||||||
readonly SyncReport syncReport;
|
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[]>>();
|
readonly Dictionary<int, Queue<byte[]>> pendingPackets = new Dictionary<int, Queue<byte[]>>();
|
||||||
|
|
||||||
public Session LobbyInfo = new Session();
|
public Session LobbyInfo = new Session();
|
||||||
@@ -52,7 +49,6 @@ namespace OpenRA.Network
|
|||||||
|
|
||||||
readonly List<Order> localOrders = new List<Order>();
|
readonly List<Order> localOrders = new List<Order>();
|
||||||
readonly List<Order> localImmediateOrders = 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>();
|
readonly List<ChatLine> chatCache = new List<ChatLine>();
|
||||||
|
|
||||||
@@ -83,6 +79,10 @@ namespace OpenRA.Network
|
|||||||
if (GameStarted)
|
if (GameStarted)
|
||||||
return;
|
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
|
// Generating sync reports is expensive, so only do it if we have
|
||||||
// other players to compare against if a desync did occur
|
// other players to compare against if a desync did occur
|
||||||
generateSyncReport = !(Connection is ReplayConnection) && LobbyInfo.GlobalSettings.EnableSyncReports;
|
generateSyncReport = !(Connection is ReplayConnection) && LobbyInfo.GlobalSettings.EnableSyncReports;
|
||||||
@@ -132,9 +132,13 @@ namespace OpenRA.Network
|
|||||||
Connection.Receive(
|
Connection.Receive(
|
||||||
(clientId, packet) =>
|
(clientId, packet) =>
|
||||||
{
|
{
|
||||||
|
// HACK: The shellmap relies on ticking a disposed OM
|
||||||
|
if (disposed && World.Type != WorldType.Shellmap)
|
||||||
|
return;
|
||||||
|
|
||||||
var frame = BitConverter.ToInt32(packet, 0);
|
var frame = BitConverter.ToInt32(packet, 0);
|
||||||
if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect)
|
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)
|
else if (packet.Length > 4 && packet[4] == (byte)OrderType.SyncHash)
|
||||||
{
|
{
|
||||||
if (packet.Length != 4 + Order.SyncHashOrderLength)
|
if (packet.Length != 4 + Order.SyncHashOrderLength)
|
||||||
@@ -146,27 +150,24 @@ namespace OpenRA.Network
|
|||||||
CheckSync(packet);
|
CheckSync(packet);
|
||||||
}
|
}
|
||||||
else if (frame == 0)
|
else if (frame == 0)
|
||||||
immediatePackets.Add((clientId, packet));
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
activeClients.Add(clientId);
|
foreach (var o in packet.ToOrderList(World))
|
||||||
pendingPackets.GetOrAdd(clientId).Enqueue(packet);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var p in immediatePackets)
|
|
||||||
{
|
{
|
||||||
foreach (var o in p.Packet.ToOrderList(World))
|
UnitOrders.ProcessOrder(this, World, clientId, o);
|
||||||
{
|
|
||||||
UnitOrders.ProcessOrder(this, World, p.ClientId, o);
|
|
||||||
|
|
||||||
// A mod switch or other event has pulled the ground from beneath us
|
// A mod switch or other event has pulled the ground from beneath us
|
||||||
if (disposed)
|
if (disposed)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
immediatePackets.Clear();
|
{
|
||||||
|
if (pendingPackets.TryGetValue(clientId, out var queue))
|
||||||
|
queue.Enqueue(packet);
|
||||||
|
else
|
||||||
|
Log.Write("debug", $"Received packet from disconnected client '{clientId}'");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<int, byte[]> syncForFrame = new Dictionary<int, byte[]>();
|
Dictionary<int, byte[]> syncForFrame = new Dictionary<int, byte[]>();
|
||||||
@@ -187,7 +188,7 @@ namespace OpenRA.Network
|
|||||||
syncForFrame.Add(frame, packet);
|
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()
|
public void Tick()
|
||||||
{
|
{
|
||||||
@@ -201,10 +202,10 @@ namespace OpenRA.Network
|
|||||||
|
|
||||||
var clientOrders = new List<ClientOrder>();
|
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
|
// 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
|
// 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.
|
// and then making sure that we enqueue and process exactly one packet for each player each tick.
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ namespace OpenRA.Network
|
|||||||
public bool IsReady => State == ClientState.Ready;
|
public bool IsReady => State == ClientState.Ready;
|
||||||
public bool IsInvalid => State == ClientState.Invalid;
|
public bool IsInvalid => State == ClientState.Invalid;
|
||||||
public bool IsObserver => Slot == null;
|
public bool IsObserver => Slot == null;
|
||||||
|
public bool IsBot => Bot != null;
|
||||||
|
|
||||||
// Linked to the online player database
|
// Linked to the online player database
|
||||||
public string Fingerprint;
|
public string Fingerprint;
|
||||||
|
|||||||
Reference in New Issue
Block a user