extract FrameData from OrderManager. fix disconnect bug in NetworkConnection

This commit is contained in:
Bob
2010-10-10 23:21:52 +13:00
parent 3724f46a3e
commit f8776d773d
4 changed files with 70 additions and 32 deletions

View File

@@ -114,12 +114,13 @@ namespace OpenRA.Network
receivedPackets.Add( new ReceivedPacket { FromClient = client, Data = buf } );
}
}
catch( SocketException )
catch { }
finally
{
connectionState = ConnectionState.NotConnected;
if( socket != null )
socket.Close();
}
catch ( IOException ) { socket.Close(); }
catch (ThreadAbortException ) { socket.Close(); }
}
) { IsBackground = true };
t.Start();
@@ -134,12 +135,10 @@ namespace OpenRA.Network
try
{
var ms = new MemoryStream();
ms.Write(BitConverter.GetBytes((int)packet.Length));
ms.Write(packet);
ms.WriteTo(socket.GetStream());
}
catch (SocketException) { /* drop this on the floor; we'll pick up the disconnect from the reader thread */ }
catch (ObjectDisposedException) { /* ditto */ }

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenRA.Network
{
class FrameData
{
public struct ClientOrder
{
public int Client;
public Order Order;
}
readonly Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();
readonly Dictionary<int, Dictionary<int, byte[]>> framePackets = new Dictionary<int, Dictionary<int, byte[]>>();
public IEnumerable<int> ClientsPlayingInFrame( int frame )
{
return clientQuitTimes
.Where( x => frame <= x.Value )
.Select( x => x.Key )
.OrderBy( x => x );
}
public void ClientQuit( int clientId, int lastClientFrame )
{
clientQuitTimes.Add( clientId, lastClientFrame );
}
public void AddFrameOrders( int clientId, int frame, byte[] orders )
{
var frameData = framePackets.GetOrAdd( frame );
frameData.Add( clientId, orders );
}
public bool IsReadyForFrame( int frame )
{
var frameData = framePackets.GetOrAdd( frame );
return ClientsPlayingInFrame( frame )
.All( client => frameData.ContainsKey( client ) );
}
public IEnumerable<ClientOrder> OrdersForFrame( World world, int frame )
{
var frameData = framePackets[ frame ];
var clientData = ClientsPlayingInFrame( frame )
.ToDictionary( k => k, v => frameData[ v ] );
return clientData
.SelectMany( x => x.Value
.ToOrderList( world )
.Select( o => new ClientOrder { Client = x.Key, Order = o } ) );
}
}
}

View File

@@ -18,7 +18,8 @@ namespace OpenRA.Network
{
class OrderManager : IDisposable
{
SyncReport syncReport = new SyncReport();
readonly SyncReport syncReport = new SyncReport();
readonly FrameData frameData = new FrameData();
public int FrameNumber { get; private set; }
@@ -29,10 +30,6 @@ namespace OpenRA.Network
public readonly int SyncHeaderSize = 9;
Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();
Dictionary<int, Dictionary<int, byte[]>> frameClientData =
new Dictionary<int, Dictionary<int, byte[]>>();
List<Order> localOrders = new List<Order>();
public void StartGame()
@@ -74,13 +71,13 @@ namespace OpenRA.Network
{
var frame = BitConverter.ToInt32( packet, 0 );
if( packet.Length == 5 && packet[ 4 ] == 0xBF )
clientQuitTimes[ clientId ] = frame;
frameData.ClientQuit( clientId, frame );
else if( packet.Length >= 5 && packet[ 4 ] == 0x65 )
CheckSync( packet );
else if( frame == 0 )
immediatePackets.Add( Pair.New( clientId, packet ) );
else
frameClientData.GetOrAdd( frame ).Add( clientId, packet );
frameData.AddFrameOrders( clientId, frame, packet );
} );
foreach( var p in immediatePackets )
@@ -123,12 +120,7 @@ namespace OpenRA.Network
void OutOfSync(int frame, int index)
{
var frameData = clientQuitTimes
.Where( x => frame <= x.Value )
.OrderBy( x => x.Key )
.ToDictionary( k => k.Key, v => frameClientData[ FrameNumber ][ v.Key ] );
var order = frameData.SelectMany( o => o.Value.ToOrderList( Game.world ).Select( a => new { Client = o.Key, Order = a } ) ).ElementAt(index);
var order = frameData.OrdersForFrame( Game.world, frame ).ElementAt(index);
throw new InvalidOperationException("Out of sync in frame {0}.\n {1}".F(frame, order.Order.ToString()));
}
@@ -144,13 +136,7 @@ namespace OpenRA.Network
public bool IsReadyForNextFrame
{
get
{
return FrameNumber > 0 &&
clientQuitTimes
.Where( x => FrameNumber <= x.Value )
.All( x => frameClientData.GetOrAdd( FrameNumber ).ContainsKey( x.Key ) );
}
get { return FrameNumber >= 1 && frameData.IsReadyForFrame( FrameNumber ); }
}
public void Tick( World world )
@@ -161,14 +147,10 @@ namespace OpenRA.Network
Connection.Send( localOrders.Serialize( FrameNumber + FramesAhead ) );
localOrders.Clear();
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.SelectMany( o => o.Value.ToOrderList( world ).Select( a => new { Client = o.Key, Order = a } ) ) )
foreach( var order in frameData.OrdersForFrame( world, FrameNumber) )
{
UnitOrders.ProcessOrder( world, order.Client, order.Order );
sync.Add( world.SyncHash() );

View File

@@ -222,6 +222,7 @@
<Compile Include="ActorReference.cs" />
<Compile Include="ModData.cs" />
<Compile Include="Map.cs" />
<Compile Include="Network\FrameData.cs" />
<Compile Include="Network\ReplayConnection.cs" />
<Compile Include="Network\Session.cs" />
<Compile Include="ObjectCreator.cs" />