diff --git a/OpenRA.Server/Server.cs b/OpenRA.Server/Server.cs index ee8757171c..df2665c07f 100644 --- a/OpenRA.Server/Server.cs +++ b/OpenRA.Server/Server.cs @@ -5,8 +5,9 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; -using OpenRa.FileFormats; using System.Security.Cryptography; +using OpenRa; +using OpenRa.FileFormats; namespace OpenRA.Server { diff --git a/OpenRa.FileFormats/Exts.cs b/OpenRa.FileFormats/Exts.cs index a2781f0318..34a5cb27c3 100644 --- a/OpenRa.FileFormats/Exts.cs +++ b/OpenRa.FileFormats/Exts.cs @@ -1,5 +1,5 @@  -namespace OpenRa.FileFormats +namespace OpenRa { public static class Exts { diff --git a/OpenRa.Game/Network/OrderIO.cs b/OpenRa.Game/Network/OrderIO.cs index 2e12b09be4..46155d5d56 100755 --- a/OpenRa.Game/Network/OrderIO.cs +++ b/OpenRa.Game/Network/OrderIO.cs @@ -41,5 +41,18 @@ namespace OpenRa.Network } return ret; } + + public static byte[] SerializeSync( this List sync, int frameNumber ) + { + var ms = new MemoryStream(); + using( var writer = new BinaryWriter( ms ) ) + { + writer.Write( frameNumber ); + writer.Write( (byte)0x65 ); + foreach( var s in sync ) + writer.Write( s ); + } + return ms.ToArray(); + } } } diff --git a/OpenRa.Game/Network/OrderManager.cs b/OpenRa.Game/Network/OrderManager.cs index 4414a65f5e..5ec36c4081 100755 --- a/OpenRa.Game/Network/OrderManager.cs +++ b/OpenRa.Game/Network/OrderManager.cs @@ -67,6 +67,8 @@ namespace OpenRa.Network var frame = BitConverter.ToInt32( packet, 0 ); if( packet.Length == 5 && packet[ 4 ] == 0xEF ) readyForFrames.Add( frame ); + else if( packet.Length >= 5 && packet[ 4 ] == 0x65 ) + CheckSync( packet ); else if( frame == 0 ) immediatePackets.Add( packet ); else @@ -78,6 +80,30 @@ namespace OpenRa.Network UnitOrders.ProcessOrder( o ); } + Dictionary syncForFrame = new Dictionary(); + + void CheckSync( byte[] packet ) + { + var frame = BitConverter.ToInt32( packet, 0 ); + byte[] existingSync; + if( syncForFrame.TryGetValue( frame, out existingSync ) ) + { + if( packet.Length != existingSync.Length ) + OutOfSync( frame ); + else + for( int i = 0 ; i < packet.Length ; i++ ) + if( packet[ i ] != existingSync[ i ] ) + OutOfSync( frame ); + } + else + syncForFrame.Add( frame, packet ); + } + + void OutOfSync( int frame ) + { + throw new InvalidOperationException( "out of sync in frame {0}".F( frame ) ); + } + public bool IsReadyForNextFrame { get { return readyForFrames.Contains( FrameNumber ); } @@ -93,8 +119,18 @@ namespace OpenRa.Network localOrders.Clear(); var frameData = frameClientData[ FrameNumber ]; + var sync = new List(); + sync.Add( world.SyncHash() ); + foreach( var order in frameData.OrderBy( p => p.Key ).SelectMany( o => o.Value.ToOrderList( world ) ) ) + { UnitOrders.ProcessOrder( order ); + sync.Add( world.SyncHash() ); + } + + var ss = sync.SerializeSync( FrameNumber ); + CheckSync( ss ); + Connection.Send( ss ); ++frameNumber; }