added ready/gamestart handling

This commit is contained in:
Chris Forbes
2009-12-01 20:03:59 +13:00
parent 235ff36792
commit aa4517c7ab
7 changed files with 153 additions and 19 deletions

View File

@@ -15,6 +15,9 @@ namespace OpenRA.Server
public int ExpectLength = 8; public int ExpectLength = 8;
public int Frame = 0; public int Frame = 0;
/* client data */
public bool IsReady;
public byte[] PopBytes(int n) public byte[] PopBytes(int n)
{ {
var result = data.GetRange(0, n); var result = data.GetRange(0, n);

View File

@@ -10,6 +10,55 @@ using System.Collections;
namespace OpenRA.Server namespace OpenRA.Server
{ {
class ServerOrder
{
public readonly int PlayerId;
public readonly string Name;
public readonly string Data;
public ServerOrder(int playerId, string name, string data)
{
PlayerId = playerId;
Name = name;
Data = data;
}
public static ServerOrder Deserialize(BinaryReader r)
{
byte b;
switch (b = r.ReadByte())
{
case 0xff:
Console.WriteLine("This isn't a server order.");
return null;
case 0xfe:
{
var playerID = r.ReadInt32();
var name = r.ReadString();
var data = r.ReadString();
return new ServerOrder(playerID, name, data);
}
default:
throw new NotImplementedException(b.ToString("x2"));
}
}
public byte[] Serialize()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write((byte)0xfe);
bw.Write(PlayerId);
bw.Write(Name);
bw.Write(Data);
return ms.ToArray();
}
}
static class Server static class Server
{ {
static List<Connection> conns = new List<Connection>(); static List<Connection> conns = new List<Connection>();
@@ -27,10 +76,11 @@ namespace OpenRA.Server
checkRead.Add(listener.Server); checkRead.Add(listener.Server);
foreach (var c in conns) checkRead.Add(c.socket); foreach (var c in conns) checkRead.Add(c.socket);
Socket.Select(checkRead, null, null, 1000000 /* 1s */); /* msdn lies, -1 doesnt work. this is ~1h instead. */
Socket.Select(checkRead, null, null, -2 );
Console.WriteLine("Select() completed with {0} sockets", //Console.WriteLine("Select() completed with {0} sockets",
checkRead.Count); // checkRead.Count);
foreach (Socket s in checkRead) foreach (Socket s in checkRead)
if (s == listener.Server) AcceptConnection(); if (s == listener.Server) AcceptConnection();
@@ -62,7 +112,7 @@ namespace OpenRA.Server
{ {
if (0 < (len = conn.socket.Receive(rx))) if (0 < (len = conn.socket.Receive(rx)))
{ {
Console.WriteLine("Read {0} bytes", len); // Console.WriteLine("Read {0} bytes", len);
conn.data.AddRange(rx.Take(len)); conn.data.AddRange(rx.Take(len));
} }
else else
@@ -81,8 +131,8 @@ namespace OpenRA.Server
static void ReadData(Connection conn) static void ReadData(Connection conn)
{ {
Console.WriteLine("Start ReadData() for {0}", //Console.WriteLine("Start ReadData() for {0}",
conn.socket.RemoteEndPoint); // conn.socket.RemoteEndPoint);
if (ReadDataInner(conn)) if (ReadDataInner(conn))
while (conn.data.Count >= conn.ExpectLength) while (conn.data.Count >= conn.ExpectLength)
@@ -106,8 +156,8 @@ namespace OpenRA.Server
} }
} }
Console.WriteLine("End ReadData() for {0}", //Console.WriteLine("End ReadData() for {0}",
conn.socket.RemoteEndPoint); // conn.socket.RemoteEndPoint);
} }
static void DispatchOrders(Connection conn, int frame, byte[] data) static void DispatchOrders(Connection conn, int frame, byte[] data)
@@ -125,13 +175,40 @@ namespace OpenRA.Server
catch (Exception e) { DropClient(c, e); } catch (Exception e) { DropClient(c, e); }
} }
if (frame == 0) if (frame == 0 && conn != null)
InterpretServerOrders(data); InterpretServerOrders(conn, data);
} }
static void InterpretServerOrders(byte[] data) static void InterpretServerOrders(Connection conn, byte[] data)
{ {
/* todo: handle all server orders! */ var ms = new MemoryStream(data);
var br = new BinaryReader(ms);
try
{
for (; ; )
{
var so = ServerOrder.Deserialize(br);
if (so == null) return;
InterpretServerOrder(conn, so);
}
}
catch (EndOfStreamException) { }
}
static void InterpretServerOrder(Connection conn, ServerOrder so)
{
switch (so.Name)
{
case "ToggleReady":
conn.IsReady ^= true;
// start the game if everyone is ready.
if (conns.All(c => c.IsReady))
DispatchOrders(null, 0,
new ServerOrder(0, "StartGame", "").Serialize());
break;
}
} }
static void DropClient(Connection c, Exception e) static void DropClient(Connection c, Exception e)

View File

@@ -86,13 +86,14 @@ namespace OpenRa.Game
buildItems.Clear(); buildItems.Clear();
renderer.Device.DisableScissor(); renderer.Device.DisableScissor();
renderer.DrawText(string.Format("RenderFrame {0} ({2:F1} ms)\nTick {1} ({3:F1} ms)\n$ {4}\nPower {5}", renderer.DrawText(string.Format("RenderFrame {0} ({2:F1} ms)\nTick {1} ({3:F1} ms)\n$ {4}\nPower {5}\nReady: {6}",
Game.RenderFrame, Game.RenderFrame,
Game.orderManager.FrameNumber, Game.orderManager.FrameNumber,
PerfHistory.items["render"].LastValue, PerfHistory.items["render"].LastValue,
PerfHistory.items["tick_time"].LastValue, PerfHistory.items["tick_time"].LastValue,
Game.LocalPlayer.DisplayCash, Game.LocalPlayer.DisplayCash,
Game.LocalPlayer.GetTotalPower() Game.LocalPlayer.GetTotalPower(),
Game.LocalPlayer.IsReady ? "Yes" : "No"
), new int2(140, 5), Color.White); ), new int2(140, 5), Color.White);
PerfHistory.Render(renderer, Game.worldRenderer.lineRenderer); PerfHistory.Render(renderer, Game.worldRenderer.lineRenderer);

View File

@@ -129,8 +129,13 @@ namespace OpenRa.Game
base.OnKeyDown(e); base.OnKeyDown(e);
/* hack hack hack */ /* hack hack hack */
if (e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted) if (e.KeyCode == Keys.F8)
Game.orderManager.StartGame(); {
Game.LocalPlayer.IsReady ^= true;
Game.controller.AddOrder(
new Order(Game.LocalPlayer,
"ToggleReady", null, null, int2.Zero, "") { IsImmediate = true });
}
} }
protected override void OnKeyPress(KeyPressEventArgs e) protected override void OnKeyPress(KeyPressEventArgs e)

View File

@@ -17,7 +17,7 @@ namespace OpenRa.Game
public readonly string TargetString; public readonly string TargetString;
public bool IsImmediate; public bool IsImmediate;
Order(Player player, string orderString, Actor subject, public Order(Player player, string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString) Actor targetActor, int2 targetLocation, string targetString)
{ {
this.Player = player; this.Player = player;
@@ -30,6 +30,17 @@ namespace OpenRa.Game
public byte[] Serialize() public byte[] Serialize()
{ {
if (IsImmediate) /* chat, whatever */
{
var ret = new MemoryStream();
var w = new BinaryWriter(ret);
w.Write((byte)0xfe);
w.Write((uint)Player.Index);
w.Write(OrderString);
w.Write(TargetString);
return ret.ToArray();
}
switch (OrderString) switch (OrderString)
{ {
// Format: // Format:
@@ -56,6 +67,13 @@ namespace OpenRa.Game
} }
} }
static Player LookupPlayer(uint index)
{
return Game.players
.Where(x => x.Value.Index == index)
.First().Value;
}
public static Order Deserialize(BinaryReader r) public static Order Deserialize(BinaryReader r)
{ {
switch (r.ReadByte()) switch (r.ReadByte())
@@ -72,9 +90,21 @@ namespace OpenRa.Game
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( LookupPlayer(playerID),
return new Order( player, order, subject, targetActor, targetLocation, targetString); order, subject, targetActor, targetLocation,
targetString);
} }
case 0xfe:
{
var playerID = r.ReadUInt32();
var name = r.ReadString();
var data = r.ReadString();
return new Order(LookupPlayer(playerID),
name, null, null, int2.Zero, data);
}
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@@ -15,6 +15,8 @@ namespace OpenRa.Game
int powerProvided; int powerProvided;
int powerDrained; int powerDrained;
public bool IsReady;
public Player( int index, int palette, string playerName, Race race ) public Player( int index, int palette, string playerName, Race race )
{ {
this.Index = index; this.Index = index;

View File

@@ -97,6 +97,22 @@ namespace OpenRa.Game
Game.chat.AddLine(Pair.New(order.Player.PlayerName + ":", order.TargetString)); Game.chat.AddLine(Pair.New(order.Player.PlayerName + ":", order.TargetString));
break; break;
} }
case "ToggleReady":
{
Game.chat.AddLine(Pair.New(order.Player.PlayerName, "toggled ready status" ));
break;
}
case "AssignPlayer":
{
break; /* todo: set LocalPlayer based on this */
}
case "StartGame":
{
Game.chat.AddLine(Pair.New("Server:", "The game has started."));
Game.orderManager.StartGame();
break;
}
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }