some Network changes.
This commit is contained in:
@@ -76,7 +76,7 @@ namespace OpenRA.Server
|
||||
|
||||
// assign the player number.
|
||||
newConn.PlayerIndex = ChooseFreePlayerIndex();
|
||||
|
||||
newConn.socket.Send( BitConverter.GetBytes( newConn.PlayerIndex ) );
|
||||
conns.Add(newConn);
|
||||
|
||||
lobbyInfo.Clients.Add(
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace OpenRa
|
||||
{
|
||||
if (isChatting && typing.Length > 0)
|
||||
{
|
||||
Game.controller.AddOrder(Order.Chat(Game.world.LocalPlayer, typing));
|
||||
Game.orderManager.IssueOrder(Order.Chat(Game.world.LocalPlayer, typing));
|
||||
AddLine(Game.world.LocalPlayer, typing);
|
||||
}
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ namespace OpenRa
|
||||
{
|
||||
var queue = world.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
||||
foreach( var item in queue.AllItems( groupName ) )
|
||||
Game.controller.AddOrder(Order.CancelProduction(world.LocalPlayer, item.Item));
|
||||
Game.orderManager.IssueOrder(Order.CancelProduction(world.LocalPlayer, item.Item));
|
||||
}
|
||||
|
||||
void ChooseAvailableTab( World world )
|
||||
@@ -760,7 +760,7 @@ namespace OpenRa
|
||||
{
|
||||
var unit = Rules.Info[item];
|
||||
Sound.Play(unit.Traits.Contains<BuildingInfo>() ? "abldgin1.aud" : "train1.aud");
|
||||
Game.controller.AddOrder(Order.StartProduction(world.LocalPlayer, item));
|
||||
Game.orderManager.IssueOrder(Order.StartProduction(world.LocalPlayer, item));
|
||||
}
|
||||
|
||||
void HandleBuildPalette( World world, string item, bool isLmb )
|
||||
@@ -785,7 +785,7 @@ namespace OpenRa
|
||||
|
||||
if (producing.Paused)
|
||||
{
|
||||
Game.controller.AddOrder(Order.PauseProduction(player, item, false));
|
||||
Game.orderManager.IssueOrder(Order.PauseProduction(player, item, false));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -800,12 +800,12 @@ namespace OpenRa
|
||||
if (producing.Paused || producing.Done || producing.TotalCost == producing.RemainingCost)
|
||||
{
|
||||
Sound.Play("cancld1.aud");
|
||||
Game.controller.AddOrder(Order.CancelProduction(player, item));
|
||||
Game.orderManager.IssueOrder(Order.CancelProduction(player, item));
|
||||
}
|
||||
else
|
||||
{
|
||||
Sound.Play("onhold1.aud");
|
||||
Game.controller.AddOrder(Order.PauseProduction(player, item, true));
|
||||
Game.orderManager.IssueOrder(Order.PauseProduction(player, item, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,14 +41,12 @@ namespace OpenRa
|
||||
}
|
||||
}
|
||||
|
||||
List<Order> recentOrders = new List<Order>();
|
||||
|
||||
void ApplyOrders(World world, float2 xy, MouseInput mi)
|
||||
{
|
||||
if (orderGenerator == null) return;
|
||||
|
||||
var orders = orderGenerator.Order(world, xy.ToInt2(), mi).ToArray();
|
||||
recentOrders.AddRange( orders );
|
||||
Game.orderManager.IssueOrders( orders );
|
||||
|
||||
var voicedActor = orders.Select(o => o.Subject)
|
||||
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.traits.Contains<Unit>());
|
||||
@@ -65,16 +63,6 @@ namespace OpenRa
|
||||
}
|
||||
}
|
||||
|
||||
public void AddOrder(Order o) { recentOrders.Add(o); }
|
||||
|
||||
public List<Order> GetRecentOrders( bool imm )
|
||||
{
|
||||
Func<Order, bool> p = o => o.IsImmediate ^ !imm;
|
||||
var result = recentOrders.Where(p).ToList();
|
||||
recentOrders.RemoveAll(o => p(o)); // ffs.
|
||||
return result;
|
||||
}
|
||||
|
||||
float2 dragStart, dragEnd;
|
||||
public bool HandleInput(World world, MouseInput mi)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRa.GameRules;
|
||||
using OpenRa.Traits;
|
||||
@@ -51,5 +52,19 @@ namespace OpenRa
|
||||
if (oai == null) return 0;
|
||||
return oai.HP;
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
||||
where V : new()
|
||||
{
|
||||
return d.GetOrAdd( k, _ => new V() );
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
|
||||
{
|
||||
V ret;
|
||||
if( !d.TryGetValue( k, out ret ) )
|
||||
d.Add( k, ret = createFn( k ) );
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using IjwFramework.Types;
|
||||
using OpenRa.FileFormats;
|
||||
using OpenRa.GameRules;
|
||||
using OpenRa.Graphics;
|
||||
using OpenRa.Network;
|
||||
using OpenRa.Orders;
|
||||
using OpenRa.Support;
|
||||
using OpenRa.Traits;
|
||||
using System.Windows.Forms;
|
||||
using Timer = OpenRa.Support.Timer;
|
||||
|
||||
namespace OpenRa
|
||||
@@ -101,13 +102,14 @@ namespace OpenRa
|
||||
ChangeMap(mapName);
|
||||
|
||||
if (Settings.Replay != "")
|
||||
orderManager = new OrderManager(new IOrderSource[] { new ReplayOrderSource(Settings.Replay) });
|
||||
//orderManager = new OrderManager(new IOrderSource[] { new ReplayOrderSource(Settings.Replay) });
|
||||
throw new NotImplementedException();
|
||||
else
|
||||
{
|
||||
var orderSources = (string.IsNullOrEmpty(Settings.NetworkHost))
|
||||
? new IOrderSource[] { new LocalOrderSource() }
|
||||
: new IOrderSource[] { new LocalOrderSource(), new NetworkOrderSource(Settings.NetworkHost, Settings.NetworkPort) };
|
||||
orderManager = new OrderManager(orderSources, "replay.rep");
|
||||
var connection = (string.IsNullOrEmpty(Settings.NetworkHost))
|
||||
? new EchoConnection()
|
||||
: new NetworkConnection( Settings.NetworkHost, Settings.NetworkPort );
|
||||
orderManager = new OrderManager(connection, "replay.rep");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +273,7 @@ namespace OpenRa
|
||||
/* hack hack hack */
|
||||
if( e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted )
|
||||
{
|
||||
Game.controller.AddOrder(
|
||||
Game.orderManager.IssueOrder(
|
||||
new Order( "ToggleReady", Game.world.LocalPlayer.PlayerActor, null, int2.Zero, "" ) { IsImmediate = true } );
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using OpenRa.FileFormats;
|
||||
using OpenRa.Orders;
|
||||
using OpenRa.Traits;
|
||||
using OpenRa.Network;
|
||||
|
||||
namespace OpenRa.Graphics
|
||||
{
|
||||
@@ -57,32 +58,25 @@ namespace OpenRa.Graphics
|
||||
world.WorldRenderer.Draw();
|
||||
Game.chrome.Draw( world );
|
||||
|
||||
if (Game.orderManager.IsNetplay &&
|
||||
Game.orderManager.Sources.OfType<NetworkOrderSource>().First().State == ConnectionState.NotConnected)
|
||||
if( Game.orderManager.Connection.ConnectionState == ConnectionState.NotConnected )
|
||||
Game.chrome.DrawDialog("Connection lost.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// what a hack. as soon as we have some real chrome stuff...
|
||||
|
||||
if (Game.orderManager.IsNetplay)
|
||||
switch( Game.orderManager.Connection.ConnectionState )
|
||||
{
|
||||
var nos = Game.orderManager.Sources.OfType<NetworkOrderSource>().First();
|
||||
switch (nos.State)
|
||||
{
|
||||
case ConnectionState.Connecting:
|
||||
Game.chrome.DrawDialog("Connecting to {0}:{1}...".F( Game.Settings.NetworkHost, Game.Settings.NetworkPort ));
|
||||
break;
|
||||
case ConnectionState.NotConnected:
|
||||
Game.chrome.DrawDialog("Connection failed.");
|
||||
break;
|
||||
case ConnectionState.Connected:
|
||||
Game.chrome.DrawLobby( world );
|
||||
break;
|
||||
}
|
||||
case ConnectionState.Connecting:
|
||||
Game.chrome.DrawDialog("Connecting to {0}:{1}...".F( Game.Settings.NetworkHost, Game.Settings.NetworkPort ));
|
||||
break;
|
||||
case ConnectionState.NotConnected:
|
||||
Game.chrome.DrawDialog("Connection failed.");
|
||||
break;
|
||||
case ConnectionState.Connected:
|
||||
Game.chrome.DrawLobby( world );
|
||||
break;
|
||||
}
|
||||
else
|
||||
Game.chrome.DrawLobby( world );
|
||||
}
|
||||
|
||||
var c = Game.chrome.HitTest(mousePos) ? Cursor.Default : Game.controller.ChooseCursor( world );
|
||||
|
||||
111
OpenRa.Game/Network/Connection.cs
Executable file
111
OpenRa.Game/Network/Connection.cs
Executable file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRa.Network
|
||||
{
|
||||
enum ConnectionState
|
||||
{
|
||||
NotConnected,
|
||||
Connecting,
|
||||
Connected,
|
||||
}
|
||||
|
||||
interface IConnection
|
||||
{
|
||||
int LocalClientId { get; }
|
||||
ConnectionState ConnectionState { get; }
|
||||
void Send( byte[] packet );
|
||||
void Receive( Action<int, byte[]> packetFn );
|
||||
}
|
||||
|
||||
class EchoConnection : IConnection
|
||||
{
|
||||
protected struct ReceivedPacket
|
||||
{
|
||||
public int FromClient;
|
||||
public byte[] Data;
|
||||
}
|
||||
protected List<ReceivedPacket> receivedPackets = new List<ReceivedPacket>();
|
||||
|
||||
public virtual int LocalClientId
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public virtual ConnectionState ConnectionState
|
||||
{
|
||||
get { return ConnectionState.Connected; }
|
||||
}
|
||||
|
||||
public virtual void Send( byte[] packet )
|
||||
{
|
||||
lock( this )
|
||||
receivedPackets.Add( new ReceivedPacket { FromClient = LocalClientId, Data = packet } );
|
||||
}
|
||||
|
||||
public virtual void Receive( Action<int, byte[]> packetFn )
|
||||
{
|
||||
List<ReceivedPacket> packets;
|
||||
lock( this )
|
||||
{
|
||||
packets = receivedPackets;
|
||||
receivedPackets = new List<ReceivedPacket>();
|
||||
}
|
||||
|
||||
foreach( var p in packets )
|
||||
packetFn( p.FromClient, p.Data );
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkConnection : EchoConnection
|
||||
{
|
||||
TcpClient socket;
|
||||
int clientId;
|
||||
ConnectionState connectionState = ConnectionState.Connecting;
|
||||
|
||||
public NetworkConnection( string host, int port )
|
||||
{
|
||||
new Thread( _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
socket = new TcpClient( host, port );
|
||||
var reader = new BinaryReader( socket.GetStream() );
|
||||
clientId = reader.ReadInt32();
|
||||
connectionState = ConnectionState.Connected;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
var len = reader.ReadInt32();
|
||||
var buf = reader.ReadBytes( len );
|
||||
lock( this )
|
||||
receivedPackets.Add( new ReceivedPacket { FromClient = -1, Data = buf } );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
connectionState = ConnectionState.NotConnected;
|
||||
}
|
||||
}
|
||||
) { IsBackground = true }.Start();
|
||||
}
|
||||
|
||||
public override int LocalClientId { get { return clientId; } }
|
||||
public override ConnectionState ConnectionState { get { return connectionState; } }
|
||||
|
||||
public override void Send( byte[] packet )
|
||||
{
|
||||
base.Send( packet );
|
||||
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( (int)packet.Length ) );
|
||||
ms.Write( packet );
|
||||
ms.WriteTo( socket.GetStream() );
|
||||
}
|
||||
}
|
||||
}
|
||||
0
OpenRa.Game/Orders/Order.cs → OpenRa.Game/Network/Order.cs
Normal file → Executable file
0
OpenRa.Game/Orders/Order.cs → OpenRa.Game/Network/Order.cs
Normal file → Executable file
24
OpenRa.Game/Orders/OrderIO.cs → OpenRa.Game/Network/OrderIO.cs
Normal file → Executable file
24
OpenRa.Game/Orders/OrderIO.cs → OpenRa.Game/Network/OrderIO.cs
Normal file → Executable file
@@ -1,30 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
namespace OpenRa.Network
|
||||
{
|
||||
static class OrderIO
|
||||
{
|
||||
static void Write(this Stream s, byte[] buf)
|
||||
public static void Write(this Stream s, byte[] buf)
|
||||
{
|
||||
s.Write(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
public static void WriteFrameData(this Stream s, IEnumerable<Order> orders, int frameNumber)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write(BitConverter.GetBytes(frameNumber));
|
||||
foreach (var order in orders)
|
||||
ms.Write(order.Serialize());
|
||||
var bytes = Serialize( orders, frameNumber );
|
||||
s.Write( BitConverter.GetBytes( (int)bytes.Length ) );
|
||||
s.Write( bytes );
|
||||
}
|
||||
|
||||
s.Write(BitConverter.GetBytes((int)ms.Length));
|
||||
ms.WriteTo(s);
|
||||
public static byte[] Serialize( this IEnumerable<Order> orders, int frameNumber )
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Write( BitConverter.GetBytes( frameNumber ) );
|
||||
foreach( var o in orders.Select( o => o.Serialize() ) )
|
||||
ms.Write( o );
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public static List<Order> ToOrderList(this byte[] bytes, World world)
|
||||
{
|
||||
var ms = new MemoryStream(bytes);
|
||||
var ms = new MemoryStream(bytes, 4, bytes.Length - 4);
|
||||
var reader = new BinaryReader(ms);
|
||||
var ret = new List<Order>();
|
||||
while( ms.Position < ms.Length )
|
||||
102
OpenRa.Game/Network/OrderManager.cs
Executable file
102
OpenRa.Game/Network/OrderManager.cs
Executable file
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRa.Network
|
||||
{
|
||||
class OrderManager
|
||||
{
|
||||
Stream savingReplay;
|
||||
int frameNumber = 0;
|
||||
|
||||
public int FramesAhead = 0;
|
||||
|
||||
public bool GameStarted { get { return frameNumber != 0; } }
|
||||
public IConnection Connection { get; private set; }
|
||||
|
||||
Dictionary<int, Dictionary<int, byte[]>> frameClientData = new Dictionary<int, Dictionary<int, byte[]>>();
|
||||
List<int> readyForFrames = new List<int>();
|
||||
List<Order> localOrders = new List<Order>();
|
||||
|
||||
public void StartGame()
|
||||
{
|
||||
if (GameStarted) return;
|
||||
|
||||
frameNumber = 1;
|
||||
for( int i = frameNumber ; i <= FramesAhead ; i++ )
|
||||
Connection.Send( new List<Order>().Serialize( i ) );
|
||||
}
|
||||
|
||||
public int FrameNumber { get { return frameNumber; } }
|
||||
|
||||
public OrderManager( IConnection conn )
|
||||
{
|
||||
Connection = conn;
|
||||
}
|
||||
|
||||
public OrderManager( IConnection conn, string replayFilename )
|
||||
: this( conn )
|
||||
{
|
||||
savingReplay = new FileStream( replayFilename, FileMode.Create );
|
||||
}
|
||||
|
||||
public void IssueOrders( Order[] orders )
|
||||
{
|
||||
foreach( var order in orders )
|
||||
IssueOrder( order );
|
||||
}
|
||||
|
||||
public void IssueOrder( Order order )
|
||||
{
|
||||
localOrders.Add( order );
|
||||
}
|
||||
|
||||
public void TickImmediate( World world )
|
||||
{
|
||||
var immediateOrders = localOrders.Where( o => o.IsImmediate ).ToList();
|
||||
if( immediateOrders.Count != 0 )
|
||||
Connection.Send( immediateOrders.Serialize( 0 ) );
|
||||
localOrders.RemoveAll( o => o.IsImmediate );
|
||||
|
||||
var immediatePackets = new List<byte[]>();
|
||||
|
||||
Connection.Receive(
|
||||
( clientId, packet ) =>
|
||||
{
|
||||
var frame = BitConverter.ToInt32( packet, 0 );
|
||||
if( packet.Length == 5 && packet[ 4 ] == 0xEF )
|
||||
readyForFrames.Add( frame );
|
||||
else if( frame == 0 )
|
||||
immediatePackets.Add( packet );
|
||||
else
|
||||
frameClientData.GetOrAdd( frame ).Add( clientId, packet );
|
||||
} );
|
||||
|
||||
foreach( var p in immediatePackets )
|
||||
foreach( var o in p.ToOrderList( world ) )
|
||||
UnitOrders.ProcessOrder( o );
|
||||
}
|
||||
|
||||
public bool IsReadyForNextFrame
|
||||
{
|
||||
get { return readyForFrames.Contains( FrameNumber ); }
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if( !IsReadyForNextFrame )
|
||||
throw new InvalidOperationException();
|
||||
readyForFrames.RemoveAll( f => f <= FrameNumber );
|
||||
|
||||
Connection.Send( localOrders.Serialize( FrameNumber + FramesAhead ) );
|
||||
localOrders.Clear();
|
||||
|
||||
var frameData = frameClientData[ FrameNumber ];
|
||||
foreach( var order in frameData.OrderBy( p => p.Key ).SelectMany( o => o.Value.ToOrderList( world ) ) )
|
||||
UnitOrders.ProcessOrder( order );
|
||||
|
||||
++frameNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
OpenRa.Game/Orders/UnitOrders.cs → OpenRa.Game/Network/UnitOrders.cs
Normal file → Executable file
2
OpenRa.Game/Orders/UnitOrders.cs → OpenRa.Game/Network/UnitOrders.cs
Normal file → Executable file
@@ -4,7 +4,7 @@ using OpenRa.GameRules;
|
||||
using OpenRa.Graphics;
|
||||
using OpenRa.Traits;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
namespace OpenRa.Network
|
||||
{
|
||||
static class UnitOrders
|
||||
{
|
||||
@@ -101,19 +101,17 @@
|
||||
<Compile Include="Graphics\ChromeProvider.cs" />
|
||||
<Compile Include="Graphics\MappedImage.cs" />
|
||||
<Compile Include="Graphics\Minimap.cs" />
|
||||
<Compile Include="Network\Connection.cs" />
|
||||
<Compile Include="Resources1.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Orders\ChronosphereSelectOrderGenerator.cs" />
|
||||
<Compile Include="Orders\IOrderSource.cs" />
|
||||
<Compile Include="Orders\IronCurtainOrderGenerator.cs" />
|
||||
<Compile Include="Orders\LocalOrderSource.cs" />
|
||||
<Compile Include="Effects\Missile.cs" />
|
||||
<Compile Include="Orders\NetworkOrderSource.cs" />
|
||||
<Compile Include="Orders\OrderIO.cs" />
|
||||
<Compile Include="Orders\OrderManager.cs" />
|
||||
<Compile Include="Network\OrderIO.cs" />
|
||||
<Compile Include="Network\OrderManager.cs" />
|
||||
<Compile Include="Orders\PowerDownOrderGenerator.cs" />
|
||||
<Compile Include="Orders\RepairOrderGenerator.cs" />
|
||||
<Compile Include="Orders\SellOrderGenerator.cs" />
|
||||
@@ -122,7 +120,6 @@
|
||||
<Compile Include="PackageDownloader.cs" />
|
||||
<Compile Include="PathSearch.cs" />
|
||||
<Compile Include="ProductionItem.cs" />
|
||||
<Compile Include="Orders\ReplayOrderSource.cs" />
|
||||
<Compile Include="Shroud.cs" />
|
||||
<Compile Include="Smudge.cs" />
|
||||
<Compile Include="Sound.cs" />
|
||||
@@ -182,7 +179,7 @@
|
||||
<Compile Include="Graphics\Sheet.cs" />
|
||||
<Compile Include="PathFinder.cs" />
|
||||
<Compile Include="Graphics\Sequence.cs" />
|
||||
<Compile Include="Orders\Order.cs" />
|
||||
<Compile Include="Network\Order.cs" />
|
||||
<Compile Include="Graphics\SequenceProvider.cs" />
|
||||
<Compile Include="Graphics\SheetBuilder.cs" />
|
||||
<Compile Include="Graphics\HardwarePalette.cs" />
|
||||
@@ -271,7 +268,7 @@
|
||||
<Compile Include="Traits\Unit.cs" />
|
||||
<Compile Include="Traits\WaterPaletteRotation.cs" />
|
||||
<Compile Include="Traits\WithShadow.cs" />
|
||||
<Compile Include="Orders\UnitOrders.cs" />
|
||||
<Compile Include="Network\UnitOrders.cs" />
|
||||
<Compile Include="Traits\Util.cs" />
|
||||
<Compile Include="UiOverlay.cs" />
|
||||
<Compile Include="Graphics\Util.cs" />
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
{
|
||||
interface IOrderSource
|
||||
{
|
||||
void SendLocalOrders(int localFrame, List<Order> localOrders);
|
||||
List<byte[]> OrdersForFrame(int currentFrame);
|
||||
bool IsReadyForFrame(int frameNumber);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
{
|
||||
class LocalOrderSource : IOrderSource
|
||||
{
|
||||
Dictionary<int, List<byte[]>> orders = new Dictionary<int, List<byte[]>>();
|
||||
|
||||
public List<byte[]> OrdersForFrame(int currentFrame)
|
||||
{
|
||||
if (!orders.ContainsKey(currentFrame))
|
||||
return new List<byte[]>();
|
||||
|
||||
var result = orders[currentFrame];
|
||||
orders.Remove(currentFrame);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void SendLocalOrders(int localFrame, List<Order> localOrders)
|
||||
{
|
||||
if (localFrame == 0) return;
|
||||
orders[localFrame] = localOrders.Select(o=>o.Serialize()).ToList();
|
||||
}
|
||||
|
||||
public bool IsReadyForFrame(int frameNumber)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
{
|
||||
enum ConnectionState
|
||||
{
|
||||
NotConnected,
|
||||
Connecting,
|
||||
Connected,
|
||||
}
|
||||
|
||||
class NetworkOrderSource : IOrderSource
|
||||
{
|
||||
TcpClient socket;
|
||||
|
||||
Dictionary<int, List<byte[]>> orderBuffers = new Dictionary<int, List<byte[]>>();
|
||||
Dictionary<int, bool> gotEverything = new Dictionary<int, bool>();
|
||||
|
||||
public ConnectionState State { get; private set; }
|
||||
|
||||
public NetworkOrderSource(string host, int port)
|
||||
{
|
||||
State = ConnectionState.Connecting;
|
||||
|
||||
socket = new TcpClient();
|
||||
socket.BeginConnect(host, port, OnConnected, null);
|
||||
socket.NoDelay = true;
|
||||
}
|
||||
|
||||
void OnConnected(IAsyncResult r)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.EndConnect(r);
|
||||
State = ConnectionState.Connected;
|
||||
new Thread(() =>
|
||||
{
|
||||
var reader = new BinaryReader(socket.GetStream());
|
||||
|
||||
try
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
var len = reader.ReadInt32();
|
||||
var frame = reader.ReadInt32();
|
||||
var buf = reader.ReadBytes(len - 4);
|
||||
|
||||
lock (orderBuffers)
|
||||
{
|
||||
if (len == 5 && buf[0] == 0xef) /* got everything marker */
|
||||
gotEverything[frame] = true;
|
||||
else
|
||||
{
|
||||
/* accumulate this chunk */
|
||||
if (!orderBuffers.ContainsKey(frame))
|
||||
orderBuffers[frame] = new List<byte[]> { buf };
|
||||
else
|
||||
orderBuffers[frame].Add(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
State = ConnectionState.NotConnected;
|
||||
}
|
||||
|
||||
}) { IsBackground = true }.Start();
|
||||
}
|
||||
catch
|
||||
{
|
||||
State = ConnectionState.NotConnected;
|
||||
}
|
||||
}
|
||||
|
||||
static List<byte[]> NoOrders = new List<byte[]>();
|
||||
List<byte[]> ExtractOrders(int frame)
|
||||
{
|
||||
lock (orderBuffers)
|
||||
{
|
||||
List<byte[]> result;
|
||||
if (!orderBuffers.TryGetValue(frame, out result))
|
||||
result = NoOrders;
|
||||
orderBuffers.Remove(frame);
|
||||
gotEverything.Remove(frame);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public List<byte[]> OrdersForFrame(int currentFrame)
|
||||
{
|
||||
return ExtractOrders(currentFrame).ToList();
|
||||
}
|
||||
|
||||
public void SendLocalOrders(int localFrame, List<Order> localOrders)
|
||||
{
|
||||
if (socket.Connected)
|
||||
socket.GetStream().WriteFrameData(localOrders, localFrame);
|
||||
}
|
||||
|
||||
public bool IsReadyForFrame(int frameNumber)
|
||||
{
|
||||
lock (orderBuffers)
|
||||
return gotEverything.ContainsKey(frameNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
{
|
||||
class OrderManager
|
||||
{
|
||||
Stream savingReplay;
|
||||
List<IOrderSource> sources;
|
||||
int frameNumber = 0;
|
||||
|
||||
public int FramesAhead = 3;
|
||||
|
||||
public bool GameStarted { get { return frameNumber != 0; } }
|
||||
public bool IsNetplay { get { return sources.OfType<NetworkOrderSource>().Any(); } }
|
||||
|
||||
public void StartGame()
|
||||
{
|
||||
if (GameStarted) return;
|
||||
|
||||
frameNumber = 1;
|
||||
foreach (var p in this.sources)
|
||||
for (int i = frameNumber; i <= FramesAhead; i++)
|
||||
p.SendLocalOrders(i, new List<Order>());
|
||||
}
|
||||
|
||||
public IEnumerable<IOrderSource> Sources { get { return sources; } }
|
||||
|
||||
public int FrameNumber { get { return frameNumber; } }
|
||||
|
||||
public OrderManager( IEnumerable<IOrderSource> sources )
|
||||
{
|
||||
this.sources = sources.ToList();
|
||||
if (!IsNetplay)
|
||||
StartGame();
|
||||
}
|
||||
|
||||
public OrderManager( IEnumerable<IOrderSource> sources, string replayFilename )
|
||||
: this( sources )
|
||||
{
|
||||
savingReplay = new FileStream( replayFilename, FileMode.Create );
|
||||
}
|
||||
|
||||
public bool IsReadyForNextFrame
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach( var p in sources )
|
||||
if( !p.IsReadyForFrame( frameNumber ) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessOrders(World world, int frame, bool save)
|
||||
{
|
||||
var orders = sources
|
||||
.SelectMany(s => s.OrdersForFrame(frame))
|
||||
.SelectMany(x => x.ToOrderList(world))
|
||||
.OrderBy(o => o.Player.Index)
|
||||
.ToList();
|
||||
|
||||
foreach (var o in orders)
|
||||
UnitOrders.ProcessOrder(o);
|
||||
|
||||
if (save && savingReplay != null)
|
||||
savingReplay.WriteFrameData(orders, frame);
|
||||
}
|
||||
|
||||
public void TickImmediate( World world )
|
||||
{
|
||||
var localOrders = Game.controller.GetRecentOrders(true);
|
||||
if (localOrders.Count > 0)
|
||||
foreach (var p in sources)
|
||||
p.SendLocalOrders(0, localOrders);
|
||||
|
||||
ProcessOrders(world, 0, false);
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
var localOrders = Game.controller.GetRecentOrders(false);
|
||||
|
||||
foreach( var p in sources )
|
||||
p.SendLocalOrders( frameNumber + FramesAhead, localOrders );
|
||||
|
||||
ProcessOrders(world, frameNumber, true);
|
||||
|
||||
++frameNumber;
|
||||
|
||||
// sanity check on the framenumber. This is 2^31 frames maximum, or multiple *years* at 40ms/frame.
|
||||
if( ( frameNumber & 0x80000000 ) != 0 )
|
||||
throw new InvalidOperationException( "(OrderManager) Frame number too large" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRa.Orders
|
||||
{
|
||||
class ReplayOrderSource : IOrderSource
|
||||
{
|
||||
BinaryReader replayReader;
|
||||
public ReplayOrderSource(string replayFilename)
|
||||
{
|
||||
replayReader = new BinaryReader(File.Open(replayFilename, FileMode.Open));
|
||||
}
|
||||
|
||||
public void SendLocalOrders(int localFrame, List<Order> localOrders) { }
|
||||
|
||||
public List<byte[]> OrdersForFrame(int frameNumber)
|
||||
{
|
||||
if (frameNumber == 0)
|
||||
return new List<byte[]>();
|
||||
|
||||
try
|
||||
{
|
||||
var len = replayReader.ReadInt32() - 4;
|
||||
var frame = replayReader.ReadInt32();
|
||||
var ret = replayReader.ReadBytes(len);
|
||||
|
||||
if (frameNumber != frame)
|
||||
throw new InvalidOperationException("Attempted time-travel in OrdersForFrame (replay)");
|
||||
|
||||
return new List<byte[]> { ret };
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
return new List<byte[]>();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadyForFrame(int frameNumber)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ namespace OpenRa
|
||||
|
||||
Game.chat.AddLine(Color.White, "Debug", "Requesting package: {0}".F(currentPackage));
|
||||
|
||||
Game.controller.AddOrder(
|
||||
Game.orderManager.IssueOrder(
|
||||
new Order("RequestFile", Game.world.LocalPlayer.PlayerActor, null, int2.Zero, currentPackage) { IsImmediate = true });
|
||||
|
||||
Fraction = 0f;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRa.SupportPowers
|
||||
// Play chronosphere active anim
|
||||
var chronosphere = target.World.Actors.Where(a => a.Owner == p.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault();
|
||||
if (chronosphere != null)
|
||||
Game.controller.AddOrder(Order.PlayAnimation(chronosphere, "active"));
|
||||
Game.orderManager.IssueOrder(Order.PlayAnimation(chronosphere, "active"));
|
||||
|
||||
// Trigger screen desaturate effect
|
||||
foreach (var a in target.World.Actors.Where(a => a.traits.Contains<ChronoshiftPaletteEffect>()))
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRa.SupportPowers
|
||||
.Where(a => a.Owner == p.Owner && a.traits.Contains<IronCurtain>())
|
||||
.FirstOrDefault();
|
||||
if (ironCurtain != null)
|
||||
Game.controller.AddOrder(Order.PlayAnimation(ironCurtain, "active"));
|
||||
Game.orderManager.IssueOrder(Order.PlayAnimation(ironCurtain, "active"));
|
||||
|
||||
}
|
||||
SupportPower p;
|
||||
|
||||
Reference in New Issue
Block a user