Refactor server orders

This commit is contained in:
teinarss
2021-06-14 21:04:59 +02:00
committed by Paul Chote
parent a8900d9860
commit 1f1373509e
5 changed files with 48 additions and 19 deletions

View File

@@ -52,6 +52,9 @@ namespace OpenRA
// Length of orders with type OrderType.SyncHash // Length of orders with type OrderType.SyncHash
public const int SyncHashOrderLength = 13; public const int SyncHashOrderLength = 13;
// Length of orders with type OrderType.Disconnect
public const int DisconnectOrderLength = 5;
public readonly string OrderString; public readonly string OrderString;
public readonly Actor Subject; public readonly Actor Subject;
public readonly bool Queued; public readonly bool Queued;

View File

@@ -131,8 +131,10 @@ namespace OpenRA.Network
return; 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 == Order.DisconnectOrderLength + 4 && packet[4] == (byte)OrderType.Disconnect)
pendingPackets.Remove(clientId); {
pendingPackets.Remove(BitConverter.ToInt32(packet, 5));
}
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)

View File

@@ -115,7 +115,7 @@ namespace OpenRA.Network
continue; continue;
var packet = tmpPacketPair.Packet; var packet = tmpPacketPair.Packet;
if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect) if (packet.Length == Order.DisconnectOrderLength + 4 && packet[4] == (byte)OrderType.Disconnect)
{ {
var lastClientFrame = lastClientsFrame[client]; var lastClientFrame = lastClientsFrame[client];
var lastFramePacket = BitConverter.GetBytes(lastClientFrame); var lastFramePacket = BitConverter.GetBytes(lastClientFrame);

View File

@@ -68,6 +68,6 @@ namespace OpenRA.Server
// The protocol for server and world orders // The protocol for server and world orders
// This applies after the handshake has completed, and is provided to support // This applies after the handshake has completed, and is provided to support
// alternative server implementations that wish to support multiple versions in parallel // alternative server implementations that wish to support multiple versions in parallel
public const int Orders = 12; public const int Orders = 13;
} }
} }

View File

@@ -482,7 +482,7 @@ namespace OpenRA.Server
Log.Write("server", "{0} ({1}) has joined the game.", client.Name, newConn.EndPoint); Log.Write("server", "{0} ({1}) has joined the game.", client.Name, newConn.EndPoint);
// Report to all other players // Report to all other players
SendMessage($"{client.Name} has joined the game.", newConn); SendMessage($"{client.Name} has joined the game.");
// Send initial ping // Send initial ping
SendOrderTo(newConn, "Ping", Game.RunTime.ToString(CultureInfo.InvariantCulture)); SendOrderTo(newConn, "Ping", Game.RunTime.ToString(CultureInfo.InvariantCulture));
@@ -737,12 +737,17 @@ namespace OpenRA.Server
public void DispatchOrdersToClients(Connection conn, int frame, byte[] data) public void DispatchOrdersToClients(Connection conn, int frame, byte[] data)
{ {
var from = conn?.PlayerIndex ?? 0; var from = conn.PlayerIndex;
var frameData = CreateFrame(from, frame, data); var frameData = CreateFrame(from, frame, data);
foreach (var c in Conns.ToList()) foreach (var c in Conns.ToList())
if (c != conn && c.Validated) if (c != conn && c.Validated)
DispatchFrameToClient(c, from, frameData); DispatchFrameToClient(c, from, frameData);
RecordOrder(frame, data, from);
}
void RecordOrder(int frame, byte[] data, int from)
{
if (recorder != null) if (recorder != null)
{ {
recorder.ReceiveFrame(from, frame, data); recorder.ReceiveFrame(from, frame, data);
@@ -757,14 +762,31 @@ namespace OpenRA.Server
} }
} }
public void DispatchServerOrdersToClients(Order order)
{
DispatchServerOrdersToClients(order.Serialize());
}
public void DispatchServerOrdersToClients(byte[] data)
{
var from = 0;
var frame = 0;
var frameData = CreateFrame(from, frame, data);
foreach (var c in Conns.ToList())
if (c.Validated)
DispatchFrameToClient(c, from, frameData);
RecordOrder(frame, data, from);
}
public void DispatchOrders(Connection conn, int frame, byte[] data) public void DispatchOrders(Connection conn, int frame, byte[] data)
{ {
if (frame == 0 && conn != null) if (frame == 0)
InterpretServerOrders(conn, data); InterpretServerOrders(conn, data);
else else
DispatchOrdersToClients(conn, frame, data); DispatchOrdersToClients(conn, frame, data);
if (GameSave != null && conn != null) if (GameSave != null)
GameSave.DispatchOrders(conn, frame, data); GameSave.DispatchOrders(conn, frame, data);
} }
@@ -791,9 +813,9 @@ namespace OpenRA.Server
DispatchOrdersToClient(conn, 0, 0, Order.FromTargetString(order, data, true).Serialize()); DispatchOrdersToClient(conn, 0, 0, Order.FromTargetString(order, data, true).Serialize());
} }
public void SendMessage(string text, Connection conn = null) public void SendMessage(string text)
{ {
DispatchOrdersToClients(conn, 0, Order.FromTargetString("Message", text, true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("Message", text, true));
if (Type == ServerType.Dedicated) if (Type == ServerType.Dedicated)
Console.WriteLine($"[{DateTime.Now.ToString(Settings.TimestampFormat)}] {text}"); Console.WriteLine($"[{DateTime.Now.ToString(Settings.TimestampFormat)}] {text}");
@@ -903,7 +925,7 @@ namespace OpenRA.Server
Directory.CreateDirectory(baseSavePath); Directory.CreateDirectory(baseSavePath);
GameSave.Save(Path.Combine(baseSavePath, filename)); GameSave.Save(Path.Combine(baseSavePath, filename));
DispatchOrdersToClients(null, 0, Order.FromTargetString("GameSaved", filename, true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("GameSaved", filename, true));
} }
break; break;
@@ -1039,7 +1061,10 @@ namespace OpenRA.Server
} }
} }
DispatchOrders(toDrop, toDrop.MostRecentFrame, new[] { (byte)OrderType.Disconnect }); var disconnectPacket = new MemoryStream(5);
disconnectPacket.WriteByte((byte)OrderType.Disconnect);
disconnectPacket.Write(toDrop.PlayerIndex);
DispatchServerOrdersToClients(disconnectPacket.ToArray());
// All clients have left: clean up // All clients have left: clean up
if (!Conns.Any(c => c.Validated)) if (!Conns.Any(c => c.Validated))
@@ -1061,7 +1086,7 @@ namespace OpenRA.Server
lock (LobbyInfo) lock (LobbyInfo)
{ {
if (State == ServerState.WaitingPlayers) // Don't do this while the game is running, it breaks things! if (State == ServerState.WaitingPlayers) // Don't do this while the game is running, it breaks things!
DispatchOrders(null, 0, Order.FromTargetString("SyncInfo", LobbyInfo.Serialize(), true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("SyncInfo", LobbyInfo.Serialize(), true));
foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>()) foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>())
t.LobbyInfoSynced(this); t.LobbyInfoSynced(this);
@@ -1078,7 +1103,7 @@ namespace OpenRA.Server
// TODO: Only need to sync the specific client that has changed to avoid conflicts! // TODO: Only need to sync the specific client that has changed to avoid conflicts!
var clientData = LobbyInfo.Clients.Select(client => client.Serialize()).ToList(); var clientData = LobbyInfo.Clients.Select(client => client.Serialize()).ToList();
DispatchOrders(null, 0, Order.FromTargetString("SyncLobbyClients", clientData.WriteToString(), true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("SyncLobbyClients", clientData.WriteToString(), true));
foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>()) foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>())
t.LobbyInfoSynced(this); t.LobbyInfoSynced(this);
@@ -1095,7 +1120,7 @@ namespace OpenRA.Server
// TODO: Don't sync all the slots if just one changed! // TODO: Don't sync all the slots if just one changed!
var slotData = LobbyInfo.Slots.Select(slot => slot.Value.Serialize()).ToList(); var slotData = LobbyInfo.Slots.Select(slot => slot.Value.Serialize()).ToList();
DispatchOrders(null, 0, Order.FromTargetString("SyncLobbySlots", slotData.WriteToString(), true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("SyncLobbySlots", slotData.WriteToString(), true));
foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>()) foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>())
t.LobbyInfoSynced(this); t.LobbyInfoSynced(this);
@@ -1111,7 +1136,7 @@ namespace OpenRA.Server
{ {
var sessionData = new List<MiniYamlNode> { LobbyInfo.GlobalSettings.Serialize() }; var sessionData = new List<MiniYamlNode> { LobbyInfo.GlobalSettings.Serialize() };
DispatchOrders(null, 0, Order.FromTargetString("SyncLobbyGlobalSettings", sessionData.WriteToString(), true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("SyncLobbyGlobalSettings", sessionData.WriteToString(), true));
foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>()) foreach (var t in serverTraits.WithInterface<INotifySyncLobbyInfo>())
t.LobbyInfoSynced(this); t.LobbyInfoSynced(this);
@@ -1126,7 +1151,7 @@ namespace OpenRA.Server
var clientPings = LobbyInfo.ClientPings.Select(ping => ping.Serialize()).ToList(); var clientPings = LobbyInfo.ClientPings.Select(ping => ping.Serialize()).ToList();
// Note that syncing pings doesn't trigger INotifySyncLobbyInfo // Note that syncing pings doesn't trigger INotifySyncLobbyInfo
DispatchOrders(null, 0, Order.FromTargetString("SyncClientPings", clientPings.WriteToString(), true).Serialize()); DispatchServerOrdersToClients(Order.FromTargetString("SyncClientPings", clientPings.WriteToString(), true));
} }
} }
@@ -1194,8 +1219,7 @@ namespace OpenRA.Server
} }
} }
DispatchOrders(null, 0, DispatchServerOrdersToClients(Order.FromTargetString("StartGame", startGameData, true));
Order.FromTargetString("StartGame", startGameData, true).Serialize());
foreach (var t in serverTraits.WithInterface<IStartGame>()) foreach (var t in serverTraits.WithInterface<IStartGame>())
t.GameStarted(this); t.GameStarted(this);