Allow kicking dead players
This commit is contained in:
committed by
Matthias Mailänder
parent
c4bd9fb7aa
commit
bf00577d33
@@ -791,9 +791,12 @@ namespace OpenRA.Server
|
|||||||
|
|
||||||
// Make sure the written file is not valid
|
// Make sure the written file is not valid
|
||||||
// TODO: storing a serverside replay on desync would be extremely useful
|
// TODO: storing a serverside replay on desync would be extremely useful
|
||||||
recorder.Metadata = null;
|
if (recorder != null)
|
||||||
|
{
|
||||||
|
recorder.Metadata = null;
|
||||||
|
|
||||||
recorder.Dispose();
|
recorder.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// Stop the recording
|
// Stop the recording
|
||||||
recorder = null;
|
recorder = null;
|
||||||
@@ -856,17 +859,14 @@ namespace OpenRA.Server
|
|||||||
|
|
||||||
void RecordOrder(int frame, byte[] data, int from)
|
void RecordOrder(int frame, byte[] data, int from)
|
||||||
{
|
{
|
||||||
if (recorder != null)
|
recorder?.ReceiveFrame(from, frame, data);
|
||||||
{
|
|
||||||
recorder.ReceiveFrame(from, frame, data);
|
|
||||||
|
|
||||||
if (data.Length > 0 && data[0] == (byte)OrderType.SyncHash)
|
if (data.Length > 0 && data[0] == (byte)OrderType.SyncHash)
|
||||||
{
|
{
|
||||||
if (data.Length == Order.SyncHashOrderLength)
|
if (data.Length == Order.SyncHashOrderLength)
|
||||||
HandleSyncOrder(frame, data);
|
HandleSyncOrder(frame, data);
|
||||||
else
|
else
|
||||||
Log.Write("server", $"Dropped sync order with length {data.Length} from client {from}. Expected length {Order.SyncHashOrderLength}.");
|
Log.Write("server", $"Dropped sync order with length {data.Length} from client {from}. Expected length {Order.SyncHashOrderLength}.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,6 +1163,16 @@ namespace OpenRA.Server
|
|||||||
return LobbyInfo.ClientWithIndex(conn.PlayerIndex);
|
return LobbyInfo.ClientWithIndex(conn.PlayerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <Remarks> Does not check if client is admin </Remarks>
|
||||||
|
public bool CanKickClient(Session.Client kickee)
|
||||||
|
{
|
||||||
|
if (State != ServerState.GameStarted || kickee.IsObserver)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var player = worldPlayers.FirstOrDefault(p => p?.ClientIndex == kickee.Index);
|
||||||
|
return player != null && player.Outcome != WinState.Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
public void DropClient(Connection toDrop)
|
public void DropClient(Connection toDrop)
|
||||||
{
|
{
|
||||||
lock (LobbyInfo)
|
lock (LobbyInfo)
|
||||||
@@ -1323,24 +1333,22 @@ namespace OpenRA.Server
|
|||||||
foreach (var cmpi in Map.WorldActorInfo.TraitInfos<ICreatePlayersInfo>())
|
foreach (var cmpi in Map.WorldActorInfo.TraitInfos<ICreatePlayersInfo>())
|
||||||
cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom);
|
cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom);
|
||||||
|
|
||||||
if (recorder != null)
|
gameInfo = new GameInformation
|
||||||
{
|
{
|
||||||
gameInfo = new GameInformation
|
Mod = Game.ModData.Manifest.Id,
|
||||||
{
|
Version = Game.ModData.Manifest.Metadata.Version,
|
||||||
Mod = Game.ModData.Manifest.Id,
|
MapUid = Map.Uid,
|
||||||
Version = Game.ModData.Manifest.Metadata.Version,
|
MapTitle = Map.Title,
|
||||||
MapUid = Map.Uid,
|
StartTimeUtc = DateTime.UtcNow,
|
||||||
MapTitle = Map.Title,
|
};
|
||||||
StartTimeUtc = DateTime.UtcNow,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Replay metadata should only include the playable players
|
// Replay metadata should only include the playable players
|
||||||
foreach (var p in worldPlayers)
|
foreach (var p in worldPlayers)
|
||||||
if (p != null)
|
if (p != null)
|
||||||
gameInfo.Players.Add(p);
|
gameInfo.Players.Add(p);
|
||||||
|
|
||||||
|
if (recorder != null)
|
||||||
recorder.Metadata = new ReplayMetadata(gameInfo);
|
recorder.Metadata = new ReplayMetadata(gameInfo);
|
||||||
}
|
|
||||||
|
|
||||||
SyncLobbyInfo();
|
SyncLobbyInfo();
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
const string KickNone = "notification-kick-none";
|
const string KickNone = "notification-kick-none";
|
||||||
|
|
||||||
|
[TranslationReference]
|
||||||
|
const string NoKickSelf = "notification-kick-self";
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
const string NoKickGameStarted = "notification-no-kick-game-started";
|
const string NoKickGameStarted = "notification-no-kick-game-started";
|
||||||
|
|
||||||
@@ -794,7 +797,13 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
var kickClient = server.GetClient(kickConn);
|
var kickClient = server.GetClient(kickConn);
|
||||||
if (server.State == ServerState.GameStarted && !kickClient.IsObserver)
|
if (client == kickClient)
|
||||||
|
{
|
||||||
|
server.SendLocalizedMessageTo(conn, NoKickSelf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!server.CanKickClient(kickClient))
|
||||||
{
|
{
|
||||||
server.SendLocalizedMessageTo(conn, NoKickGameStarted);
|
server.SendLocalizedMessageTo(conn, NoKickGameStarted);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -114,6 +114,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
||||||
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0));
|
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0));
|
||||||
|
|
||||||
|
void KickAction(Session.Client client)
|
||||||
|
{
|
||||||
|
hideMenu(true);
|
||||||
|
ConfirmationDialogs.ButtonPrompt(modData,
|
||||||
|
title: KickTitle,
|
||||||
|
titleArguments: Translation.Arguments("player", client.Name),
|
||||||
|
text: KickPrompt,
|
||||||
|
onConfirm: () =>
|
||||||
|
{
|
||||||
|
orderManager.IssueOrder(Order.Command($"kick {client.Index} {false}"));
|
||||||
|
hideMenu(false);
|
||||||
|
},
|
||||||
|
onCancel: () => hideMenu(false),
|
||||||
|
confirmText: KickAccept);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var t in teams)
|
foreach (var t in teams)
|
||||||
{
|
{
|
||||||
if (teams.Count() > 1)
|
if (teams.Count() > 1)
|
||||||
@@ -165,6 +181,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
muteCheckbox.IsVisible = () => !pp.IsBot && client.State != Session.ClientState.Disconnected && pp.ClientIndex != orderManager.LocalClient?.Index;
|
muteCheckbox.IsVisible = () => !pp.IsBot && client.State != Session.ClientState.Disconnected && pp.ClientIndex != orderManager.LocalClient?.Index;
|
||||||
muteCheckbox.GetTooltipText = () => muteCheckbox.IsChecked() ? unmuteTooltip : muteTooltip;
|
muteCheckbox.GetTooltipText = () => muteCheckbox.IsChecked() ? unmuteTooltip : muteTooltip;
|
||||||
|
|
||||||
|
var kickButton = item.Get<ButtonWidget>("KICK");
|
||||||
|
kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient?.Index && client.State != Session.ClientState.Disconnected && pp.WinState != WinState.Undefined && !pp.IsBot;
|
||||||
|
kickButton.OnClick = () => KickAction(client);
|
||||||
|
|
||||||
playerPanel.AddChild(item);
|
playerPanel.AddChild(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,21 +218,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var kickButton = item.Get<ButtonWidget>("KICK");
|
var kickButton = item.Get<ButtonWidget>("KICK");
|
||||||
kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient?.Index && client.State != Session.ClientState.Disconnected;
|
kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient?.Index && client.State != Session.ClientState.Disconnected;
|
||||||
kickButton.OnClick = () =>
|
kickButton.OnClick = () => KickAction(client);
|
||||||
{
|
|
||||||
hideMenu(true);
|
|
||||||
ConfirmationDialogs.ButtonPrompt(modData,
|
|
||||||
title: KickTitle,
|
|
||||||
titleArguments: Translation.Arguments("player", client.Name),
|
|
||||||
text: KickPrompt,
|
|
||||||
onConfirm: () =>
|
|
||||||
{
|
|
||||||
orderManager.IssueOrder(Order.Command($"kick {client.Index} {false}"));
|
|
||||||
hideMenu(false);
|
|
||||||
},
|
|
||||||
onCancel: () => hideMenu(false),
|
|
||||||
confirmText: KickAccept);
|
|
||||||
};
|
|
||||||
|
|
||||||
var muteCheckbox = item.Get<CheckboxWidget>("MUTE");
|
var muteCheckbox = item.Get<CheckboxWidget>("MUTE");
|
||||||
muteCheckbox.IsChecked = () => TextNotificationsManager.MutedPlayers[client.Index];
|
muteCheckbox.IsChecked = () => TextNotificationsManager.MutedPlayers[client.Index];
|
||||||
|
|||||||
@@ -133,6 +133,19 @@ Container@SKIRMISH_STATS:
|
|||||||
Checkmark: mute
|
Checkmark: mute
|
||||||
Background: checkbox-toggle
|
Background: checkbox-toggle
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Button@KICK:
|
||||||
|
X: 485
|
||||||
|
Width: 25
|
||||||
|
Height: 25
|
||||||
|
Background: checkbox-toggle
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipText: Kick this player
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 7
|
||||||
|
Y: 7
|
||||||
Container@SPECTATOR_TEMPLATE:
|
Container@SPECTATOR_TEMPLATE:
|
||||||
Width: PARENT_RIGHT - 27
|
Width: PARENT_RIGHT - 27
|
||||||
Height: 25
|
Height: 25
|
||||||
|
|||||||
@@ -130,6 +130,19 @@ Container@SKIRMISH_STATS:
|
|||||||
Checkmark: mute
|
Checkmark: mute
|
||||||
Background: checkbox-toggle
|
Background: checkbox-toggle
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Button@KICK:
|
||||||
|
X: 485
|
||||||
|
Width: 25
|
||||||
|
Height: 25
|
||||||
|
Background: checkbox-toggle
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipText: Kick this player
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 7
|
||||||
|
Y: 7
|
||||||
Container@SPECTATOR_TEMPLATE:
|
Container@SPECTATOR_TEMPLATE:
|
||||||
Width: PARENT_RIGHT - 26
|
Width: PARENT_RIGHT - 26
|
||||||
Height: 25
|
Height: 25
|
||||||
|
|||||||
@@ -64,8 +64,9 @@ notification-invalid-configuration-command = Invalid configuration command.
|
|||||||
notification-admin-option = Only the host can set that option.
|
notification-admin-option = Only the host can set that option.
|
||||||
notification-error-number-teams = Number of teams could not be parsed: { $raw }
|
notification-error-number-teams = Number of teams could not be parsed: { $raw }
|
||||||
notification-admin-kick = Only the host can kick players.
|
notification-admin-kick = Only the host can kick players.
|
||||||
|
notification-kick-self = The host is not allowed to kick themselves.
|
||||||
notification-kick-none = No-one in that slot.
|
notification-kick-none = No-one in that slot.
|
||||||
notification-no-kick-game-started = Only spectators can be kicked after the game has started.
|
notification-no-kick-game-started = Only spectators and defeated players can be kicked after the game has started.
|
||||||
notification-admin-clear-spawn = Only admins can clear spawn points.
|
notification-admin-clear-spawn = Only admins can clear spawn points.
|
||||||
notification-spawn-occupied = You cannot occupy the same spawn point as another player.
|
notification-spawn-occupied = You cannot occupy the same spawn point as another player.
|
||||||
notification-spawn-locked = The spawn point is locked to another player slot.
|
notification-spawn-locked = The spawn point is locked to another player slot.
|
||||||
|
|||||||
@@ -132,6 +132,19 @@ Container@SKIRMISH_STATS:
|
|||||||
Checkmark: mute
|
Checkmark: mute
|
||||||
Background: checkbox-toggle
|
Background: checkbox-toggle
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Button@KICK:
|
||||||
|
X: 485
|
||||||
|
Width: 25
|
||||||
|
Height: 25
|
||||||
|
Background: checkbox-toggle
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipText: Kick this player
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 7
|
||||||
|
Y: 7
|
||||||
Container@SPECTATOR_TEMPLATE:
|
Container@SPECTATOR_TEMPLATE:
|
||||||
Width: PARENT_RIGHT - 27
|
Width: PARENT_RIGHT - 27
|
||||||
Height: 25
|
Height: 25
|
||||||
|
|||||||
Reference in New Issue
Block a user