First frame is No. 1, not 0. Order no longer needs to use that bit to signify playerness.

This commit is contained in:
Bob
2009-11-30 23:11:19 +13:00
parent 2913c3310d
commit 1b8208892d
2 changed files with 64 additions and 61 deletions

View File

@@ -31,7 +31,6 @@ namespace OpenRa.Game
switch (OrderString) switch (OrderString)
{ {
// Format: // Format:
// u32 : player, with msb set. (if msb is clear, not an order)
// u8 : orderID. // u8 : orderID.
// 0xFF: Full serialized order. // 0xFF: Full serialized order.
// varies: rest of order. // varies: rest of order.
@@ -40,8 +39,8 @@ namespace OpenRa.Game
{ {
var ret = new MemoryStream(); var ret = new MemoryStream();
var w = new BinaryWriter(ret); var w = new BinaryWriter(ret);
w.Write((uint)Player.Index | 0x80000000u);
w.Write( (byte)0xFF ); w.Write( (byte)0xFF );
w.Write( (uint)Player.Index );
w.Write(OrderString); w.Write(OrderString);
w.Write(Subject == null ? 0xFFFFFFFF : Subject.ActorID); w.Write(Subject == null ? 0xFFFFFFFF : Subject.ActorID);
w.Write(TargetActor == null ? 0xFFFFFFFF : TargetActor.ActorID); w.Write(TargetActor == null ? 0xFFFFFFFF : TargetActor.ActorID);
@@ -55,15 +54,13 @@ namespace OpenRa.Game
} }
} }
public static Order Deserialize(BinaryReader r, uint first) public static Order Deserialize(BinaryReader r)
{ {
if ((first >> 31) == 0) return null;
var player = Game.players.Where(x => x.Value.Index == (first & 0x7FFFFFFF)).First().Value;
switch (r.ReadByte()) switch (r.ReadByte())
{ {
case 0xFF: case 0xFF:
{ {
var playerID = r.ReadUInt32();
var order = r.ReadString(); var order = r.ReadString();
var subject = ActorFromUInt(r.ReadUInt32()); var subject = ActorFromUInt(r.ReadUInt32());
var targetActor = ActorFromUInt(r.ReadUInt32()); var targetActor = ActorFromUInt(r.ReadUInt32());
@@ -72,6 +69,8 @@ namespace OpenRa.Game
var targetString = null as string; var targetString = null as string;
if (r.ReadBoolean()) if (r.ReadBoolean())
targetString = r.ReadString(); targetString = r.ReadString();
var player = Game.players.Where( x => x.Value.Index == playerID ).First().Value;
return new Order( player, order, subject, targetActor, targetLocation, targetString ); return new Order( player, order, subject, targetActor, targetLocation, targetString );
} }
default: default:

View File

@@ -9,9 +9,9 @@ namespace OpenRa.Game
{ {
class OrderManager class OrderManager
{ {
BinaryWriter savingReplay; Stream savingReplay;
List<OrderSource> players; List<OrderSource> players;
int frameNumber = 0; int frameNumber = 1;
const int FramesAhead = 3; const int FramesAhead = 3;
@@ -22,14 +22,14 @@ namespace OpenRa.Game
this.players = players.ToList(); this.players = players.ToList();
foreach( var p in this.players ) foreach( var p in this.players )
for( int i = 0 ; i < FramesAhead ; i++ ) for( int i = 1 ; i <= FramesAhead ; i++ )
p.SendLocalOrders( i, new List<Order>() ); p.SendLocalOrders( i, new List<Order>() );
} }
public OrderManager( IEnumerable<OrderSource> players, string replayFilename ) public OrderManager( IEnumerable<OrderSource> players, string replayFilename )
: this( players ) : this( players )
{ {
savingReplay = new BinaryWriter( new FileStream( replayFilename, FileMode.Create ) ); savingReplay = new FileStream( replayFilename, FileMode.Create );
} }
public bool IsReadyForNextFrame public bool IsReadyForNextFrame
@@ -50,16 +50,12 @@ namespace OpenRa.Game
foreach( var p in players ) foreach( var p in players )
p.SendLocalOrders( frameNumber + FramesAhead, localOrders ); p.SendLocalOrders( frameNumber + FramesAhead, localOrders );
if( savingReplay != null ) var allOrders = players.SelectMany(p => p.OrdersForFrame(frameNumber)).OrderBy(o => o.Player.Index).ToList();
savingReplay.Write( frameNumber );
var allOrders = players.SelectMany(p => p.OrdersForFrame(frameNumber)).OrderBy(o => o.Player.Index);
foreach (var order in allOrders) foreach (var order in allOrders)
{
UnitOrders.ProcessOrder(order); UnitOrders.ProcessOrder(order);
if( savingReplay != null ) if( savingReplay != null )
savingReplay.Write(order.Serialize()); savingReplay.WriteFrameData( allOrders, frameNumber );
}
++frameNumber; ++frameNumber;
// sanity check on the framenumber. This is 2^31 frames maximum, or multiple *years* at 40ms/frame. // sanity check on the framenumber. This is 2^31 frames maximum, or multiple *years* at 40ms/frame.
@@ -104,32 +100,27 @@ namespace OpenRa.Game
public ReplayOrderSource( string replayFilename ) public ReplayOrderSource( string replayFilename )
{ {
replayReader = new BinaryReader( File.Open( replayFilename, FileMode.Open ) ); replayReader = new BinaryReader( File.Open( replayFilename, FileMode.Open ) );
replayReader.ReadUInt32();
} }
public void SendLocalOrders( int localFrame, List<Order> localOrders ) { } public void SendLocalOrders( int localFrame, List<Order> localOrders ) { }
public List<Order> OrdersForFrame( int frameNumber ) public List<Order> OrdersForFrame( int frameNumber )
{
var ret = new List<Order>();
while( true )
{ {
try try
{ {
var first = replayReader.ReadUInt32(); uint fn;
var order = Order.Deserialize( replayReader, first );
if( order == null ) var len = replayReader.ReadInt32();
{ var ret = replayReader.ReadBytes( len ).ToOrderList( out fn );
if( (uint)frameNumber + 1 != first )
throw new NotImplementedException(); if( frameNumber != fn )
throw new InvalidOperationException( "Attempted time-travel in OrdersForFrame (replay)" );
return ret; return ret;
} }
ret.Add( order );
}
catch( EndOfStreamException ) catch( EndOfStreamException )
{ {
return ret; return new List<Order>();
}
} }
} }
@@ -141,7 +132,7 @@ namespace OpenRa.Game
class NetworkOrderSource : OrderSource class NetworkOrderSource : OrderSource
{ {
int nextLocalOrderFrame = 0; int nextLocalOrderFrame = 1;
TcpClient socket; TcpClient socket;
Dictionary<int, byte[]> orderBuffers = new Dictionary<int, byte[]>(); Dictionary<int, byte[]> orderBuffers = new Dictionary<int, byte[]>();
@@ -182,19 +173,12 @@ namespace OpenRa.Game
lock( orderBuffers ) lock( orderBuffers )
orderBuffer = orderBuffers[ currentFrame ]; orderBuffer = orderBuffers[ currentFrame ];
var ms = new MemoryStream( orderBuffer ); uint frameNumber;
var reader = new BinaryReader( ms ); var ret = orderBuffer.ToOrderList( out frameNumber );
var ret = new List<Order>();
if( reader.ReadUInt32() != currentFrame ) if( frameNumber != currentFrame )
throw new InvalidOperationException( "Attempted time-travel in OrdersForFrame (network)" ); throw new InvalidOperationException( "Attempted time-travel in OrdersForFrame (network)" );
while( ms.Position < ms.Length )
{
var first = reader.ReadUInt32();
ret.Add( Order.Deserialize( reader, first ) );
}
return ret; return ret;
} }
@@ -203,17 +187,7 @@ namespace OpenRa.Game
if( nextLocalOrderFrame != localFrame ) if( nextLocalOrderFrame != localFrame )
throw new InvalidOperationException( "Attempted time-travel in NetworkOrderSource.SendLocalOrders()" ); throw new InvalidOperationException( "Attempted time-travel in NetworkOrderSource.SendLocalOrders()" );
var ms = new MemoryStream(); socket.GetStream().WriteFrameData( localOrders, nextLocalOrderFrame++ );
ms.Write( BitConverter.GetBytes( nextLocalOrderFrame ) );
foreach( var order in localOrders )
ms.Write( order.Serialize() );
++nextLocalOrderFrame;
socket.GetStream().Write( BitConverter.GetBytes( (int)ms.Length ) );
ms.WriteTo( socket.GetStream() );
} }
public bool IsReadyForFrame( int frameNumber ) public bool IsReadyForFrame( int frameNumber )
@@ -230,4 +204,34 @@ namespace OpenRa.Game
s.Write( buf, 0, buf.Length ); s.Write( buf, 0, buf.Length );
} }
} }
static class OrderIO
{
public static MemoryStream ToMemoryStream( this List<Order> orders, int nextLocalOrderFrame )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( nextLocalOrderFrame ) );
foreach( var order in orders )
ms.Write( order.Serialize() );
return ms;
}
public static void WriteFrameData( this Stream s, List<Order> orders, int frameNumber )
{
var ms = orders.ToMemoryStream( frameNumber );
s.Write( BitConverter.GetBytes( (int)ms.Length ) );
ms.WriteTo( s );
}
public static List<Order> ToOrderList( this byte[] bytes, out uint frameNumber )
{
var ms = new MemoryStream( bytes );
var reader = new BinaryReader( ms );
frameNumber = reader.ReadUInt32();
var ret = new List<Order>();
while( ms.Position < ms.Length )
ret.Add( Order.Deserialize( reader ) );
return ret;
}
}
} }