Allow spectators to be kicked after the game starts.

This commit is contained in:
Paul Chote
2020-02-26 23:27:33 +00:00
committed by abcdefg30
parent a7d5b7b8b0
commit 41657dd291
8 changed files with 139 additions and 7 deletions

View File

@@ -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;
} }
} }

View File

@@ -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));

View File

@@ -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;

View File

@@ -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);
} }
} }

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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