Move order latency control to the server.

This commit is contained in:
Paul Chote
2021-09-02 22:08:28 +01:00
committed by abcdefg30
parent 6421c17515
commit 8f412f869d
9 changed files with 120 additions and 45 deletions

View File

@@ -32,6 +32,7 @@ namespace OpenRA.Network
public interface IConnection : IDisposable
{
int LocalClientId { get; }
void StartGame();
void Send(int frame, IEnumerable<Order> orders);
void SendImmediate(IEnumerable<Order> orders);
void SendSync(int frame, int syncHash, ulong defeatState);
@@ -47,6 +48,12 @@ namespace OpenRA.Network
int IConnection.LocalClientId => LocalClientId;
void IConnection.StartGame()
{
// Inject an empty frame to fill the gap we are making by projecting forward orders
orders.Enqueue((0, new OrderPacket(Array.Empty<Order>())));
}
void IConnection.Send(int frame, IEnumerable<Order> o)
{
orders.Enqueue((frame, new OrderPacket(o.ToArray())));
@@ -67,8 +74,9 @@ namespace OpenRA.Network
while (immediateOrders.TryDequeue(out var i))
orderManager.ReceiveImmediateOrders(LocalClientId, i);
// Project orders forward to the next frame
while (orders.TryDequeue(out var o))
orderManager.ReceiveOrders(LocalClientId, o);
orderManager.ReceiveOrders(LocalClientId, (o.Frame + 1, o.Orders));
while (sync.TryDequeue(out var s))
orderManager.ReceiveSync(s);
@@ -207,6 +215,8 @@ namespace OpenRA.Network
int IConnection.LocalClientId => clientId;
void IConnection.StartGame() { }
void IConnection.Send(int frame, IEnumerable<Order> orders)
{
var o = new OrderPacket(orders.ToArray());
@@ -270,19 +280,26 @@ namespace OpenRA.Network
Recorder?.Receive(clientId, OrderIO.SerializeSync(s));
}
while (sentOrders.TryDequeue(out var o))
{
orderManager.ReceiveOrders(clientId, o);
Recorder?.Receive(clientId, o.Orders.Serialize(o.Frame));
}
// Orders from other players
while (receivedPackets.TryDequeue(out var p))
{
var record = true;
if (OrderIO.TryParseDisconnect(p.Data, out var disconnectClient))
orderManager.ReceiveDisconnect(disconnectClient);
else if (OrderIO.TryParseSync(p.Data, out var sync))
orderManager.ReceiveSync(sync);
else if (OrderIO.TryParseAck(p, out var ackFrame))
{
if (!sentOrders.TryDequeue(out var q))
throw new InvalidOperationException("Received Ack with empty send queue");
// The Acknowledgement packet is a placeholder that tells us to process the first packet in our
// local sent buffer and the frame at which it should be applied. This is an optimization to avoid having
// to send the (much larger than 5 byte) packet back to us over the network.
orderManager.ReceiveOrders(clientId, (ackFrame, q.Orders));
Recorder?.Receive(clientId, q.Orders.Serialize(ackFrame));
record = false;
}
else if (OrderIO.TryParseOrderPacket(p.Data, out var orders))
{
if (orders.Frame == 0)
@@ -293,7 +310,8 @@ namespace OpenRA.Network
else
throw new InvalidDataException($"Received unknown packet from client {p.FromClient} with length {p.Data.Length}");
Recorder?.Receive(p.FromClient, p.Data);
if (record)
Recorder?.Receive(p.FromClient, p.Data);
}
}