fix round-trip-time bug

This commit is contained in:
Bob
2010-03-10 17:33:04 +13:00
parent 79ce7c15d5
commit 962f1fa9b7
4 changed files with 42 additions and 43 deletions

View File

@@ -168,8 +168,8 @@ namespace OpenRA.Network
public void Receive( Action<int, byte[]> packetFn ) public void Receive( Action<int, byte[]> packetFn )
{ {
if( replayStream != null ) if( replayStream == null ) return;
{
var reader = new BinaryReader( replayStream ); var reader = new BinaryReader( replayStream );
while( replayStream.Position < replayStream.Length ) while( replayStream.Position < replayStream.Length )
{ {
@@ -183,13 +183,5 @@ namespace OpenRA.Network
} }
replayStream = null; replayStream = null;
} }
else
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( nextFrame++ ) );
ms.Write( new byte[] { 0xEF } );
packetFn( 0, ms.ToArray() );
}
}
} }
} }

View File

@@ -28,16 +28,17 @@ namespace OpenRA.Network
{ {
class OrderManager class OrderManager
{ {
int frameNumber = 0; public int FrameNumber { get; private set; }
public int FramesAhead = 0; public int FramesAhead = 0;
public bool GameStarted { get { return frameNumber != 0; } } public bool GameStarted { get { return FrameNumber != 0; } }
public IConnection Connection { get; private set; } public IConnection Connection { get; private set; }
Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();
Dictionary<int, Dictionary<int, byte[]>> frameClientData = Dictionary<int, Dictionary<int, byte[]>> frameClientData =
new Dictionary<int, Dictionary<int, byte[]>>(); new Dictionary<int, Dictionary<int, byte[]>>();
List<int> readyForFrames = new List<int>();
List<Order> localOrders = new List<Order>(); List<Order> localOrders = new List<Order>();
FileStream replaySaveFile; FileStream replaySaveFile;
@@ -46,13 +47,11 @@ namespace OpenRA.Network
{ {
if (GameStarted) return; if (GameStarted) return;
frameNumber = 1; FrameNumber = 1;
for( int i = frameNumber ; i <= FramesAhead ; i++ ) for( int i = FrameNumber ; i <= FramesAhead ; i++ )
Connection.Send( new List<Order>().Serialize( i ) ); Connection.Send( new List<Order>().Serialize( i ) );
} }
public int FrameNumber { get { return frameNumber; } }
public OrderManager( IConnection conn ) public OrderManager( IConnection conn )
{ {
Connection = conn; Connection = conn;
@@ -88,8 +87,8 @@ namespace OpenRA.Network
( clientId, packet ) => ( clientId, packet ) =>
{ {
var frame = BitConverter.ToInt32( packet, 0 ); var frame = BitConverter.ToInt32( packet, 0 );
if( packet.Length == 5 && packet[ 4 ] == 0xEF ) if( packet.Length == 5 && packet[ 4 ] == 0xBF )
readyForFrames.Add( frame ); clientQuitTimes[ clientId ] = frame;
else if( packet.Length >= 5 && packet[ 4 ] == 0x65 ) else if( packet.Length >= 5 && packet[ 4 ] == 0x65 )
CheckSync( packet ); CheckSync( packet );
else if( frame == 0 ) else if( frame == 0 )
@@ -132,23 +131,31 @@ namespace OpenRA.Network
public bool IsReadyForNextFrame 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 ) public void Tick( World world )
{ {
if( !IsReadyForNextFrame ) if( !IsReadyForNextFrame )
throw new InvalidOperationException(); throw new InvalidOperationException();
readyForFrames.RemoveAll( f => f <= FrameNumber );
Connection.Send( localOrders.Serialize( FrameNumber + FramesAhead ) ); Connection.Send( localOrders.Serialize( FrameNumber + FramesAhead ) );
localOrders.Clear(); 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>(); var sync = new List<int>();
sync.Add( world.SyncHash() ); 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 ); UnitOrders.ProcessOrder( world, order.Client, order.Order );
sync.Add( world.SyncHash() ); sync.Add( world.SyncHash() );
@@ -160,7 +167,7 @@ namespace OpenRA.Network
CheckSync( ss ); CheckSync( ss );
++frameNumber; ++FrameNumber;
} }
void WriteToReplay( Dictionary<int, byte[]> frameData, byte[] syncData ) void WriteToReplay( Dictionary<int, byte[]> frameData, byte[] syncData )

View File

@@ -34,6 +34,8 @@ namespace OpenRA.Server
public int ExpectLength = 8; public int ExpectLength = 8;
public int Frame = 0; public int Frame = 0;
public int MostRecentFrame = 0;
/* client data */ /* client data */
public int PlayerIndex; public int PlayerIndex;
@@ -98,6 +100,7 @@ namespace OpenRA.Server
case ReceiveState.Data: case ReceiveState.Data:
{ {
Server.DispatchOrders(this, Frame, bytes); Server.DispatchOrders(this, Frame, bytes);
MostRecentFrame = Frame;
ExpectLength = 8; ExpectLength = 8;
State = ReceiveState.Header; State = ReceiveState.Header;

View File

@@ -156,7 +156,6 @@ namespace OpenRA.Server
if (conns.All(c => inFlightFrames[conn.Frame].Contains(c))) if (conns.All(c => inFlightFrames[conn.Frame].Contains(c)))
{ {
inFlightFrames.Remove(conn.Frame); inFlightFrames.Remove(conn.Frame);
DispatchOrders(null, conn.Frame, new byte[] { 0xef });
} }
} }
} }
@@ -431,10 +430,14 @@ namespace OpenRA.Server
SyncLobbyInfo(); SyncLobbyInfo();
// start the game if everyone is ready. // 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!"); Console.WriteLine("All players are ready. Starting the game!");
GameStarted = true; GameStarted = true;
foreach( var c in conns )
foreach( var d in conns )
DispatchOrdersToClient( c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF } );
DispatchOrders(null, 0, DispatchOrders(null, 0,
new ServerOrder("StartGame", "").Serialize()); new ServerOrder("StartGame", "").Serialize());
} }
@@ -494,14 +497,8 @@ namespace OpenRA.Server
lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex); 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 c in conns )
DispatchOrders( toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf } );
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 });
}
if (conns.Count == 0) OnServerEmpty(); if (conns.Count == 0) OnServerEmpty();
else SyncLobbyInfo(); else SyncLobbyInfo();