Allow spectators to be kicked after the game starts.
This commit is contained in:
@@ -66,6 +66,6 @@ namespace OpenRA.Server
|
|||||||
// The protocol for server and world orders
|
// The protocol for server and world orders
|
||||||
// This applies after the handshake has completed, and is provided to support
|
// This applies after the handshake has completed, and is provided to support
|
||||||
// alternative server implementations that wish to support multiple versions in parallel
|
// alternative server implementations that wish to support multiple versions in parallel
|
||||||
public const int Orders = 9;
|
public const int Orders = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
|
|
||||||
public static bool ValidateCommand(S server, Connection conn, Session.Client client, string cmd)
|
public static bool ValidateCommand(S server, Connection conn, Session.Client client, string cmd)
|
||||||
{
|
{
|
||||||
|
// Kick command is always valid for the host
|
||||||
|
if (cmd.StartsWith("kick "))
|
||||||
|
return true;
|
||||||
|
|
||||||
if (server.State == ServerState.GameStarted)
|
if (server.State == ServerState.GameStarted)
|
||||||
{
|
{
|
||||||
server.SendOrderTo(conn, "Message", "Cannot change state when game started. ({0})".F(cmd));
|
server.SendOrderTo(conn, "Message", "Cannot change state when game started. ({0})".F(cmd));
|
||||||
@@ -584,6 +588,11 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
var kickClient = server.GetClient(kickConn);
|
var kickClient = server.GetClient(kickConn);
|
||||||
|
if (server.State == ServerState.GameStarted && !kickClient.IsObserver)
|
||||||
|
{
|
||||||
|
server.SendOrderTo(conn, "Message", "Only spectators can be kicked after the game has started.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Log.Write("server", "Kicking client {0}.", kickClientID);
|
Log.Write("server", "Kicking client {0}.", kickClientID);
|
||||||
server.SendMessage("{0} kicked {1} from the server.".F(client.Name, kickClient.Name));
|
server.SendMessage("{0} kicked {1} from the server.".F(client.Name, kickClient.Name));
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Mods.Common.Scripting;
|
using OpenRA.Mods.Common.Scripting;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
@@ -21,7 +22,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
class GameInfoLogic : ChromeLogic
|
class GameInfoLogic : ChromeLogic
|
||||||
{
|
{
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public GameInfoLogic(Widget widget, World world, IngameInfoPanel activePanel)
|
public GameInfoLogic(Widget widget, World world, IngameInfoPanel activePanel, Action<bool> hideMenu)
|
||||||
{
|
{
|
||||||
var lp = world.LocalPlayer;
|
var lp = world.LocalPlayer;
|
||||||
var numTabs = 0;
|
var numTabs = 0;
|
||||||
@@ -47,7 +48,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var objectivesPanel = widget.Get<ContainerWidget>("OBJECTIVES_PANEL");
|
var objectivesPanel = widget.Get<ContainerWidget>("OBJECTIVES_PANEL");
|
||||||
objectivesPanel.IsVisible = () => activePanel == IngameInfoPanel.Objectives;
|
objectivesPanel.IsVisible = () => activePanel == IngameInfoPanel.Objectives;
|
||||||
|
|
||||||
Game.LoadWidget(world, panel, objectivesPanel, new WidgetArgs());
|
Game.LoadWidget(world, panel, objectivesPanel, new WidgetArgs()
|
||||||
|
{
|
||||||
|
{ "hideMenu", hideMenu }
|
||||||
|
});
|
||||||
|
|
||||||
if (activePanel == IngameInfoPanel.AutoSelect)
|
if (activePanel == IngameInfoPanel.AutoSelect)
|
||||||
activePanel = IngameInfoPanel.Objectives;
|
activePanel = IngameInfoPanel.Objectives;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
@@ -22,7 +23,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
class GameInfoStatsLogic : ChromeLogic
|
class GameInfoStatsLogic : ChromeLogic
|
||||||
{
|
{
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer)
|
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer, Action<bool> hideMenu)
|
||||||
{
|
{
|
||||||
var player = world.LocalPlayer;
|
var player = world.LocalPlayer;
|
||||||
var playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST");
|
var playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST");
|
||||||
@@ -61,6 +62,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var teamTemplate = playerPanel.Get<ScrollItemWidget>("TEAM_TEMPLATE");
|
var teamTemplate = playerPanel.Get<ScrollItemWidget>("TEAM_TEMPLATE");
|
||||||
var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE");
|
var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE");
|
||||||
|
var spectatorTemplate = playerPanel.Get("SPECTATOR_TEMPLATE");
|
||||||
playerPanel.RemoveChildren();
|
playerPanel.RemoveChildren();
|
||||||
|
|
||||||
var teams = world.Players.Where(p => !p.NonCombatant && p.Playable)
|
var teams = world.Players.Where(p => !p.NonCombatant && p.Playable)
|
||||||
@@ -137,7 +139,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
foreach (var client in spectators)
|
foreach (var client in spectators)
|
||||||
{
|
{
|
||||||
var item = playerTemplate.Clone();
|
var item = spectatorTemplate.Clone();
|
||||||
LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer);
|
LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer);
|
||||||
|
|
||||||
var nameLabel = item.Get<LabelWidget>("NAME");
|
var nameLabel = item.Get<LabelWidget>("NAME");
|
||||||
@@ -153,7 +155,23 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
return name.Update(Pair.New(client.Name, suffix));
|
return name.Update(Pair.New(client.Name, suffix));
|
||||||
};
|
};
|
||||||
|
|
||||||
item.Get<ImageWidget>("FACTIONFLAG").IsVisible = () => false;
|
var kickButton = item.Get<ButtonWidget>("KICK");
|
||||||
|
kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index && client.State != Session.ClientState.Disconnected;
|
||||||
|
kickButton.OnClick = () =>
|
||||||
|
{
|
||||||
|
hideMenu(true);
|
||||||
|
ConfirmationDialogs.ButtonPrompt(
|
||||||
|
title: "Kick {0}?".F(client.Name),
|
||||||
|
text: "They will not be able to rejoin this game.",
|
||||||
|
onConfirm: () =>
|
||||||
|
{
|
||||||
|
orderManager.IssueOrder(Order.Command("kick {0} {1}".F(client.Index, false)));
|
||||||
|
hideMenu(false);
|
||||||
|
},
|
||||||
|
onCancel: () => hideMenu(false),
|
||||||
|
confirmText: "Kick");
|
||||||
|
};
|
||||||
|
|
||||||
playerPanel.AddChild(item);
|
playerPanel.AddChild(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,9 +104,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var panelRoot = widget.GetOrNull("PANEL_ROOT");
|
var panelRoot = widget.GetOrNull("PANEL_ROOT");
|
||||||
if (panelRoot != null && world.Type != WorldType.Editor)
|
if (panelRoot != null && world.Type != WorldType.Editor)
|
||||||
{
|
{
|
||||||
|
Action<bool> requestHideMenu = h => hideMenu = h;
|
||||||
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
|
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
|
||||||
{
|
{
|
||||||
{ "activePanel", activePanel }
|
{ "activePanel", activePanel },
|
||||||
|
{ "hideMenu", requestHideMenu }
|
||||||
});
|
});
|
||||||
|
|
||||||
gameInfoPanel.IsVisible = () => !hideMenu;
|
gameInfoPanel.IsVisible = () => !hideMenu;
|
||||||
|
|||||||
@@ -120,3 +120,36 @@ Container@SKIRMISH_STATS:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Align: Right
|
Align: Right
|
||||||
Shadow: True
|
Shadow: True
|
||||||
|
Container@SPECTATOR_TEMPLATE:
|
||||||
|
Width: PARENT_RIGHT - 27
|
||||||
|
Height: 25
|
||||||
|
X: 2
|
||||||
|
Children:
|
||||||
|
Image@PROFILE:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
X: 8
|
||||||
|
Y: 4
|
||||||
|
Visible: false
|
||||||
|
ClientTooltipRegion@PROFILE_TOOLTIP:
|
||||||
|
X: 8
|
||||||
|
Y: 4
|
||||||
|
Width: 16
|
||||||
|
Height: 16
|
||||||
|
Visible: false
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Template: ANONYMOUS_PLAYER_TOOLTIP
|
||||||
|
Label@NAME:
|
||||||
|
X: 29
|
||||||
|
Width: 166
|
||||||
|
Height: 25
|
||||||
|
Shadow: True
|
||||||
|
Button@KICK:
|
||||||
|
X: 195
|
||||||
|
Width: 24
|
||||||
|
Height: 25
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 6
|
||||||
|
Y: 8
|
||||||
|
|||||||
@@ -118,3 +118,36 @@ Container@SKIRMISH_STATS:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Align: Right
|
Align: Right
|
||||||
Shadow: True
|
Shadow: True
|
||||||
|
Container@SPECTATOR_TEMPLATE:
|
||||||
|
Width: PARENT_RIGHT - 27
|
||||||
|
Height: 25
|
||||||
|
X: 2
|
||||||
|
Children:
|
||||||
|
Image@PROFILE:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
X: 8
|
||||||
|
Y: 4
|
||||||
|
Visible: false
|
||||||
|
ClientTooltipRegion@PROFILE_TOOLTIP:
|
||||||
|
X: 8
|
||||||
|
Y: 4
|
||||||
|
Width: 16
|
||||||
|
Height: 16
|
||||||
|
Visible: false
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Template: ANONYMOUS_PLAYER_TOOLTIP
|
||||||
|
Label@NAME:
|
||||||
|
X: 29
|
||||||
|
Width: 166
|
||||||
|
Height: 25
|
||||||
|
Shadow: True
|
||||||
|
Button@KICK:
|
||||||
|
X: 195
|
||||||
|
Width: 24
|
||||||
|
Height: 25
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 6
|
||||||
|
Y: 8
|
||||||
|
|||||||
@@ -119,3 +119,36 @@ Container@SKIRMISH_STATS:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Align: Right
|
Align: Right
|
||||||
Shadow: True
|
Shadow: True
|
||||||
|
Container@SPECTATOR_TEMPLATE:
|
||||||
|
Width: PARENT_RIGHT - 27
|
||||||
|
Height: 25
|
||||||
|
X: 2
|
||||||
|
Children:
|
||||||
|
Image@PROFILE:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
X: 8
|
||||||
|
Y: 4
|
||||||
|
Visible: false
|
||||||
|
ClientTooltipRegion@PROFILE_TOOLTIP:
|
||||||
|
X: 8
|
||||||
|
Y: 4
|
||||||
|
Width: 16
|
||||||
|
Height: 16
|
||||||
|
Visible: false
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Template: ANONYMOUS_PLAYER_TOOLTIP
|
||||||
|
Label@NAME:
|
||||||
|
X: 29
|
||||||
|
Width: 166
|
||||||
|
Height: 25
|
||||||
|
Shadow: True
|
||||||
|
Button@KICK:
|
||||||
|
X: 195
|
||||||
|
Width: 24
|
||||||
|
Height: 25
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 6
|
||||||
|
Y: 8
|
||||||
|
|||||||
Reference in New Issue
Block a user