diff --git a/OpenRA.Server/Server.cs b/OpenRA.Server/Server.cs index 5db7614d00..a3324d645d 100644 --- a/OpenRA.Server/Server.cs +++ b/OpenRA.Server/Server.cs @@ -24,11 +24,8 @@ namespace OpenRA.Server for (; ; ) { var checkRead = new ArrayList(); - var checkWrite = new ArrayList(); - var checkError = new ArrayList(); checkRead.Add(listener.Server); - foreach (var c in conns) - checkRead.Add(c.socket); + foreach (var c in conns) checkRead.Add(c.socket); Socket.Select(checkRead, null, null, 1000000 /* 1s */); @@ -45,6 +42,7 @@ namespace OpenRA.Server { var newConn = new Connection { socket = listener.AcceptSocket() }; newConn.socket.Blocking = false; + newConn.socket.NoDelay = true; conns.Add(newConn); /* todo: assign a player number, setup host behavior, etc */ @@ -94,8 +92,8 @@ namespace OpenRA.Server { case ReceiveState.Header: { + conn.ExpectLength = BitConverter.ToInt32(bytes, 4) - 4; conn.Frame = BitConverter.ToInt32(bytes, 0); - conn.ExpectLength = BitConverter.ToInt32(bytes, 4); conn.State = ReceiveState.Data; } break; @@ -119,8 +117,8 @@ namespace OpenRA.Server try { c.socket.Blocking = true; + c.socket.Send(BitConverter.GetBytes(data.Length + 4)); c.socket.Send(BitConverter.GetBytes(frame)); - c.socket.Send(BitConverter.GetBytes(data.Length)); c.socket.Send(data); c.socket.Blocking = false; } diff --git a/OpenRa.Game/OrderManager.cs b/OpenRa.Game/OrderManager.cs index 17615350f0..3bbe107dd2 100755 --- a/OpenRa.Game/OrderManager.cs +++ b/OpenRa.Game/OrderManager.cs @@ -108,12 +108,11 @@ namespace OpenRa.Game { try { - uint fn; + var len = replayReader.ReadInt32() - 4; + var frame = replayReader.ReadInt32(); + var ret = replayReader.ReadBytes( len ).ToOrderList(); - var len = replayReader.ReadInt32(); - var ret = replayReader.ReadBytes( len ).ToOrderList( out fn ); - - if( frameNumber != fn ) + if( frameNumber != frame ) throw new InvalidOperationException( "Attempted time-travel in OrdersForFrame (replay)" ); return ret; @@ -135,7 +134,7 @@ namespace OpenRa.Game int nextLocalOrderFrame = 1; TcpClient socket; - Dictionary orderBuffers = new Dictionary(); + Dictionary> orderBuffers = new Dictionary>(); public NetworkOrderSource( TcpClient socket ) { @@ -143,43 +142,42 @@ namespace OpenRa.Game this.socket.NoDelay = true; var reader = new BinaryReader( socket.GetStream() ); - var nextFrameId = BitConverter.GetBytes( nextLocalOrderFrame ); - socket.GetStream().Write( nextFrameId, 0, nextFrameId.Length ); - new Thread( () => { - var firstFrameNum = reader.ReadInt32(); - if( firstFrameNum != 0 ) - throw new InvalidOperationException( "Wrong frame number at start of stream" ); - - var currentFrame = 0; - var ret = new List(); - while( true ) + for (; ; ) { var len = reader.ReadInt32(); - var buf = reader.ReadBytes( len ); + var frame = reader.ReadInt32(); + var buf = reader.ReadBytes(len - 4); - lock( orderBuffers ) - orderBuffers[ currentFrame ] = buf; - ++currentFrame; + lock (orderBuffers) + { + /* accumulate this chunk */ + if (orderBuffers[frame] == null) + orderBuffers[frame] = new List(); + orderBuffers[frame].Add(buf); + } } } ) { IsBackground = true }.Start(); } + static List NoOrders = new List(); + List ExtractOrders(int frame) + { + lock (orderBuffers) + { + List result; + return orderBuffers.TryGetValue(frame, out result) + ? result : NoOrders; + } + } + public List OrdersForFrame( int currentFrame ) { - // TODO: prune `orderBuffers` based on currentFrame. - byte[] orderBuffer; - lock( orderBuffers ) - orderBuffer = orderBuffers[ currentFrame ]; + var orderData = ExtractOrders(currentFrame); + /* todo: immediate orders hooked in here? */ - uint frameNumber; - var ret = orderBuffer.ToOrderList( out frameNumber ); - - if( frameNumber != currentFrame ) - throw new InvalidOperationException( "Attempted time-travel in OrdersForFrame (network)" ); - - return ret; + return orderData.SelectMany(a => a.ToOrderList()).ToList(); } public void SendLocalOrders( int localFrame, List localOrders ) @@ -223,11 +221,10 @@ namespace OpenRa.Game ms.WriteTo( s ); } - public static List ToOrderList( this byte[] bytes, out uint frameNumber ) + public static List ToOrderList( this byte[] bytes ) { var ms = new MemoryStream( bytes ); var reader = new BinaryReader( ms ); - frameNumber = reader.ReadUInt32(); var ret = new List(); while( ms.Position < ms.Length ) ret.Add( Order.Deserialize( reader ) );