Update copyright header. Normalize line endings to LF.

This commit is contained in:
Paul Chote
2011-02-13 10:38:57 +13:00
parent ea5e2c0588
commit 094907c1a9
489 changed files with 43614 additions and 43613 deletions

View File

@@ -1,210 +1,210 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using OpenRA.Server;
using OpenRA.Support;
namespace OpenRA.Network
{
public enum ConnectionState
{
PreConnecting,
NotConnected,
Connecting,
Connected,
}
public interface IConnection : IDisposable
{
int LocalClientId { get; }
ConnectionState ConnectionState { get; }
void Send( int frame, List<byte[]> orders );
void SendImmediate( List<byte[]> orders );
void SendSync( int frame, byte[] syncData );
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.PreConnecting; }
}
public virtual void Send( int frame, List<byte[]> orders )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
foreach( var o in orders )
ms.Write( o );
Send( ms.ToArray() );
}
public virtual void SendImmediate( List<byte[]> orders )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( (int)0 ) );
foreach( var o in orders )
ms.Write( o );
Send( ms.ToArray() );
}
public virtual void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
Send( ms.ToArray() );
}
protected virtual void Send( byte[] packet )
{
if( packet.Length == 0 )
throw new NotImplementedException();
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 );
}
public virtual void Dispose() { }
}
class NetworkConnection : EchoConnection
{
TcpClient socket;
int clientId;
ConnectionState connectionState = ConnectionState.Connecting;
Thread t;
public NetworkConnection( string host, int port )
{
t = new Thread( _ =>
{
try
{
socket = new TcpClient( host, port );
socket.NoDelay = true;
var reader = new BinaryReader( socket.GetStream() );
var serverProtocol = reader.ReadInt32();
if (ProtocolVersion.Version != serverProtocol)
throw new InvalidOperationException(
"Protocol version mismatch. Server={0} Client={1}"
.F(serverProtocol, ProtocolVersion.Version));
clientId = reader.ReadInt32();
connectionState = ConnectionState.Connected;
for( ; ; )
{
var len = reader.ReadInt32();
var client = reader.ReadInt32();
var buf = reader.ReadBytes( len );
if( len == 0 )
throw new NotImplementedException();
lock( this )
receivedPackets.Add( new ReceivedPacket { FromClient = client, Data = buf } );
}
}
catch { }
finally
{
connectionState = ConnectionState.NotConnected;
if( socket != null )
socket.Close();
}
}
) { IsBackground = true };
t.Start();
}
public override int LocalClientId { get { return clientId; } }
public override ConnectionState ConnectionState { get { return connectionState; } }
List<byte[]> queuedSyncPackets = new List<byte[]>();
public override void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
queuedSyncPackets.Add( ms.ToArray() );
}
protected override void Send( byte[] packet )
{
base.Send( packet );
try
{
var ms = new MemoryStream();
ms.Write(BitConverter.GetBytes((int)packet.Length));
ms.Write(packet);
foreach( var q in queuedSyncPackets )
{
ms.Write( BitConverter.GetBytes( (int)q.Length ) );
ms.Write( q );
base.Send( q );
}
queuedSyncPackets.Clear();
ms.WriteTo(socket.GetStream());
}
catch (SocketException) { /* drop this on the floor; we'll pick up the disconnect from the reader thread */ }
catch (ObjectDisposedException) { /* ditto */ }
catch (InvalidOperationException) { /* ditto */ }
}
bool disposed = false;
public override void Dispose ()
{
if (disposed) return;
disposed = true;
GC.SuppressFinalize( this );
t.Abort();
if (socket != null)
socket.Client.Close();
using( new PerfSample( "Thread.Join" ))
t.Join();
}
~NetworkConnection() { Dispose(); }
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using OpenRA.Server;
using OpenRA.Support;
namespace OpenRA.Network
{
public enum ConnectionState
{
PreConnecting,
NotConnected,
Connecting,
Connected,
}
public interface IConnection : IDisposable
{
int LocalClientId { get; }
ConnectionState ConnectionState { get; }
void Send( int frame, List<byte[]> orders );
void SendImmediate( List<byte[]> orders );
void SendSync( int frame, byte[] syncData );
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.PreConnecting; }
}
public virtual void Send( int frame, List<byte[]> orders )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
foreach( var o in orders )
ms.Write( o );
Send( ms.ToArray() );
}
public virtual void SendImmediate( List<byte[]> orders )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( (int)0 ) );
foreach( var o in orders )
ms.Write( o );
Send( ms.ToArray() );
}
public virtual void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
Send( ms.ToArray() );
}
protected virtual void Send( byte[] packet )
{
if( packet.Length == 0 )
throw new NotImplementedException();
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 );
}
public virtual void Dispose() { }
}
class NetworkConnection : EchoConnection
{
TcpClient socket;
int clientId;
ConnectionState connectionState = ConnectionState.Connecting;
Thread t;
public NetworkConnection( string host, int port )
{
t = new Thread( _ =>
{
try
{
socket = new TcpClient( host, port );
socket.NoDelay = true;
var reader = new BinaryReader( socket.GetStream() );
var serverProtocol = reader.ReadInt32();
if (ProtocolVersion.Version != serverProtocol)
throw new InvalidOperationException(
"Protocol version mismatch. Server={0} Client={1}"
.F(serverProtocol, ProtocolVersion.Version));
clientId = reader.ReadInt32();
connectionState = ConnectionState.Connected;
for( ; ; )
{
var len = reader.ReadInt32();
var client = reader.ReadInt32();
var buf = reader.ReadBytes( len );
if( len == 0 )
throw new NotImplementedException();
lock( this )
receivedPackets.Add( new ReceivedPacket { FromClient = client, Data = buf } );
}
}
catch { }
finally
{
connectionState = ConnectionState.NotConnected;
if( socket != null )
socket.Close();
}
}
) { IsBackground = true };
t.Start();
}
public override int LocalClientId { get { return clientId; } }
public override ConnectionState ConnectionState { get { return connectionState; } }
List<byte[]> queuedSyncPackets = new List<byte[]>();
public override void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
queuedSyncPackets.Add( ms.ToArray() );
}
protected override void Send( byte[] packet )
{
base.Send( packet );
try
{
var ms = new MemoryStream();
ms.Write(BitConverter.GetBytes((int)packet.Length));
ms.Write(packet);
foreach( var q in queuedSyncPackets )
{
ms.Write( BitConverter.GetBytes( (int)q.Length ) );
ms.Write( q );
base.Send( q );
}
queuedSyncPackets.Clear();
ms.WriteTo(socket.GetStream());
}
catch (SocketException) { /* drop this on the floor; we'll pick up the disconnect from the reader thread */ }
catch (ObjectDisposedException) { /* ditto */ }
catch (InvalidOperationException) { /* ditto */ }
}
bool disposed = false;
public override void Dispose ()
{
if (disposed) return;
disposed = true;
GC.SuppressFinalize( this );
t.Abort();
if (socket != null)
socket.Client.Close();
using( new PerfSample( "Thread.Join" ))
t.Join();
}
~NetworkConnection() { Dispose(); }
}
}

View File

@@ -1,10 +1,10 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
* see COPYING.
*/
#endregion

View File

@@ -1,227 +1,227 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.IO;
using System.Linq;
using OpenRA.Network;
namespace OpenRA
{
[Flags]
enum OrderFields : byte
{
TargetActor = 0x01,
TargetLocation = 0x02,
TargetString = 0x04,
Queued = 0x08,
ExtraLocation = 0x10,
}
static class OrderFieldsExts
{
public static bool HasField(this OrderFields of, OrderFields f)
{
return (of & f) != 0;
}
}
public sealed class Order
{
public readonly string OrderString;
public readonly Actor Subject;
public readonly bool Queued;
public Actor TargetActor;
public int2 TargetLocation;
public string TargetString;
public int2 ExtraLocation;
public bool IsImmediate;
public Player Player { get { return Subject.Owner; } }
Order(string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString, bool queued, int2 extraLocation)
{
this.OrderString = orderString;
this.Subject = subject;
this.TargetActor = targetActor;
this.TargetLocation = targetLocation;
this.TargetString = targetString;
this.Queued = queued;
this.ExtraLocation = extraLocation;
}
// For scripting special powers
public Order()
: this(null, null, null, int2.Zero, null, false, int2.Zero) { }
public Order(string orderString, Actor subject, bool queued)
: this(orderString, subject, null, int2.Zero, null, queued, int2.Zero) { }
public Order(string orderstring, Order order)
: this(orderstring, order.Subject, order.TargetActor, order.TargetLocation,
order.TargetString, order.Queued, order.ExtraLocation) {}
public byte[] Serialize()
{
if (IsImmediate) /* chat, whatever */
{
var ret = new MemoryStream();
var w = new BinaryWriter(ret);
w.Write((byte)0xfe);
w.Write(OrderString);
w.Write(TargetString);
return ret.ToArray();
}
switch (OrderString)
{
// Format:
// u8 : orderID.
// 0xFF: Full serialized order.
// varies: rest of order.
default:
// TODO: specific serializers for specific orders.
{
var ret = new MemoryStream();
var w = new BinaryWriter(ret);
w.Write( (byte)0xFF );
w.Write(OrderString);
w.Write(UIntFromActor(Subject));
OrderFields fields = 0;
if (TargetActor != null) fields |= OrderFields.TargetActor;
if (TargetLocation != int2.Zero) fields |= OrderFields.TargetLocation;
if (TargetString != null) fields |= OrderFields.TargetString;
if (Queued) fields |= OrderFields.Queued;
if (ExtraLocation != int2.Zero) fields |= OrderFields.ExtraLocation;
w.Write((byte)fields);
if (TargetActor != null)
w.Write(UIntFromActor(TargetActor));
if (TargetLocation != int2.Zero)
w.Write(TargetLocation);
if (TargetString != null)
w.Write(TargetString);
if (ExtraLocation != int2.Zero)
w.Write(ExtraLocation);
return ret.ToArray();
}
}
}
public static Order Deserialize(World world, BinaryReader r)
{
switch (r.ReadByte())
{
case 0xFF:
{
var order = r.ReadString();
var subjectId = r.ReadUInt32();
var flags = (OrderFields)r.ReadByte();
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff;
var targetLocation = flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero;
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued);
var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero;
Actor subject, targetActor;
if( !TryGetActorFromUInt( world, subjectId, out subject ) || !TryGetActorFromUInt( world, targetActorId, out targetActor ) )
return null;
return new Order( order, subject, targetActor, targetLocation, targetString, queued, extraLocation);
}
case 0xfe:
{
var name = r.ReadString();
var data = r.ReadString();
return new Order( name, null, false ) { IsImmediate = true, TargetString = data };
}
default:
throw new NotImplementedException();
}
}
public override string ToString()
{
return ("OrderString: \"{0}\" \n\t Subject: \"{1}\". \n\t TargetActor: \"{2}\" \n\t TargetLocation: {3}." +
"\n\t TargetString: \"{4}\".\n\t IsImmediate: {5}.\n\t Player(PlayerName): {6}\n").F(
OrderString, Subject, TargetActor != null ? TargetActor.Info.Name : null , TargetLocation, TargetString, IsImmediate, Player != null ? Player.PlayerName : null);
}
static uint UIntFromActor(Actor a)
{
if (a == null) return 0xffffffff;
return a.ActorID;
}
static bool TryGetActorFromUInt(World world, uint aID, out Actor ret )
{
if( aID == 0xFFFFFFFF )
{
ret = null;
return true;
}
else
{
foreach( var a in world.Actors.Where( x => x.ActorID == aID ) )
{
ret = a;
return true;
}
ret = null;
return false;
}
}
// Named constructors for Orders.
// Now that Orders are resolved by individual Actors, these are weird; you unpack orders manually, but not pack them.
public static Order Chat(string text)
{
return new Order("Chat", null, false) { IsImmediate = true, TargetString = text};
}
public static Order TeamChat(string text)
{
return new Order("TeamChat", null, false) { IsImmediate = true, TargetString = text };
}
public static Order HandshakeResponse(string text)
{
return new Order("HandshakeResponse", null, false) { IsImmediate = true, TargetString = text };
}
public static Order Command(string text)
{
return new Order("Command", null, false) { IsImmediate = true, TargetString = text };
}
public static Order StartProduction(Actor subject, string item, int count)
{
return new Order("StartProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
}
public static Order PauseProduction(Actor subject, string item, bool pause)
{
return new Order("PauseProduction", subject, false) { TargetLocation = new int2(pause ? 1 : 0, 0), TargetString = item };
}
public static Order CancelProduction(Actor subject, string item, int count)
{
return new Order("CancelProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.IO;
using System.Linq;
using OpenRA.Network;
namespace OpenRA
{
[Flags]
enum OrderFields : byte
{
TargetActor = 0x01,
TargetLocation = 0x02,
TargetString = 0x04,
Queued = 0x08,
ExtraLocation = 0x10,
}
static class OrderFieldsExts
{
public static bool HasField(this OrderFields of, OrderFields f)
{
return (of & f) != 0;
}
}
public sealed class Order
{
public readonly string OrderString;
public readonly Actor Subject;
public readonly bool Queued;
public Actor TargetActor;
public int2 TargetLocation;
public string TargetString;
public int2 ExtraLocation;
public bool IsImmediate;
public Player Player { get { return Subject.Owner; } }
Order(string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString, bool queued, int2 extraLocation)
{
this.OrderString = orderString;
this.Subject = subject;
this.TargetActor = targetActor;
this.TargetLocation = targetLocation;
this.TargetString = targetString;
this.Queued = queued;
this.ExtraLocation = extraLocation;
}
// For scripting special powers
public Order()
: this(null, null, null, int2.Zero, null, false, int2.Zero) { }
public Order(string orderString, Actor subject, bool queued)
: this(orderString, subject, null, int2.Zero, null, queued, int2.Zero) { }
public Order(string orderstring, Order order)
: this(orderstring, order.Subject, order.TargetActor, order.TargetLocation,
order.TargetString, order.Queued, order.ExtraLocation) {}
public byte[] Serialize()
{
if (IsImmediate) /* chat, whatever */
{
var ret = new MemoryStream();
var w = new BinaryWriter(ret);
w.Write((byte)0xfe);
w.Write(OrderString);
w.Write(TargetString);
return ret.ToArray();
}
switch (OrderString)
{
// Format:
// u8 : orderID.
// 0xFF: Full serialized order.
// varies: rest of order.
default:
// TODO: specific serializers for specific orders.
{
var ret = new MemoryStream();
var w = new BinaryWriter(ret);
w.Write( (byte)0xFF );
w.Write(OrderString);
w.Write(UIntFromActor(Subject));
OrderFields fields = 0;
if (TargetActor != null) fields |= OrderFields.TargetActor;
if (TargetLocation != int2.Zero) fields |= OrderFields.TargetLocation;
if (TargetString != null) fields |= OrderFields.TargetString;
if (Queued) fields |= OrderFields.Queued;
if (ExtraLocation != int2.Zero) fields |= OrderFields.ExtraLocation;
w.Write((byte)fields);
if (TargetActor != null)
w.Write(UIntFromActor(TargetActor));
if (TargetLocation != int2.Zero)
w.Write(TargetLocation);
if (TargetString != null)
w.Write(TargetString);
if (ExtraLocation != int2.Zero)
w.Write(ExtraLocation);
return ret.ToArray();
}
}
}
public static Order Deserialize(World world, BinaryReader r)
{
switch (r.ReadByte())
{
case 0xFF:
{
var order = r.ReadString();
var subjectId = r.ReadUInt32();
var flags = (OrderFields)r.ReadByte();
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff;
var targetLocation = flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero;
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued);
var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero;
Actor subject, targetActor;
if( !TryGetActorFromUInt( world, subjectId, out subject ) || !TryGetActorFromUInt( world, targetActorId, out targetActor ) )
return null;
return new Order( order, subject, targetActor, targetLocation, targetString, queued, extraLocation);
}
case 0xfe:
{
var name = r.ReadString();
var data = r.ReadString();
return new Order( name, null, false ) { IsImmediate = true, TargetString = data };
}
default:
throw new NotImplementedException();
}
}
public override string ToString()
{
return ("OrderString: \"{0}\" \n\t Subject: \"{1}\". \n\t TargetActor: \"{2}\" \n\t TargetLocation: {3}." +
"\n\t TargetString: \"{4}\".\n\t IsImmediate: {5}.\n\t Player(PlayerName): {6}\n").F(
OrderString, Subject, TargetActor != null ? TargetActor.Info.Name : null , TargetLocation, TargetString, IsImmediate, Player != null ? Player.PlayerName : null);
}
static uint UIntFromActor(Actor a)
{
if (a == null) return 0xffffffff;
return a.ActorID;
}
static bool TryGetActorFromUInt(World world, uint aID, out Actor ret )
{
if( aID == 0xFFFFFFFF )
{
ret = null;
return true;
}
else
{
foreach( var a in world.Actors.Where( x => x.ActorID == aID ) )
{
ret = a;
return true;
}
ret = null;
return false;
}
}
// Named constructors for Orders.
// Now that Orders are resolved by individual Actors, these are weird; you unpack orders manually, but not pack them.
public static Order Chat(string text)
{
return new Order("Chat", null, false) { IsImmediate = true, TargetString = text};
}
public static Order TeamChat(string text)
{
return new Order("TeamChat", null, false) { IsImmediate = true, TargetString = text };
}
public static Order HandshakeResponse(string text)
{
return new Order("HandshakeResponse", null, false) { IsImmediate = true, TargetString = text };
}
public static Order Command(string text)
{
return new Order("Command", null, false) { IsImmediate = true, TargetString = text };
}
public static Order StartProduction(Actor subject, string item, int count)
{
return new Order("StartProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
}
public static Order PauseProduction(Actor subject, string item, bool pause)
{
return new Order("PauseProduction", subject, false) { TargetLocation = new int2(pause ? 1 : 0, 0), TargetString = item };
}
public static Order CancelProduction(Actor subject, string item, int count)
{
return new Order("CancelProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
}
}
}

View File

@@ -1,62 +1,62 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using System.IO;
namespace OpenRA.Network
{
public static class OrderIO
{
public static void Write(this Stream s, byte[] buf)
{
s.Write(buf, 0, buf.Length);
}
public static List<Order> ToOrderList(this byte[] bytes, World world)
{
var ms = new MemoryStream(bytes, 4, bytes.Length - 4);
var reader = new BinaryReader(ms);
var ret = new List<Order>();
while( ms.Position < ms.Length )
{
var o = Order.Deserialize( world, reader );
if( o != null )
ret.Add( o );
}
return ret;
}
public static byte[] SerializeSync( this List<int> sync )
{
var ms = new MemoryStream();
using( var writer = new BinaryWriter( ms ) )
{
writer.Write( (byte)0x65 );
foreach( var s in sync )
writer.Write( s );
}
return ms.ToArray();
}
public static int2 ReadInt2(this BinaryReader r)
{
var x = r.ReadInt32();
var y = r.ReadInt32();
return new int2(x, y);
}
public static void Write(this BinaryWriter w, int2 p)
{
w.Write(p.X);
w.Write(p.Y);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.IO;
namespace OpenRA.Network
{
public static class OrderIO
{
public static void Write(this Stream s, byte[] buf)
{
s.Write(buf, 0, buf.Length);
}
public static List<Order> ToOrderList(this byte[] bytes, World world)
{
var ms = new MemoryStream(bytes, 4, bytes.Length - 4);
var reader = new BinaryReader(ms);
var ret = new List<Order>();
while( ms.Position < ms.Length )
{
var o = Order.Deserialize( world, reader );
if( o != null )
ret.Add( o );
}
return ret;
}
public static byte[] SerializeSync( this List<int> sync )
{
var ms = new MemoryStream();
using( var writer = new BinaryWriter( ms ) )
{
writer.Write( (byte)0x65 );
foreach( var s in sync )
writer.Write( s );
}
return ms.ToArray();
}
public static int2 ReadInt2(this BinaryReader r)
{
var x = r.ReadInt32();
var y = r.ReadInt32();
return new int2(x, y);
}
public static void Write(this BinaryWriter w, int2 p)
{
w.Write(p.X);
w.Write(p.Y);
}
}
}

View File

@@ -1,198 +1,198 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Network
{
public class OrderManager : IDisposable
{
readonly SyncReport syncReport;
readonly FrameData frameData = new FrameData();
public Session LobbyInfo = new Session( Game.Settings.Game.Mods );
public Session.Client LocalClient { get { return LobbyInfo.ClientWithIndex( Connection.LocalClientId ); } }
public World world;
public readonly string Host;
public readonly int Port;
public string ServerError;
public int NetFrameNumber { get; private set; }
public int LocalFrameNumber;
public int FramesAhead = 0;
public int LastTickTime = Environment.TickCount;
public bool GameStarted { get { return NetFrameNumber != 0; } }
public IConnection Connection { get; private set; }
public readonly int SyncHeaderSize = 9;
List<Order> localOrders = new List<Order>();
public void StartGame()
{
if (GameStarted) return;
NetFrameNumber = 1;
for( int i = NetFrameNumber ; i <= FramesAhead ; i++ )
Connection.Send( i, new List<byte[]>() );
}
public OrderManager( string host, int port, IConnection conn )
{
this.Host = host;
this.Port = port;
Connection = conn;
syncReport = new SyncReport( this );
}
public void IssueOrders( Order[] orders )
{
foreach( var order in orders )
IssueOrder( order );
}
public void IssueOrder( Order order )
{
localOrders.Add( order );
}
public void TickImmediate()
{
var immediateOrders = localOrders.Where( o => o.IsImmediate ).ToList();
if( immediateOrders.Count != 0 )
Connection.SendImmediate( immediateOrders.Select( o => o.Serialize() ).ToList() );
localOrders.RemoveAll( o => o.IsImmediate );
var immediatePackets = new List<Pair<int, byte[]>>();
Connection.Receive(
( clientId, packet ) =>
{
var frame = BitConverter.ToInt32( packet, 0 );
if( packet.Length == 5 && packet[ 4 ] == 0xBF )
frameData.ClientQuit( clientId, frame );
else if( packet.Length >= 5 && packet[ 4 ] == 0x65 )
CheckSync( packet );
else if( frame == 0 )
immediatePackets.Add( Pair.New( clientId, packet ) );
else
frameData.AddFrameOrders( clientId, frame, packet );
} );
foreach( var p in immediatePackets )
foreach( var o in p.Second.ToOrderList( world ) )
UnitOrders.ProcessOrder( this, world, p.First, o );
}
Dictionary<int, byte[]> syncForFrame = new Dictionary<int, byte[]>();
void CheckSync( byte[] packet )
{
var frame = BitConverter.ToInt32(packet, 0);
byte[] existingSync;
if (syncForFrame.TryGetValue(frame, out existingSync))
{
if (packet.Length != existingSync.Length)
{
syncReport.DumpSyncReport(frame);
OutOfSync(frame);
}
else
{
for (int i = 0; i < packet.Length; i++)
{
if (packet[i] != existingSync[i])
{
syncReport.DumpSyncReport(frame);
if (i < SyncHeaderSize)
OutOfSync(frame, "Tick");
else
OutOfSync(frame, (i - SyncHeaderSize) / 4);
}
}
}
}
else
syncForFrame.Add(frame, packet);
}
void OutOfSync(int frame, int index)
{
var orders = frameData.OrdersForFrame( world, frame );
// Invalid index
if (index >= orders.Count())
OutOfSync(frame);
throw new InvalidOperationException("Out of sync in frame {0}.\n {1}".F(frame, orders.ElementAt(index).Order.ToString()));
}
void OutOfSync(int frame)
{
throw new InvalidOperationException("Out of sync in frame {0}.\n".F(frame));
}
void OutOfSync(int frame, string blame)
{
throw new InvalidOperationException("Out of sync in frame {0}: Blame {1}.\n".F(frame, blame));
}
public bool IsReadyForNextFrame
{
get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame( NetFrameNumber ); }
}
public void Tick()
{
if( !IsReadyForNextFrame )
throw new InvalidOperationException();
Connection.Send( NetFrameNumber + FramesAhead, localOrders.Select( o => o.Serialize() ).ToList() );
localOrders.Clear();
var sync = new List<int>();
sync.Add( world.SyncHash() );
foreach( var order in frameData.OrdersForFrame( world, NetFrameNumber) )
{
UnitOrders.ProcessOrder( this, world, order.Client, order.Order );
sync.Add( world.SyncHash() );
}
var ss = sync.SerializeSync();
Connection.SendSync( NetFrameNumber, ss );
syncReport.UpdateSyncReport();
++NetFrameNumber;
}
bool disposed;
public void Dispose()
{
if (disposed) return;
Connection.Dispose();
disposed = true;
GC.SuppressFinalize(this);
}
~OrderManager() { Dispose(); }
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Network
{
public class OrderManager : IDisposable
{
readonly SyncReport syncReport;
readonly FrameData frameData = new FrameData();
public Session LobbyInfo = new Session( Game.Settings.Game.Mods );
public Session.Client LocalClient { get { return LobbyInfo.ClientWithIndex( Connection.LocalClientId ); } }
public World world;
public readonly string Host;
public readonly int Port;
public string ServerError;
public int NetFrameNumber { get; private set; }
public int LocalFrameNumber;
public int FramesAhead = 0;
public int LastTickTime = Environment.TickCount;
public bool GameStarted { get { return NetFrameNumber != 0; } }
public IConnection Connection { get; private set; }
public readonly int SyncHeaderSize = 9;
List<Order> localOrders = new List<Order>();
public void StartGame()
{
if (GameStarted) return;
NetFrameNumber = 1;
for( int i = NetFrameNumber ; i <= FramesAhead ; i++ )
Connection.Send( i, new List<byte[]>() );
}
public OrderManager( string host, int port, IConnection conn )
{
this.Host = host;
this.Port = port;
Connection = conn;
syncReport = new SyncReport( this );
}
public void IssueOrders( Order[] orders )
{
foreach( var order in orders )
IssueOrder( order );
}
public void IssueOrder( Order order )
{
localOrders.Add( order );
}
public void TickImmediate()
{
var immediateOrders = localOrders.Where( o => o.IsImmediate ).ToList();
if( immediateOrders.Count != 0 )
Connection.SendImmediate( immediateOrders.Select( o => o.Serialize() ).ToList() );
localOrders.RemoveAll( o => o.IsImmediate );
var immediatePackets = new List<Pair<int, byte[]>>();
Connection.Receive(
( clientId, packet ) =>
{
var frame = BitConverter.ToInt32( packet, 0 );
if( packet.Length == 5 && packet[ 4 ] == 0xBF )
frameData.ClientQuit( clientId, frame );
else if( packet.Length >= 5 && packet[ 4 ] == 0x65 )
CheckSync( packet );
else if( frame == 0 )
immediatePackets.Add( Pair.New( clientId, packet ) );
else
frameData.AddFrameOrders( clientId, frame, packet );
} );
foreach( var p in immediatePackets )
foreach( var o in p.Second.ToOrderList( world ) )
UnitOrders.ProcessOrder( this, world, p.First, o );
}
Dictionary<int, byte[]> syncForFrame = new Dictionary<int, byte[]>();
void CheckSync( byte[] packet )
{
var frame = BitConverter.ToInt32(packet, 0);
byte[] existingSync;
if (syncForFrame.TryGetValue(frame, out existingSync))
{
if (packet.Length != existingSync.Length)
{
syncReport.DumpSyncReport(frame);
OutOfSync(frame);
}
else
{
for (int i = 0; i < packet.Length; i++)
{
if (packet[i] != existingSync[i])
{
syncReport.DumpSyncReport(frame);
if (i < SyncHeaderSize)
OutOfSync(frame, "Tick");
else
OutOfSync(frame, (i - SyncHeaderSize) / 4);
}
}
}
}
else
syncForFrame.Add(frame, packet);
}
void OutOfSync(int frame, int index)
{
var orders = frameData.OrdersForFrame( world, frame );
// Invalid index
if (index >= orders.Count())
OutOfSync(frame);
throw new InvalidOperationException("Out of sync in frame {0}.\n {1}".F(frame, orders.ElementAt(index).Order.ToString()));
}
void OutOfSync(int frame)
{
throw new InvalidOperationException("Out of sync in frame {0}.\n".F(frame));
}
void OutOfSync(int frame, string blame)
{
throw new InvalidOperationException("Out of sync in frame {0}: Blame {1}.\n".F(frame, blame));
}
public bool IsReadyForNextFrame
{
get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame( NetFrameNumber ); }
}
public void Tick()
{
if( !IsReadyForNextFrame )
throw new InvalidOperationException();
Connection.Send( NetFrameNumber + FramesAhead, localOrders.Select( o => o.Serialize() ).ToList() );
localOrders.Clear();
var sync = new List<int>();
sync.Add( world.SyncHash() );
foreach( var order in frameData.OrdersForFrame( world, NetFrameNumber) )
{
UnitOrders.ProcessOrder( this, world, order.Client, order.Order );
sync.Add( world.SyncHash() );
}
var ss = sync.SerializeSync();
Connection.SendSync( NetFrameNumber, ss );
syncReport.UpdateSyncReport();
++NetFrameNumber;
}
bool disposed;
public void Dispose()
{
if (disposed) return;
Connection.Dispose();
disposed = true;
GC.SuppressFinalize(this);
}
~OrderManager() { Dispose(); }
}
}

View File

@@ -1,122 +1,122 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Network
{
public class Session
{
public List<Client> Clients = new List<Client>();
public List<Slot> Slots = new List<Slot>();
public Global GlobalSettings = new Global();
public Client ClientWithIndex(int clientID)
{
return Clients.SingleOrDefault(c => c.Index == clientID);
}
public Client ClientInSlot(Slot slot)
{
return Clients.SingleOrDefault(c => c.Slot == slot.Index);
}
public enum ClientState
{
NotReady,
Ready,
Disconnected = 1000
}
public class Client
{
public int Index;
public ColorRamp ColorRamp;
public string Country;
public int SpawnPoint;
public string Name;
public ClientState State;
public int Team;
public int Slot; // which slot we're in, or -1 for `observer`.
}
public class Slot
{
public int Index;
public string Bot; // trait name of the bot to initialize in this slot, or null otherwise.
public bool Closed; // host has explicitly closed this slot.
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Network
{
public class Session
{
public List<Client> Clients = new List<Client>();
public List<Slot> Slots = new List<Slot>();
public Global GlobalSettings = new Global();
public Client ClientWithIndex(int clientID)
{
return Clients.SingleOrDefault(c => c.Index == clientID);
}
public Client ClientInSlot(Slot slot)
{
return Clients.SingleOrDefault(c => c.Slot == slot.Index);
}
public enum ClientState
{
NotReady,
Ready,
Disconnected = 1000
}
public class Client
{
public int Index;
public ColorRamp ColorRamp;
public string Country;
public int SpawnPoint;
public string Name;
public ClientState State;
public int Team;
public int Slot; // which slot we're in, or -1 for `observer`.
}
public class Slot
{
public int Index;
public string Bot; // trait name of the bot to initialize in this slot, or null otherwise.
public bool Closed; // host has explicitly closed this slot.
public string MapPlayer; // playerReference to bind against.
public bool Spectator = false; // Spectating or not
// todo: more stuff?
}
public class Global
{
public string ServerName;
public string Map;
public string[] Mods = { "ra" }; // mod names
public int OrderLatency = 3;
public int RandomSeed = 0;
public bool LockTeams = true; // don't allow team changes after game start.
public bool AllowCheats = false;
}
public Session(string[] mods)
{
this.GlobalSettings.Mods = mods.ToArray();
}
public string Serialize()
{
var clientData = new List<MiniYamlNode>();
foreach (var client in Clients)
clientData.Add(new MiniYamlNode("Client@{0}".F(client.Index), FieldSaver.Save(client)));
foreach (var slot in Slots)
clientData.Add(new MiniYamlNode("Slot@{0}".F(slot.Index), FieldSaver.Save(slot)));
clientData.Add(new MiniYamlNode("GlobalSettings", FieldSaver.Save(GlobalSettings)));
return clientData.WriteToString();
}
public static Session Deserialize(string data)
{
var session = new Session(Game.Settings.Game.Mods);
var ys = MiniYaml.FromString(data);
foreach (var y in ys)
{
var yy = y.Key.Split('@');
switch (yy[0])
{
case "GlobalSettings":
FieldLoader.Load(session.GlobalSettings, y.Value);
break;
case "Client":
session.Clients.Add(FieldLoader.Load<Session.Client>(y.Value));
break;
case "Slot":
session.Slots.Add(FieldLoader.Load<Session.Slot>(y.Value));
break;
}
}
return session;
}
}
}
public bool Spectator = false; // Spectating or not
// todo: more stuff?
}
public class Global
{
public string ServerName;
public string Map;
public string[] Mods = { "ra" }; // mod names
public int OrderLatency = 3;
public int RandomSeed = 0;
public bool LockTeams = true; // don't allow team changes after game start.
public bool AllowCheats = false;
}
public Session(string[] mods)
{
this.GlobalSettings.Mods = mods.ToArray();
}
public string Serialize()
{
var clientData = new List<MiniYamlNode>();
foreach (var client in Clients)
clientData.Add(new MiniYamlNode("Client@{0}".F(client.Index), FieldSaver.Save(client)));
foreach (var slot in Slots)
clientData.Add(new MiniYamlNode("Slot@{0}".F(slot.Index), FieldSaver.Save(slot)));
clientData.Add(new MiniYamlNode("GlobalSettings", FieldSaver.Save(GlobalSettings)));
return clientData.WriteToString();
}
public static Session Deserialize(string data)
{
var session = new Session(Game.Settings.Game.Mods);
var ys = MiniYaml.FromString(data);
foreach (var y in ys)
{
var yy = y.Key.Split('@');
switch (yy[0])
{
case "GlobalSettings":
FieldLoader.Load(session.GlobalSettings, y.Value);
break;
case "Client":
session.Clients.Add(FieldLoader.Load<Session.Client>(y.Value));
break;
case "Slot":
session.Slots.Add(FieldLoader.Load<Session.Slot>(y.Value));
break;
}
}
return session;
}
}
}

View File

@@ -1,93 +1,93 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Network
{
class SyncReport
{
readonly OrderManager orderManager;
const int numSyncReports = 5;
Report[] syncReports = new Report[numSyncReports];
int curIndex = 0;
public SyncReport( OrderManager orderManager )
{
this.orderManager = orderManager;
for (var i = 0; i < numSyncReports; i++)
syncReports[i] = new SyncReport.Report();
}
internal void UpdateSyncReport()
{
GenerateSyncReport(syncReports[curIndex]);
curIndex = ++curIndex % numSyncReports;
}
void GenerateSyncReport(Report report)
{
report.Frame = orderManager.NetFrameNumber;
report.SyncedRandom = orderManager.world.SharedRandom.Last;
report.Traits.Clear();
foreach (var a in orderManager.world.Queries.WithTrait<ISync>())
{
var sync = Sync.CalculateSyncHash(a.Trait);
if (sync != 0)
report.Traits.Add(new TraitReport()
{
ActorID = a.Actor.ActorID,
Type = a.Actor.Info.Name,
Owner = (a.Actor.Owner == null) ? "null" : a.Actor.Owner.PlayerName,
Trait = a.Trait.GetType().Name,
Hash = sync
});
}
}
internal void DumpSyncReport(int frame)
{
foreach (var r in syncReports)
if (r.Frame == frame)
{
Log.Write("sync", "Sync for net frame {0} -------------", r.Frame);
Log.Write("sync", "SharedRandom: "+r.SyncedRandom);
Log.Write("sync", "Synced Traits:");
foreach (var a in r.Traits)
Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(
a.ActorID,
a.Type,
a.Owner,
a.Trait,
a.Hash
));
return;
}
Log.Write("sync", "No sync report available!");
}
class Report
{
public int Frame;
public int SyncedRandom;
public List<TraitReport> Traits = new List<TraitReport>();
}
struct TraitReport
{
public uint ActorID;
public string Type;
public string Owner;
public string Trait;
public int Hash;
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Network
{
class SyncReport
{
readonly OrderManager orderManager;
const int numSyncReports = 5;
Report[] syncReports = new Report[numSyncReports];
int curIndex = 0;
public SyncReport( OrderManager orderManager )
{
this.orderManager = orderManager;
for (var i = 0; i < numSyncReports; i++)
syncReports[i] = new SyncReport.Report();
}
internal void UpdateSyncReport()
{
GenerateSyncReport(syncReports[curIndex]);
curIndex = ++curIndex % numSyncReports;
}
void GenerateSyncReport(Report report)
{
report.Frame = orderManager.NetFrameNumber;
report.SyncedRandom = orderManager.world.SharedRandom.Last;
report.Traits.Clear();
foreach (var a in orderManager.world.Queries.WithTrait<ISync>())
{
var sync = Sync.CalculateSyncHash(a.Trait);
if (sync != 0)
report.Traits.Add(new TraitReport()
{
ActorID = a.Actor.ActorID,
Type = a.Actor.Info.Name,
Owner = (a.Actor.Owner == null) ? "null" : a.Actor.Owner.PlayerName,
Trait = a.Trait.GetType().Name,
Hash = sync
});
}
}
internal void DumpSyncReport(int frame)
{
foreach (var r in syncReports)
if (r.Frame == frame)
{
Log.Write("sync", "Sync for net frame {0} -------------", r.Frame);
Log.Write("sync", "SharedRandom: "+r.SyncedRandom);
Log.Write("sync", "Synced Traits:");
foreach (var a in r.Traits)
Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(
a.ActorID,
a.Type,
a.Owner,
a.Trait,
a.Hash
));
return;
}
Log.Write("sync", "No sync report available!");
}
class Report
{
public int Frame;
public int SyncedRandom;
public List<TraitReport> Traits = new List<TraitReport>();
}
struct TraitReport
{
public uint ActorID;
public string Type;
public string Owner;
public string Trait;
public int Hash;
}
}
}

View File

@@ -1,194 +1,194 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
using System;
using OpenRA.FileFormats;
namespace OpenRA.Network
{
static class UnitOrders
{
static Player FindPlayerByClient(this World world, Session.Client c)
{
/* todo: this is still a hack.
* the cases we're trying to avoid are the extra players on the host's client -- Neutral, other MapPlayers,
* bots,.. */
return world.players.Values.FirstOrDefault(
p => p.ClientIndex == c.Index && p.PlayerName == c.Name);
}
public static void ProcessOrder(OrderManager orderManager, World world, int clientId, Order order)
{
if (world != null)
{
if (!world.WorldActor.TraitsImplementing<IValidateOrder>().All(vo =>
vo.OrderValidation(orderManager, world, clientId, order)))
return;
}
switch (order.OrderString)
{
case "Chat":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
var player = world != null ? world.FindPlayerByClient(client) : null;
var suffix = (player != null && player.WinState == WinState.Lost) ? " (Dead)" : "";
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + suffix, order.TargetString);
}
else
Game.AddChatLine(Color.White, "(player {0})".F(clientId), order.TargetString);
break;
}
case "Disconnected": /* reports that the target player disconnected */
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
client.State = Session.ClientState.Disconnected;
}
break;
}
case "TeamChat":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
if (world == null)
{
if (client.Team == orderManager.LocalClient.Team)
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + " (Team)",
order.TargetString);
}
else
{
var player = world.FindPlayerByClient(client);
var display = player != null
&&
(world.LocalPlayer != null &&
player.Stances[world.LocalPlayer] == Stance.Ally
|| player.WinState == WinState.Lost);
if (display)
{
var suffix = (player != null && player.WinState == WinState.Lost)
? " (Dead)"
: " (Team)";
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + suffix, order.TargetString);
}
}
}
break;
}
case "StartGame":
{
Game.AddChatLine(Color.White, "Server", "The game has started.");
Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map);
break;
}
case "HandshakeRequest":
{
var request = HandshakeRequest.Deserialize(order.TargetString);
// Check that the map exists on the client
if (!Game.modData.AvailableMaps.ContainsKey(request.Map))
throw new InvalidOperationException("Missing map {0}".F(request.Map));
var info = new Session.Client()
{
Name = Game.Settings.Player.Name,
ColorRamp = Game.Settings.Player.ColorRamp,
Country = "random",
SpawnPoint = 0,
Team = 0,
State = Session.ClientState.NotReady
};
var localMods = orderManager.LobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m,Mod.AllMods[m].Version)).ToArray();
var response = new HandshakeResponse()
{
Client = info,
Mods = localMods,
Password = "Foo"
};
orderManager.IssueOrder(Order.HandshakeResponse(response.Serialize()));
break;
}
case "ServerError":
orderManager.ServerError = order.TargetString;
break;
case "SyncInfo":
{
orderManager.LobbyInfo = Session.Deserialize(order.TargetString);
if (orderManager.FramesAhead != orderManager.LobbyInfo.GlobalSettings.OrderLatency
&& !orderManager.GameStarted)
{
orderManager.FramesAhead = orderManager.LobbyInfo.GlobalSettings.OrderLatency;
Game.Debug(
"Order lag is now {0} frames.".F(orderManager.LobbyInfo.GlobalSettings.OrderLatency));
}
Game.SyncLobbyInfo();
break;
}
case "SetStance":
{
if (Game.orderManager.LobbyInfo.GlobalSettings.LockTeams)
return;
var targetPlayer = order.Player.World.players[order.TargetLocation.X];
var newStance = (Stance)order.TargetLocation.Y;
SetPlayerStance(world, order.Player, targetPlayer, newStance);
Game.Debug("{0} has set diplomatic stance vs {1} to {2}".F(
order.Player.PlayerName, targetPlayer.PlayerName, newStance));
// automatically declare war reciprocally
if (newStance == Stance.Enemy && targetPlayer.Stances[order.Player] == Stance.Ally)
{
SetPlayerStance(world, targetPlayer, order.Player, newStance);
Game.Debug("{0} has reciprocated",targetPlayer.PlayerName);
}
break;
}
default:
{
if( !order.IsImmediate )
{
var self = order.Subject;
var health = self.TraitOrDefault<Health>();
if( health == null || !health.IsDead )
foreach( var t in self.TraitsImplementing<IResolveOrder>() )
t.ResolveOrder( self, order );
}
break;
}
}
}
static void SetPlayerStance(World w, Player p, Player target, Stance s)
{
var oldStance = p.Stances[target];
p.Stances[target] = s;
if (target == w.LocalPlayer)
w.WorldActor.Trait<Shroud>().UpdatePlayerStance(w, p, oldStance, s);
}
}
}
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
using System;
using OpenRA.FileFormats;
namespace OpenRA.Network
{
static class UnitOrders
{
static Player FindPlayerByClient(this World world, Session.Client c)
{
/* todo: this is still a hack.
* the cases we're trying to avoid are the extra players on the host's client -- Neutral, other MapPlayers,
* bots,.. */
return world.players.Values.FirstOrDefault(
p => p.ClientIndex == c.Index && p.PlayerName == c.Name);
}
public static void ProcessOrder(OrderManager orderManager, World world, int clientId, Order order)
{
if (world != null)
{
if (!world.WorldActor.TraitsImplementing<IValidateOrder>().All(vo =>
vo.OrderValidation(orderManager, world, clientId, order)))
return;
}
switch (order.OrderString)
{
case "Chat":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
var player = world != null ? world.FindPlayerByClient(client) : null;
var suffix = (player != null && player.WinState == WinState.Lost) ? " (Dead)" : "";
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + suffix, order.TargetString);
}
else
Game.AddChatLine(Color.White, "(player {0})".F(clientId), order.TargetString);
break;
}
case "Disconnected": /* reports that the target player disconnected */
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
client.State = Session.ClientState.Disconnected;
}
break;
}
case "TeamChat":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
if (world == null)
{
if (client.Team == orderManager.LocalClient.Team)
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + " (Team)",
order.TargetString);
}
else
{
var player = world.FindPlayerByClient(client);
var display = player != null
&&
(world.LocalPlayer != null &&
player.Stances[world.LocalPlayer] == Stance.Ally
|| player.WinState == WinState.Lost);
if (display)
{
var suffix = (player != null && player.WinState == WinState.Lost)
? " (Dead)"
: " (Team)";
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + suffix, order.TargetString);
}
}
}
break;
}
case "StartGame":
{
Game.AddChatLine(Color.White, "Server", "The game has started.");
Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map);
break;
}
case "HandshakeRequest":
{
var request = HandshakeRequest.Deserialize(order.TargetString);
// Check that the map exists on the client
if (!Game.modData.AvailableMaps.ContainsKey(request.Map))
throw new InvalidOperationException("Missing map {0}".F(request.Map));
var info = new Session.Client()
{
Name = Game.Settings.Player.Name,
ColorRamp = Game.Settings.Player.ColorRamp,
Country = "random",
SpawnPoint = 0,
Team = 0,
State = Session.ClientState.NotReady
};
var localMods = orderManager.LobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m,Mod.AllMods[m].Version)).ToArray();
var response = new HandshakeResponse()
{
Client = info,
Mods = localMods,
Password = "Foo"
};
orderManager.IssueOrder(Order.HandshakeResponse(response.Serialize()));
break;
}
case "ServerError":
orderManager.ServerError = order.TargetString;
break;
case "SyncInfo":
{
orderManager.LobbyInfo = Session.Deserialize(order.TargetString);
if (orderManager.FramesAhead != orderManager.LobbyInfo.GlobalSettings.OrderLatency
&& !orderManager.GameStarted)
{
orderManager.FramesAhead = orderManager.LobbyInfo.GlobalSettings.OrderLatency;
Game.Debug(
"Order lag is now {0} frames.".F(orderManager.LobbyInfo.GlobalSettings.OrderLatency));
}
Game.SyncLobbyInfo();
break;
}
case "SetStance":
{
if (Game.orderManager.LobbyInfo.GlobalSettings.LockTeams)
return;
var targetPlayer = order.Player.World.players[order.TargetLocation.X];
var newStance = (Stance)order.TargetLocation.Y;
SetPlayerStance(world, order.Player, targetPlayer, newStance);
Game.Debug("{0} has set diplomatic stance vs {1} to {2}".F(
order.Player.PlayerName, targetPlayer.PlayerName, newStance));
// automatically declare war reciprocally
if (newStance == Stance.Enemy && targetPlayer.Stances[order.Player] == Stance.Ally)
{
SetPlayerStance(world, targetPlayer, order.Player, newStance);
Game.Debug("{0} has reciprocated",targetPlayer.PlayerName);
}
break;
}
default:
{
if( !order.IsImmediate )
{
var self = order.Subject;
var health = self.TraitOrDefault<Health>();
if( health == null || !health.IsDead )
foreach( var t in self.TraitsImplementing<IResolveOrder>() )
t.ResolveOrder( self, order );
}
break;
}
}
}
static void SetPlayerStance(World w, Player p, Player target, Stance s)
{
var oldStance = p.Stances[target];
p.Stances[target] = s;
if (target == w.LocalPlayer)
w.WorldActor.Trait<Shroud>().UpdatePlayerStance(w, p, oldStance, s);
}
}
}