lobby info hax

This commit is contained in:
Chris Forbes
2010-01-14 21:42:18 +13:00
parent 6184169408
commit 88c085c1c0
7 changed files with 178 additions and 103 deletions

View File

@@ -51,6 +51,17 @@
<Compile Include="Connection.cs" /> <Compile Include="Connection.cs" />
<Compile Include="Server.cs" /> <Compile Include="Server.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerOrder.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRa.DataStructures\OpenRa.DataStructures.csproj">
<Project>{2F9E7A23-56C0-4286-9C8E-1060A9B2F073}</Project>
<Name>OpenRa.DataStructures</Name>
</ProjectReference>
<ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj">
<Project>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</Project>
<Name>OpenRa.FileFormats</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -1,70 +1,21 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using OpenRa.FileFormats;
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>();
static TcpListener listener = new TcpListener(IPAddress.Any, 1234); static TcpListener listener = new TcpListener(IPAddress.Any, 1234);
static Dictionary<int, List<Connection>> inFlightFrames static Dictionary<int, List<Connection>> inFlightFrames
= new Dictionary<int, List<Connection>>(); = new Dictionary<int, List<Connection>>();
static Session lobbyInfo = new Session();
public static void Main(string[] args) public static void Main(string[] args)
{ {
@@ -109,16 +60,26 @@ namespace OpenRA.Server
conns.Add(newConn); conns.Add(newConn);
lobbyInfo.Clients.Add(
new Session.Client()
{
Index = newConn.PlayerIndex,
Palette = newConn.PlayerIndex,
Name = "Player {0}".F(newConn.PlayerIndex),
Race = 1,
State = Session.ClientState.NotReady
});
DispatchOrdersToClient(newConn, 0, DispatchOrdersToClient(newConn, 0,
new ServerOrder(newConn.PlayerIndex, "AssignPlayer", "").Serialize()); new ServerOrder(newConn.PlayerIndex, "AssignPlayer", "").Serialize());
// todo: tell this client about all the other conns.
Console.WriteLine("Accepted connection from {0}.", Console.WriteLine("Accepted connection from {0}.",
newConn.socket.RemoteEndPoint); newConn.socket.RemoteEndPoint);
DispatchOrders(newConn, 0, new ServerOrder(newConn.PlayerIndex, DispatchOrders(newConn, 0, new ServerOrder(newConn.PlayerIndex,
"Chat", "has joined the game.").Serialize()); "Chat", "has joined the game.").Serialize());
SyncLobbyInfo();
} }
catch (Exception e) { DropClient(newConn, e); } catch (Exception e) { DropClient(newConn, e); }
} }
@@ -165,8 +126,8 @@ namespace OpenRA.Server
case ReceiveState.Data: case ReceiveState.Data:
{ {
if (bytes.Length > 0) // if (bytes.Length > 0)
Console.WriteLine("{0} bytes", bytes.Length); // Console.WriteLine("{0} bytes", bytes.Length);
DispatchOrders(conn, conn.Frame, bytes); DispatchOrders(conn, conn.Frame, bytes);
conn.ExpectLength = 8; conn.ExpectLength = 8;
@@ -242,7 +203,8 @@ namespace OpenRA.Server
s => s =>
{ {
Console.WriteLine("Player@{0} is now known as {1}", conn.socket.RemoteEndPoint, s); Console.WriteLine("Player@{0} is now known as {1}", conn.socket.RemoteEndPoint, s);
DispatchOrders( null, 0, new ServerOrder( conn.PlayerIndex, "SetName", s ).Serialize()); lobbyInfo.Clients[ conn.PlayerIndex ].Name = s;
SyncLobbyInfo();
return true; return true;
}}, }},
{ "lag", { "lag",
@@ -275,8 +237,8 @@ namespace OpenRA.Server
return false; return false;
} }
DispatchOrders(null, 0, lobbyInfo.Clients[ conn.PlayerIndex ].Race = 1 + race;
new ServerOrder(conn.PlayerIndex, "SetRace", race.ToString()).Serialize()); SyncLobbyInfo();
return true; return true;
}}, }},
{ "pal", { "pal",
@@ -297,8 +259,8 @@ namespace OpenRA.Server
return false; return false;
} }
DispatchOrders(null, 0, lobbyInfo.Clients[ conn.PlayerIndex ].Palette = pal;
new ServerOrder(conn.PlayerIndex, "SetPalette", pal.ToString()).Serialize()); SyncLobbyInfo();
return true; return true;
}}, }},
{ "map", { "map",
@@ -379,11 +341,13 @@ namespace OpenRA.Server
static void DropClient(Connection toDrop, Exception e) static void DropClient(Connection toDrop, Exception e)
{ {
Console.WriteLine("Client dropped: {0}.", toDrop.socket.RemoteEndPoint); Console.WriteLine("Client dropped: {0}.", toDrop.socket.RemoteEndPoint);
Console.WriteLine(e.ToString()); //Console.WriteLine(e.ToString());
conns.Remove(toDrop); conns.Remove(toDrop);
SendChat(toDrop, "Connection Dropped"); SendChat(toDrop, "Connection Dropped");
lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex);
/* don't get stuck waiting for the dropped player, if they were the one holding up a frame */ /* don't get stuck waiting for the dropped player, if they were the one holding up a frame */
foreach( var f in inFlightFrames.ToArray() ) foreach( var f in inFlightFrames.ToArray() )
@@ -392,6 +356,9 @@ namespace OpenRA.Server
inFlightFrames.Remove(f.Key); inFlightFrames.Remove(f.Key);
DispatchOrders(null, f.Key, new byte[] { 0xef }); DispatchOrders(null, f.Key, new byte[] { 0xef });
} }
if (conns.Count == 0) OnServerEmpty();
else SyncLobbyInfo();
} }
public static void Write(this Stream s, byte[] data) { s.Write(data, 0, data.Length); } public static void Write(this Stream s, byte[] data) { s.Write(data, 0, data.Length); }
@@ -400,5 +367,22 @@ namespace OpenRA.Server
{ {
return ts.Except(new[] { t }); return ts.Except(new[] { t });
} }
static void OnServerEmpty()
{
Console.WriteLine("Server emptied out; doing a bit of housekeeping to prepare for next game..");
inFlightFrames.Clear();
lobbyInfo = new Session();
}
static void SyncLobbyInfo()
{
var clientData = lobbyInfo.Clients.ToDictionary(
a => a.Index.ToString(),
a => FieldSaver.Save(a)).WriteToString();
DispatchOrders(null, 0,
new ServerOrder(0, "SyncInfo", clientData).Serialize());
}
} }
} }

View File

@@ -0,0 +1,54 @@
using System;
using System.IO;
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();
}
}
}

View File

@@ -8,25 +8,24 @@ namespace OpenRa.FileFormats
public class Session public class Session
{ {
public List<Client> Clients = new List<Client>(); public List<Client> Clients = new List<Client>();
public string Map = "scm12ea.ini"; // todo: add mods, mapname, global settings here
// public string[] Mods = { };
}
public enum ClientState public enum ClientState
{ {
NotReady, NotReady,
// Downloading, // Downloading,
// Uploading, // Uploading,
Ready Ready
} }
public class Client public class Client
{ {
public int Index; public int Index;
public int Palette; public int Palette;
public int Race; public int Race;
// public int SpawnPoint; // public int SpawnPoint;
public string Name; public string Name;
public ClientState State; public ClientState State;
}
} }
} }

View File

@@ -343,5 +343,21 @@ namespace OpenRa.Game
return Game.PathFinder.FindPath(search).Count != 0; return Game.PathFinder.FindPath(search).Count != 0;
} }
public static void SyncLobbyInfo(string data)
{
var ys = MiniYaml.FromString(data);
foreach (var y in ys)
{
int index;
if (!int.TryParse(y.Key, out index))
continue; // not a player.
var client = new Session.Client();
FieldLoader.Load(client, y.Value);
players[index].SyncFromLobby(client);
}
}
} }
} }

View File

@@ -49,18 +49,6 @@ namespace OpenRa.Game.Orders
Game.chat.AddLine(order.Player, "is now YOU."); Game.chat.AddLine(order.Player, "is now YOU.");
break; break;
} }
case "SetName":
{
Game.chat.AddLine(order.Player, "is now known as " + order.TargetString);
order.Player.PlayerName = order.TargetString;
break;
}
case "SetRace":
{
order.Player.Race = order.TargetString == "0" ? Race.Soviet : Race.Allies;
Game.chat.AddLine(order.Player, "is now playing {0}".F(order.Player.Race));
break;
}
case "SetLag": case "SetLag":
{ {
int lag = int.Parse(order.TargetString); int lag = int.Parse(order.TargetString);
@@ -74,13 +62,6 @@ namespace OpenRa.Game.Orders
Game.chat.AddLine(Color.White, "Server", "Order lag is now {0} frames.".F(lag)); Game.chat.AddLine(Color.White, "Server", "Order lag is now {0} frames.".F(lag));
break; break;
} }
case "SetPalette":
{
int palette = int.Parse(order.TargetString);
Game.chat.AddLine(order.Player, "has changed color to {0}".F(palette));
order.Player.Palette = (PaletteType) palette;
break;
}
case "StartGame": case "StartGame":
{ {
Game.chat.AddLine(Color.White, "Server", "The game has started."); Game.chat.AddLine(Color.White, "Server", "The game has started.");
@@ -93,6 +74,12 @@ namespace OpenRa.Game.Orders
Game.ChangeMap(order.TargetString); Game.ChangeMap(order.TargetString);
break; break;
} }
case "SyncInfo":
{
Game.chat.AddLine(Color.White, "Server", "Synchronizing lobby info..."); // temp
Game.SyncLobbyInfo(order.TargetString);
break;
}
default: default:
{ {

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using OpenRa.Game.GameRules; using OpenRa.Game.GameRules;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits; using OpenRa.Game.Traits;
using OpenRa.FileFormats;
namespace OpenRa.Game namespace OpenRa.Game
{ {
@@ -151,5 +152,28 @@ namespace OpenRa.Game
} }
} }
} }
public void SyncFromLobby(Session.Client client)
{
if (PlayerName != client.Name)
{
Game.chat.AddLine(this, "is now known as " + client.Name);
PlayerName = client.Name;
}
if (Race != (Race)client.Race)
{
Game.chat.AddLine(this, "is now playing {0}".F((Race)client.Race));
Race = (Race)client.Race;
}
if (Palette != (PaletteType)client.Palette)
{
Game.chat.AddLine(this, "has changed color to {0}".F((PaletteType)client.Palette));
Palette = (PaletteType)client.Palette;
}
// todo: IsReady tracking?
}
} }
} }