Core: Added basic support for Spectators

TODO: Someone modify the files for cnc (chrome / rules)
This commit is contained in:
geckosoft
2010-10-31 03:57:03 +01:00
parent b9c40ad3ce
commit 030bd4b28d
18 changed files with 418 additions and 186 deletions

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Network
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?
}

View File

@@ -78,7 +78,7 @@ namespace OpenRA
PlayerName = client.Name;
InternalName = pr.Name;
Country = world.GetCountries()
.FirstOrDefault(c => client != null && client.Country == c.Race)
.FirstOrDefault(c => client != null && client.Country == c.Race )
?? world.GetCountries().Random(world.SharedRandom);
ClientIndex = client.Index;

View File

@@ -40,6 +40,9 @@ namespace OpenRA.Server
const int MasterPingInterval = 60 * 3; // 3 minutes. server has a 5 minute TTL for games, so give ourselves a bit
// of leeway.
public static int MaxSpectators = 4; // How many spectators to allow // @todo Expose this as an option
static int lastPing = 0;
static bool isInternetServer;
static string masterServerUrl;
@@ -135,6 +138,12 @@ namespace OpenRA.Server
.Where(s => s != null)
.Select((s, i) => { s.Index = i; return s; })
.ToList();
// Generate slots for spectators
for (int i = 0; i < MaxSpectators; i++)
{
lobbyInfo.Slots.Add(new Session.Slot { Spectator = true, Index = lobbyInfo.Slots.Count(), MapPlayer = null, Bot = null});
}
}
/* lobby rework todo:
@@ -283,6 +292,8 @@ namespace OpenRA.Server
static void SyncClientToPlayerReference(Session.Client c, PlayerReference pr)
{
if (pr == null)
return;
if (pr.LockColor)
{
c.Color1 = pr.Color;
@@ -358,6 +369,13 @@ namespace OpenRA.Server
SyncLobbyInfo();
return true;
}},
{ "spectator",
s =>
{
// GetClient(conn).Slot = -1; /* observer */
SyncLobbyInfo();
return true;
}},
{ "team",
s =>
{
@@ -411,7 +429,7 @@ namespace OpenRA.Server
var cl = GetClient(conn);
cl.Slot = slot;
SyncClientToPlayerReference(cl, Map.Players[slotData.MapPlayer]);
SyncClientToPlayerReference(cl, slotData.MapPlayer != null ? Map.Players[slotData.MapPlayer] : null);
SyncLobbyInfo();
return true;

View File

@@ -158,7 +158,7 @@ namespace OpenRA.Traits
void DrawUnitPath(Actor self)
{
if (!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
if (self.World.LocalPlayer == null ||!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
var activity = self.GetCurrentActivity();
var mobile = self.TraitOrDefault<IMove>();

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Widgets.Delegates
{
public class LobbyDelegate : IWidgetDelegate
{
Widget Players, LocalPlayerTemplate, RemotePlayerTemplate, EmptySlotTemplate, EmptySlotTemplateHost;
Widget Players, LocalPlayerTemplate, RemotePlayerTemplate, EmptySlotTemplate, EmptySlotTemplateHost, EmptySpectatorSlotTemplateHost;
Dictionary<string, string> CountryNames;
string MapUid;
@@ -44,6 +44,7 @@ namespace OpenRA.Widgets.Delegates
RemotePlayerTemplate = Players.GetWidget("TEMPLATE_REMOTE");
EmptySlotTemplate = Players.GetWidget("TEMPLATE_EMPTY");
EmptySlotTemplateHost = Players.GetWidget("TEMPLATE_EMPTY_HOST");
EmptySpectatorSlotTemplateHost = Players.GetWidget("TEMPLATE_EMPTY_SPECTATOR");
var mapPreview = lobby.GetWidget<MapPreviewWidget>("LOBBY_MAP_PREVIEW");
mapPreview.Map = () => Map;
@@ -71,6 +72,7 @@ namespace OpenRA.Widgets.Delegates
};
CountryNames = Rules.Info["world"].Traits.WithInterface<OpenRA.Traits.CountryInfo>().ToDictionary(a => a.Race, a => a.Name);
CountryNames.Add("random", "Random");
var mapButton = lobby.GetWidget("CHANGEMAP_BUTTON");
@@ -232,25 +234,48 @@ namespace OpenRA.Widgets.Delegates
{
if (Game.IsHost)
{
template = EmptySlotTemplateHost.Clone();
var name = template.GetWidget<ButtonWidget>("NAME");
name.GetText = () => s.Closed ? "Closed" : (s.Bot == null)? "Open" : "Bot: " + s.Bot;
name.OnMouseUp = _ =>
if (slot.Spectator)
{
if (s.Closed)
template = EmptySlotTemplateHost.Clone();
var btn = template.GetWidget<ButtonWidget>("JOIN");
var name = template.GetWidget<ButtonWidget>("NAME");
btn.GetText = () => "Spectate in this slot";
name.GetText = () => s.Closed ? "Closed" : "Open";
name.OnMouseUp = _ =>
{
s.Bot = null;
orderManager.IssueOrder(Order.Command("slot_open " + s.Index));
}
else
{
if (s.Bot == null && Map.Players[s.MapPlayer].AllowBots)
orderManager.IssueOrder(Order.Command("slot_bot {0} HackyAI".F(s.Index)));
if (s.Closed)
{
orderManager.IssueOrder(Order.Command("slot_open " + s.Index));
}
else
{
orderManager.IssueOrder(Order.Command("slot_close " + s.Index));
}
return true;
};
}
return true;
};
}
else
{
template = EmptySlotTemplateHost.Clone();
var name = template.GetWidget<ButtonWidget>("NAME");
name.GetText = () => s.Closed ? "Closed" : (s.Bot == null) ? "Open" : "Bot: " + s.Bot;
name.OnMouseUp = _ =>
{
if (s.Closed)
{
s.Bot = null;
orderManager.IssueOrder(Order.Command("slot_open " + s.Index));
}
else
{
if (s.Bot == null && Map.Players[s.MapPlayer].AllowBots)
orderManager.IssueOrder(Order.Command("slot_bot {0} HackyAI".F(s.Index)));
else
orderManager.IssueOrder(Order.Command("slot_close " + s.Index));
}
return true;
};
}
}
else
{
@@ -330,6 +355,14 @@ namespace OpenRA.Widgets.Delegates
var status = template.GetWidget<CheckboxWidget>("STATUS");
status.Checked = () => c.State == Session.ClientState.Ready;
status.OnMouseDown = CycleReady;
Session.Slot slot1 = slot;
color.IsVisible = () => !slot1.Spectator;
colorBlock.IsVisible = () => !slot1.Spectator;
faction.IsVisible = () => !slot1.Spectator;
factionname.IsVisible = () => !slot1.Spectator;
factionflag.IsVisible = () => !slot1.Spectator;
team.IsVisible = () => !slot1.Spectator;
}
else
{

View File

@@ -39,7 +39,7 @@ namespace OpenRA
public void AddPlayer(Player p) { players[p.Index] = p; }
int localPlayerIndex;
int localPlayerIndex = -999;
public Player LocalPlayer
{
get { return players.ContainsKey(localPlayerIndex) ? players[localPlayerIndex] : null; }

View File

@@ -103,6 +103,7 @@ namespace OpenRA
public static bool IsVisible(this Actor a, Player byPlayer) /* must never be relied on in synced code! */
{
if (byPlayer == null) return true; // Observer
if (a.World.LocalPlayer != null && a.World.LocalPlayer.Shroud.Disabled)
return true;