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
|
||||
// This applies after the handshake has completed, and is provided to support
|
||||
// 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)
|
||||
{
|
||||
// Kick command is always valid for the host
|
||||
if (cmd.StartsWith("kick "))
|
||||
return true;
|
||||
|
||||
if (server.State == ServerState.GameStarted)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
server.SendMessage("{0} kicked {1} from the server.".F(client.Name, kickClient.Name));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Scripting;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
@@ -21,7 +22,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
class GameInfoLogic : ChromeLogic
|
||||
{
|
||||
[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 numTabs = 0;
|
||||
@@ -47,7 +48,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var objectivesPanel = widget.Get<ContainerWidget>("OBJECTIVES_PANEL");
|
||||
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)
|
||||
activePanel = IngameInfoPanel.Objectives;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
@@ -22,7 +23,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
class GameInfoStatsLogic : ChromeLogic
|
||||
{
|
||||
[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 playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST");
|
||||
@@ -61,6 +62,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var teamTemplate = playerPanel.Get<ScrollItemWidget>("TEAM_TEMPLATE");
|
||||
var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE");
|
||||
var spectatorTemplate = playerPanel.Get("SPECTATOR_TEMPLATE");
|
||||
playerPanel.RemoveChildren();
|
||||
|
||||
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)
|
||||
{
|
||||
var item = playerTemplate.Clone();
|
||||
var item = spectatorTemplate.Clone();
|
||||
LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer);
|
||||
|
||||
var nameLabel = item.Get<LabelWidget>("NAME");
|
||||
@@ -153,7 +155,23 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var panelRoot = widget.GetOrNull("PANEL_ROOT");
|
||||
if (panelRoot != null && world.Type != WorldType.Editor)
|
||||
{
|
||||
Action<bool> requestHideMenu = h => hideMenu = h;
|
||||
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
|
||||
{
|
||||
{ "activePanel", activePanel }
|
||||
{ "activePanel", activePanel },
|
||||
{ "hideMenu", requestHideMenu }
|
||||
});
|
||||
|
||||
gameInfoPanel.IsVisible = () => !hideMenu;
|
||||
|
||||
@@ -120,3 +120,36 @@ Container@SKIRMISH_STATS:
|
||||
Height: 25
|
||||
Align: Right
|
||||
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
|
||||
Align: Right
|
||||
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
|
||||
Align: Right
|
||||
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