diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index d4e42c86c3..40a938e090 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -40,6 +40,9 @@ namespace OpenRa.Game public static string Replay; + public static string NetworkHost; + public static int NetworkPort; + public static bool skipMakeAnims = true; public static void Initialize(string mapName, Renderer renderer, int2 clientSize, int localPlayer) @@ -79,9 +82,15 @@ namespace OpenRa.Game soundEngine = new ISoundEngine(); sounds = new Cache(LoadSound); - orderManager = (Replay == "") - ? new OrderManager(new OrderSource[] { new LocalOrderSource(), new NetworkOrderSource( new TcpClient( "127.0.0.1", 1234 ) ) }, "replay.rep") - : new OrderManager(new OrderSource[] { new ReplayOrderSource( Replay ) }); + if( Replay != "" ) + orderManager = new OrderManager( new OrderSource[] { new ReplayOrderSource( Replay ) } ); + else + { + var orderSources = ( string.IsNullOrEmpty( NetworkHost ) ) + ? new OrderSource[] { new LocalOrderSource() } + : new OrderSource[] { new LocalOrderSource(), new NetworkOrderSource( new TcpClient( NetworkHost, NetworkPort ) ) }; + orderManager = new OrderManager(orderSources, "replay.rep" ); + } PlaySound("intro.aud", false); @@ -155,8 +164,9 @@ namespace OpenRa.Game { lastTime += timestep; - if (orderManager.Tick()) + if( orderManager.IsReadyForNextFrame ) { + orderManager.Tick(); if (controller.orderGenerator != null) controller.orderGenerator.Tick(); @@ -172,6 +182,8 @@ namespace OpenRa.Game foreach (var player in players.Values) player.Tick(); } + else if( orderManager.FrameNumber == 0 ) + lastTime = Environment.TickCount; } PerfHistory.Tick(); diff --git a/OpenRa.Game/MainWindow.cs b/OpenRa.Game/MainWindow.cs index 92b4f4067f..dff4bfe9f7 100755 --- a/OpenRa.Game/MainWindow.cs +++ b/OpenRa.Game/MainWindow.cs @@ -52,6 +52,8 @@ namespace OpenRa.Game WorldRenderer.ShowUnitPaths = settings.GetValue("pathdebug", false); Game.timestep = settings.GetValue("rate", 40); Game.Replay = settings.GetValue("replay", ""); + Game.NetworkHost = settings.GetValue( "host", "" ); + Game.NetworkPort = int.Parse( settings.GetValue( "port", "0" ) ); Game.Initialize(settings.GetValue("map", "scm12ea.ini"), renderer, new int2(ClientSize), settings.GetValue("player", 1)); diff --git a/OpenRa.Game/OrderManager.cs b/OpenRa.Game/OrderManager.cs index c1480cb84f..4eb13b9fda 100755 --- a/OpenRa.Game/OrderManager.cs +++ b/OpenRa.Game/OrderManager.cs @@ -6,6 +6,7 @@ using System.IO; using System.Net; using IjwFramework.Types; using System.Net.Sockets; +using System.Threading; namespace OpenRa.Game { @@ -34,11 +35,20 @@ namespace OpenRa.Game savingReplay = new BinaryWriter( new FileStream( replayFilename, FileMode.Create ) ); } - public bool Tick() + public bool IsReadyForNextFrame + { + get + { + foreach( var p in players ) + if( !p.IsReadyForFrame( frameNumber ) ) + return false; + return true; + } + } + + public void Tick() { var localOrders = Game.controller.GetRecentOrders(); - if( localOrders == null ) - return false; foreach( var p in players ) p.SendLocalOrders( frameNumber + FramesAhead, localOrders ); @@ -59,7 +69,7 @@ namespace OpenRa.Game if( ( frameNumber & 0x80000000 ) != 0 ) throw new InvalidOperationException( "(OrderManager) Frame number too large" ); - return true; + return; } } @@ -67,6 +77,7 @@ namespace OpenRa.Game { void SendLocalOrders( int localFrame, List localOrders ); List OrdersForFrame( int currentFrame ); + bool IsReadyForFrame( int frameNumber ); } class LocalOrderSource : OrderSource @@ -83,6 +94,11 @@ namespace OpenRa.Game { orders[ localFrame ] = localOrders; } + + public bool IsReadyForFrame( int frameNumber ) + { + return true; + } } class ReplayOrderSource : OrderSource @@ -120,40 +136,59 @@ namespace OpenRa.Game } } + public bool IsReadyForFrame( int frameNumber ) + { + return true; + } } class NetworkOrderSource : OrderSource { int nextLocalOrderFrame = 0; TcpClient socket; - BinaryReader reader; + + Dictionary> orders = new Dictionary>(); public NetworkOrderSource( TcpClient socket ) { this.socket = socket; - reader = new BinaryReader( socket.GetStream() ); + var reader = new BinaryReader( socket.GetStream() ); var nextFrameId = System.BitConverter.GetBytes( nextLocalOrderFrame ); socket.GetStream().Write( nextFrameId, 0, nextFrameId.Length ); - } - public List OrdersForFrame( int currentFrame ) - { - if( currentFrame == 0 ) + new Thread( () => { var firstFrameNum = reader.ReadInt32(); if( firstFrameNum != 0 ) throw new InvalidOperationException( "Wrong frame number at start of stream" ); - } - var ret = new List(); - while( true ) - { + var currentFrame = 0; var first = reader.ReadUInt32(); - if( first == currentFrame + 1 ) - return ret; - ret.Add( Order.Deserialize( reader, first ) ); - } + while( true ) + { + var ret = new List(); + while( true ) + { + if( first == currentFrame + 1 ) + { + lock( orders ) + orders[ currentFrame ] = ret; + ret = new List(); + ++currentFrame; + break; + } + ret.Add( Order.Deserialize( reader, first ) ); + } + } + } ).Start(); + } + + public List OrdersForFrame( int currentFrame ) + { + // TODO: prune `orders` based on currentFrame. + lock( orders ) + return orders[ currentFrame ]; } public void SendLocalOrders( int localFrame, List localOrders ) @@ -171,5 +206,11 @@ namespace OpenRa.Game var nextFrameId = System.BitConverter.GetBytes( nextLocalOrderFrame ); socket.GetStream().Write( nextFrameId, 0, nextFrameId.Length ); } + + public bool IsReadyForFrame( int frameNumber ) + { + lock( orders ) + return orders.ContainsKey( frameNumber ); + } } }