fix round-trip-time bug
This commit is contained in:
@@ -168,28 +168,20 @@ namespace OpenRA.Network
|
||||
|
||||
public void Receive( Action<int, byte[]> packetFn )
|
||||
{
|
||||
if( replayStream != null )
|
||||
{
|
||||
var reader = new BinaryReader( replayStream );
|
||||
while( replayStream.Position < replayStream.Length )
|
||||
{
|
||||
var client = reader.ReadInt32();
|
||||
var packetLen = reader.ReadInt32();
|
||||
var packet = reader.ReadBytes( packetLen );
|
||||
packetFn( client, packet );
|
||||
if( replayStream == null ) return;
|
||||
|
||||
if( !Game.orderManager.GameStarted )
|
||||
return;
|
||||
}
|
||||
replayStream = null;
|
||||
}
|
||||
else
|
||||
var reader = new BinaryReader( replayStream );
|
||||
while( replayStream.Position < replayStream.Length )
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( nextFrame++ ) );
|
||||
ms.Write( new byte[] { 0xEF } );
|
||||
packetFn( 0, ms.ToArray() );
|
||||
var client = reader.ReadInt32();
|
||||
var packetLen = reader.ReadInt32();
|
||||
var packet = reader.ReadBytes( packetLen );
|
||||
packetFn( client, packet );
|
||||
|
||||
if( !Game.orderManager.GameStarted )
|
||||
return;
|
||||
}
|
||||
replayStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,16 +28,17 @@ namespace OpenRA.Network
|
||||
{
|
||||
class OrderManager
|
||||
{
|
||||
int frameNumber = 0;
|
||||
public int FrameNumber { get; private set; }
|
||||
|
||||
public int FramesAhead = 0;
|
||||
|
||||
public bool GameStarted { get { return frameNumber != 0; } }
|
||||
public bool GameStarted { get { return FrameNumber != 0; } }
|
||||
public IConnection Connection { get; private set; }
|
||||
|
||||
Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();
|
||||
|
||||
Dictionary<int, Dictionary<int, byte[]>> frameClientData =
|
||||
new Dictionary<int, Dictionary<int, byte[]>>();
|
||||
List<int> readyForFrames = new List<int>();
|
||||
List<Order> localOrders = new List<Order>();
|
||||
|
||||
FileStream replaySaveFile;
|
||||
@@ -46,13 +47,11 @@ namespace OpenRA.Network
|
||||
{
|
||||
if (GameStarted) return;
|
||||
|
||||
frameNumber = 1;
|
||||
for( int i = frameNumber ; i <= FramesAhead ; i++ )
|
||||
FrameNumber = 1;
|
||||
for( int i = FrameNumber ; i <= FramesAhead ; i++ )
|
||||
Connection.Send( new List<Order>().Serialize( i ) );
|
||||
}
|
||||
|
||||
public int FrameNumber { get { return frameNumber; } }
|
||||
|
||||
public OrderManager( IConnection conn )
|
||||
{
|
||||
Connection = conn;
|
||||
@@ -88,8 +87,8 @@ namespace OpenRA.Network
|
||||
( clientId, packet ) =>
|
||||
{
|
||||
var frame = BitConverter.ToInt32( packet, 0 );
|
||||
if( packet.Length == 5 && packet[ 4 ] == 0xEF )
|
||||
readyForFrames.Add( frame );
|
||||
if( packet.Length == 5 && packet[ 4 ] == 0xBF )
|
||||
clientQuitTimes[ clientId ] = frame;
|
||||
else if( packet.Length >= 5 && packet[ 4 ] == 0x65 )
|
||||
CheckSync( packet );
|
||||
else if( frame == 0 )
|
||||
@@ -132,23 +131,31 @@ namespace OpenRA.Network
|
||||
|
||||
public bool IsReadyForNextFrame
|
||||
{
|
||||
get { return readyForFrames.Contains( FrameNumber ); }
|
||||
get
|
||||
{
|
||||
return FrameNumber > 0 &&
|
||||
clientQuitTimes
|
||||
.Where( x => FrameNumber <= x.Value )
|
||||
.All( x => frameClientData.GetOrAdd( FrameNumber ).ContainsKey( x.Key ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if( !IsReadyForNextFrame )
|
||||
throw new InvalidOperationException();
|
||||
readyForFrames.RemoveAll( f => f <= FrameNumber );
|
||||
|
||||
Connection.Send( localOrders.Serialize( FrameNumber + FramesAhead ) );
|
||||
localOrders.Clear();
|
||||
|
||||
var frameData = frameClientData[ FrameNumber ];
|
||||
var frameData = clientQuitTimes
|
||||
.Where( x => FrameNumber <= x.Value )
|
||||
.OrderBy( x => x.Key )
|
||||
.ToDictionary( k => k.Key, v => frameClientData[ FrameNumber ][ v.Key ] );
|
||||
var sync = new List<int>();
|
||||
sync.Add( world.SyncHash() );
|
||||
|
||||
foreach( var order in frameData.OrderBy( p => p.Key ).SelectMany( o => o.Value.ToOrderList( world ).Select( a => new { Client = o.Key, Order = a } ) ) )
|
||||
foreach( var order in frameData.SelectMany( o => o.Value.ToOrderList( world ).Select( a => new { Client = o.Key, Order = a } ) ) )
|
||||
{
|
||||
UnitOrders.ProcessOrder( world, order.Client, order.Order );
|
||||
sync.Add( world.SyncHash() );
|
||||
@@ -160,7 +167,7 @@ namespace OpenRA.Network
|
||||
|
||||
CheckSync( ss );
|
||||
|
||||
++frameNumber;
|
||||
++FrameNumber;
|
||||
}
|
||||
|
||||
void WriteToReplay( Dictionary<int, byte[]> frameData, byte[] syncData )
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace OpenRA.Server
|
||||
public int ExpectLength = 8;
|
||||
public int Frame = 0;
|
||||
|
||||
public int MostRecentFrame = 0;
|
||||
|
||||
/* client data */
|
||||
public int PlayerIndex;
|
||||
|
||||
@@ -98,6 +100,7 @@ namespace OpenRA.Server
|
||||
case ReceiveState.Data:
|
||||
{
|
||||
Server.DispatchOrders(this, Frame, bytes);
|
||||
MostRecentFrame = Frame;
|
||||
ExpectLength = 8;
|
||||
State = ReceiveState.Header;
|
||||
|
||||
|
||||
@@ -156,7 +156,6 @@ namespace OpenRA.Server
|
||||
if (conns.All(c => inFlightFrames[conn.Frame].Contains(c)))
|
||||
{
|
||||
inFlightFrames.Remove(conn.Frame);
|
||||
DispatchOrders(null, conn.Frame, new byte[] { 0xef });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,10 +430,14 @@ namespace OpenRA.Server
|
||||
SyncLobbyInfo();
|
||||
|
||||
// start the game if everyone is ready.
|
||||
if (conns.All(c => GetClient(c).State == Session.ClientState.Ready))
|
||||
if (conns.Count > 0 && conns.All(c => GetClient(c).State == Session.ClientState.Ready))
|
||||
{
|
||||
Console.WriteLine("All players are ready. Starting the game!");
|
||||
GameStarted = true;
|
||||
foreach( var c in conns )
|
||||
foreach( var d in conns )
|
||||
DispatchOrdersToClient( c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF } );
|
||||
|
||||
DispatchOrders(null, 0,
|
||||
new ServerOrder("StartGame", "").Serialize());
|
||||
}
|
||||
@@ -494,14 +497,8 @@ namespace OpenRA.Server
|
||||
|
||||
lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex);
|
||||
|
||||
/* don't get stuck waiting for the dropped player, if they were the one holding up a frame */
|
||||
|
||||
foreach( var f in inFlightFrames.ToArray() )
|
||||
if (conns.All(c => f.Value.Contains(c)))
|
||||
{
|
||||
inFlightFrames.Remove(f.Key);
|
||||
DispatchOrders(null, f.Key, new byte[] { 0xef });
|
||||
}
|
||||
foreach( var c in conns )
|
||||
DispatchOrders( toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf } );
|
||||
|
||||
if (conns.Count == 0) OnServerEmpty();
|
||||
else SyncLobbyInfo();
|
||||
|
||||
Reference in New Issue
Block a user