Administration: Ahelp tabs (#5965)
This commit is contained in:
@@ -1,12 +1,18 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Administration.Managers;
|
||||||
using Content.Client.Administration.UI;
|
using Content.Client.Administration.UI;
|
||||||
|
using Content.Client.Administration.UI.CustomControls;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
@@ -16,18 +22,21 @@ namespace Content.Client.Administration
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class BwoinkSystem : SharedBwoinkSystem
|
public class BwoinkSystem : SharedBwoinkSystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IClyde _clyde = default!;
|
[Dependency] private readonly IClyde _clyde = default!;
|
||||||
|
|
||||||
private readonly Dictionary<NetUserId, BwoinkWindow> _activeWindowMap = new();
|
private BwoinkWindow? _adminWindow;
|
||||||
|
private DefaultWindow? _plainWindow;
|
||||||
|
private readonly Dictionary<NetUserId, BwoinkPanel> _activePanelMap = new();
|
||||||
|
|
||||||
protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs)
|
protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
base.OnBwoinkTextMessage(message, eventArgs);
|
base.OnBwoinkTextMessage(message, eventArgs);
|
||||||
LogBwoink(message);
|
LogBwoink(message);
|
||||||
// Actual line
|
// Actual line
|
||||||
var window = EnsureWindow(message.ChannelId);
|
var window = EnsurePanel(message.ChannelId);
|
||||||
window.ReceiveLine(message.Text);
|
window.ReceiveLine($"[color=gray]{message.SentAt.ToShortTimeString()}[/color] {message.Text}");
|
||||||
// Play a sound if we didn't send it
|
// Play a sound if we didn't send it
|
||||||
var localPlayer = _playerManager.LocalPlayer;
|
var localPlayer = _playerManager.LocalPlayer;
|
||||||
if (localPlayer?.UserId != message.TrueSender)
|
if (localPlayer?.UserId != message.TrueSender)
|
||||||
@@ -35,27 +44,67 @@ namespace Content.Client.Administration
|
|||||||
SoundSystem.Play(Filter.Local(), "/Audio/Effects/adminhelp.ogg");
|
SoundSystem.Play(Filter.Local(), "/Audio/Effects/adminhelp.ogg");
|
||||||
_clyde.RequestWindowAttention();
|
_clyde.RequestWindowAttention();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_adminWindow?.OnBwoink(message.ChannelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BwoinkWindow EnsureWindow(NetUserId channelId)
|
public bool TryGetChannel(NetUserId ch, [NotNullWhen(true)] out BwoinkPanel? bp) => _activePanelMap.TryGetValue(ch, out bp);
|
||||||
|
|
||||||
|
private BwoinkPanel EnsureAdmin(NetUserId channelId)
|
||||||
{
|
{
|
||||||
if (!_activeWindowMap.TryGetValue(channelId, out var existingWindow))
|
_adminWindow ??= new BwoinkWindow(this);
|
||||||
|
|
||||||
|
if (!_activePanelMap.TryGetValue(channelId, out var existingPanel))
|
||||||
{
|
{
|
||||||
_activeWindowMap[channelId] = existingWindow = new BwoinkWindow(channelId,
|
_activePanelMap[channelId] = existingPanel = new BwoinkPanel(this, channelId);
|
||||||
_playerManager.SessionsDict.TryGetValue(channelId, out var otherSession)
|
existingPanel.Visible = false;
|
||||||
? otherSession.Name
|
if (!_adminWindow.BwoinkArea.Children.Contains(existingPanel))
|
||||||
: channelId.ToString());
|
_adminWindow.BwoinkArea.AddChild(existingPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
existingWindow.Open();
|
_adminWindow.Open();
|
||||||
return existingWindow;
|
|
||||||
|
return existingPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureWindowForLocalPlayer()
|
private BwoinkPanel EnsurePlain(NetUserId channelId)
|
||||||
|
{
|
||||||
|
BwoinkPanel bp;
|
||||||
|
if (_plainWindow is null)
|
||||||
|
{
|
||||||
|
bp = new BwoinkPanel(this, channelId);
|
||||||
|
_plainWindow = new DefaultWindow()
|
||||||
|
{
|
||||||
|
TitleClass="windowTitleAlert",
|
||||||
|
HeaderClass="windowHeaderAlert",
|
||||||
|
Title=Loc.GetString("bwoink-user-title"),
|
||||||
|
SetSize=(400, 200),
|
||||||
|
};
|
||||||
|
|
||||||
|
_plainWindow.Contents.AddChild(bp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bp = (BwoinkPanel) _plainWindow.Contents.GetChild(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_plainWindow.Open();
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BwoinkPanel EnsurePanel(NetUserId channelId)
|
||||||
|
{
|
||||||
|
if (_adminManager.HasFlag(AdminFlags.Adminhelp))
|
||||||
|
return EnsureAdmin(channelId);
|
||||||
|
|
||||||
|
return EnsurePlain(channelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsurePanelForLocalPlayer()
|
||||||
{
|
{
|
||||||
var localPlayer = _playerManager.LocalPlayer;
|
var localPlayer = _playerManager.LocalPlayer;
|
||||||
if (localPlayer != null)
|
if (localPlayer != null)
|
||||||
EnsureWindow(localPlayer.UserId);
|
EnsurePanel(localPlayer.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Send(NetUserId channelId, string text)
|
public void Send(NetUserId channelId, string text)
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
<SS14Window
|
<DefaultWindow
|
||||||
xmlns="https://spacestation14.io"
|
xmlns="https://spacestation14.io"
|
||||||
|
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
SetSize="400 200"
|
SetSize="400 200"
|
||||||
HeaderClass="windowHeaderAlert"
|
HeaderClass="windowHeaderAlert"
|
||||||
TitleClass="windowTitleAlert"
|
TitleClass="windowTitleAlert"
|
||||||
>
|
Title="{Loc 'bwoink-user-title'}" >
|
||||||
<BoxContainer Orientation="Vertical">
|
<SplitContainer Orientation="Horizontal">
|
||||||
<OutputPanel Name="TextOutput" VerticalExpand="true" />
|
<cc:PlayerListControl Access="Public" Name="ChannelSelector" HorizontalExpand="True" SizeFlagsStretchRatio="1" />
|
||||||
<HistoryLineEdit Name="SenderLineEdit" />
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="2">
|
||||||
</BoxContainer>
|
<BoxContainer Access="Public" Name="BwoinkArea" VerticalExpand="True" />
|
||||||
</SS14Window>
|
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
|
<Button Visible="False" Name="Kick" Text="{Loc 'admin-player-actions-kick'}" />
|
||||||
|
<Button Visible="False" Name="Ban" Text="{Loc 'admin-player-actions-ban'}" />
|
||||||
|
<Button Visible="False" Name="Respawn" Text="{Loc 'admin-player-actions-respawn'}" />
|
||||||
|
<Button Visible="False" Name="Teleport" Text="{Loc 'admin-player-actions-teleport'}" />
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</SplitContainer>
|
||||||
|
</DefaultWindow>
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Administration.Managers;
|
||||||
|
using Content.Client.Administration.UI.CustomControls;
|
||||||
|
using Content.Client.Administration.UI.Tabs.AdminTab;
|
||||||
|
using Content.Shared.Administration;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Console;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Client.Administration.UI
|
namespace Content.Client.Administration.UI
|
||||||
{
|
{
|
||||||
@@ -15,40 +19,140 @@ namespace Content.Client.Administration.UI
|
|||||||
/// This window connects to a BwoinkSystem channel. BwoinkSystem manages the rest.
|
/// This window connects to a BwoinkSystem channel. BwoinkSystem manages the rest.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public partial class BwoinkWindow : SS14Window
|
public partial class BwoinkWindow : DefaultWindow
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IEntitySystemManager _systemManager = default!;
|
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IClientConsoleHost _console = default!;
|
||||||
|
|
||||||
private readonly NetUserId _channelId;
|
private readonly BwoinkSystem _bwoinkSystem;
|
||||||
|
private PlayerInfo? _currentPlayer = default;
|
||||||
|
|
||||||
public BwoinkWindow(NetUserId userId, string channelName)
|
public BwoinkWindow(BwoinkSystem bs)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
_bwoinkSystem = bs;
|
||||||
|
|
||||||
_channelId = userId;
|
_adminManager.AdminStatusUpdated += () => FixButtons();
|
||||||
Title = (_playerManager.LocalPlayer?.UserId == _channelId) ? "Admin Message" : channelName;
|
FixButtons();
|
||||||
|
|
||||||
SenderLineEdit.OnTextEntered += Input_OnTextEntered;
|
ChannelSelector.OnSelectionChanged += sel =>
|
||||||
|
{
|
||||||
|
_currentPlayer = sel;
|
||||||
|
if (sel is not null)
|
||||||
|
{
|
||||||
|
SwitchToChannel(sel.SessionId);
|
||||||
|
Title = $"{sel.CharacterName} / {sel.Username}";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var li in ChannelSelector.PlayerItemList)
|
||||||
|
li.Text = FormatTabTitle(li);
|
||||||
|
};
|
||||||
|
|
||||||
|
ChannelSelector.DecoratePlayer += (PlayerInfo pl, ItemList.Item li) =>
|
||||||
|
{
|
||||||
|
li.Text = FormatTabTitle(li, pl);
|
||||||
|
};
|
||||||
|
|
||||||
|
ChannelSelector.SortKey = (PlayerInfo pl) =>
|
||||||
|
{
|
||||||
|
if (_bwoinkSystem.TryGetChannel(pl.SessionId, out var ch))
|
||||||
|
{
|
||||||
|
return ch.Unread;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ew
|
||||||
|
Ban.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
var bw = new BanWindow();
|
||||||
|
bw.OnPlayerSelectionChanged(_currentPlayer);
|
||||||
|
bw.Open();
|
||||||
|
};
|
||||||
|
|
||||||
|
Kick.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
// TODO: Reason field
|
||||||
|
if (_currentPlayer is not null)
|
||||||
|
_console.ExecuteCommand($"kick \"{_currentPlayer.Username}\"");
|
||||||
|
};
|
||||||
|
|
||||||
|
Teleport.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
if (_currentPlayer is not null)
|
||||||
|
_console.ExecuteCommand($"tpto \"{_currentPlayer.Username}\"");
|
||||||
|
};
|
||||||
|
|
||||||
|
Respawn.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
if (_currentPlayer is not null)
|
||||||
|
_console.ExecuteCommand($"respawn \"{_currentPlayer.Username}\"");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Input_OnTextEntered(LineEdit.LineEditEventArgs args)
|
public void OnBwoink(NetUserId channel)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(args.Text))
|
var open = IsOpen;
|
||||||
|
Open();
|
||||||
|
|
||||||
|
ChannelSelector.Refresh();
|
||||||
|
|
||||||
|
if (!open)
|
||||||
{
|
{
|
||||||
var bwoink = _systemManager.GetEntitySystem<BwoinkSystem>();
|
var pi = ChannelSelector
|
||||||
bwoink.Send(_channelId, args.Text);
|
.PlayerItemList
|
||||||
|
.FirstOrDefault(i => ((PlayerInfo) i.Metadata!).SessionId == channel);
|
||||||
|
|
||||||
|
if (pi is not null)
|
||||||
|
pi.Selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixButtons()
|
||||||
|
{
|
||||||
|
Ban.Visible = _adminManager.HasFlag(AdminFlags.Ban);
|
||||||
|
Ban.Disabled = !Ban.Visible;
|
||||||
|
|
||||||
|
Kick.Visible = _adminManager.CanCommand("kick");
|
||||||
|
Kick.Disabled = !Kick.Visible;
|
||||||
|
|
||||||
|
Teleport.Visible = _adminManager.CanCommand("tpto");
|
||||||
|
Teleport.Disabled = !Teleport.Visible;
|
||||||
|
|
||||||
|
Respawn.Visible = _adminManager.CanCommand("respawn");
|
||||||
|
Respawn.Disabled = !Respawn.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatTabTitle(ItemList.Item li, PlayerInfo? pl = default)
|
||||||
|
{
|
||||||
|
pl ??= (PlayerInfo) li.Metadata!;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(pl.Connected ? '●' : '○');
|
||||||
|
sb.Append(' ');
|
||||||
|
if (_bwoinkSystem.TryGetChannel(pl.SessionId, out var panel) && panel.Unread > 0)
|
||||||
|
{
|
||||||
|
if (panel.Unread < 11)
|
||||||
|
sb.Append(new Rune('➀' + (panel.Unread-1)));
|
||||||
|
else
|
||||||
|
sb.Append(new Rune(0x2639)); // ☹
|
||||||
|
sb.Append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
SenderLineEdit.Clear();
|
if (pl.Antag)
|
||||||
|
sb.Append(new Rune(0x1F5E1)); // 🗡
|
||||||
|
|
||||||
|
sb.AppendFormat("\"{0}\"", pl.CharacterName)
|
||||||
|
.Append(' ')
|
||||||
|
.Append(pl.Username);
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReceiveLine(string text)
|
public void SwitchToChannel(NetUserId ch)
|
||||||
{
|
{
|
||||||
var formatted = new FormattedMessage(1);
|
foreach (var bw in BwoinkArea.Children)
|
||||||
formatted.AddMarkup(text);
|
bw.Visible = (bw as BwoinkPanel)?.ChannelId == ch;
|
||||||
TextOutput.AddMessage(formatted);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<BoxContainer
|
||||||
|
xmlns="https://spacestation14.io"
|
||||||
|
Orientation="Vertical"
|
||||||
|
HorizontalExpand="true">
|
||||||
|
<OutputPanel Name="TextOutput" VerticalExpand="true" />
|
||||||
|
<HistoryLineEdit Name="SenderLineEdit" />
|
||||||
|
</BoxContainer>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#nullable enable
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.Administration.UI.CustomControls
|
||||||
|
{
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public partial class BwoinkPanel : BoxContainer
|
||||||
|
{
|
||||||
|
private readonly BwoinkSystem _bwoinkSystem;
|
||||||
|
public readonly NetUserId ChannelId;
|
||||||
|
|
||||||
|
public int Unread { get; private set; } = 0;
|
||||||
|
|
||||||
|
public BwoinkPanel(BwoinkSystem bwoinkSys, NetUserId userId)
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
_bwoinkSystem = bwoinkSys;
|
||||||
|
ChannelId = userId;
|
||||||
|
|
||||||
|
OnVisibilityChanged += c =>
|
||||||
|
{
|
||||||
|
if (c.Visible)
|
||||||
|
Unread = 0;
|
||||||
|
};
|
||||||
|
SenderLineEdit.OnTextEntered += Input_OnTextEntered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Input_OnTextEntered(LineEdit.LineEditEventArgs args)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(args.Text))
|
||||||
|
_bwoinkSystem.Send(ChannelId, args.Text);
|
||||||
|
|
||||||
|
SenderLineEdit.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReceiveLine(string text)
|
||||||
|
{
|
||||||
|
if (!Visible)
|
||||||
|
Unread++;
|
||||||
|
var formatted = new FormattedMessage(1);
|
||||||
|
formatted.AddMarkup(text);
|
||||||
|
TextOutput.AddMessage(formatted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
PlaceHolder="{Loc Filter}"/>
|
PlaceHolder="{Loc Filter}"/>
|
||||||
<ItemList Name="PlayerItemList"
|
<ItemList Name="PlayerItemList"
|
||||||
|
Access="Public"
|
||||||
SelectMode="Single"
|
SelectMode="Single"
|
||||||
VerticalExpand="True"
|
VerticalExpand="True"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
|
|||||||
@@ -2,14 +2,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Administration.Events;
|
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Player;
|
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Players;
|
|
||||||
|
|
||||||
namespace Content.Client.Administration.UI.CustomControls
|
namespace Content.Client.Administration.UI.CustomControls
|
||||||
{
|
{
|
||||||
@@ -20,6 +17,9 @@ namespace Content.Client.Administration.UI.CustomControls
|
|||||||
|
|
||||||
public event Action<PlayerInfo?>? OnSelectionChanged;
|
public event Action<PlayerInfo?>? OnSelectionChanged;
|
||||||
|
|
||||||
|
public Action<PlayerInfo, ItemList.Item>? DecoratePlayer;
|
||||||
|
public Func<PlayerInfo, int>? SortKey;
|
||||||
|
|
||||||
public PlayerListControl()
|
public PlayerListControl()
|
||||||
{
|
{
|
||||||
_adminSystem = EntitySystem.Get<AdminSystem>();
|
_adminSystem = EntitySystem.Get<AdminSystem>();
|
||||||
@@ -53,10 +53,17 @@ namespace Content.Client.Administration.UI.CustomControls
|
|||||||
OnSelectionChanged?.Invoke(null);
|
OnSelectionChanged?.Invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Refresh() => PopulateList();
|
||||||
|
|
||||||
private void PopulateList(IReadOnlyList<PlayerInfo> _ = null!)
|
private void PopulateList(IReadOnlyList<PlayerInfo> _ = null!)
|
||||||
{
|
{
|
||||||
PlayerItemList.Clear();
|
PlayerItemList.Clear();
|
||||||
foreach (var info in _adminSystem.PlayerList)
|
|
||||||
|
IEnumerable<PlayerInfo> iter = _adminSystem.PlayerList;
|
||||||
|
if (SortKey is not null)
|
||||||
|
iter = _adminSystem.PlayerList.OrderByDescending(SortKey);
|
||||||
|
|
||||||
|
foreach (var info in iter)
|
||||||
{
|
{
|
||||||
var displayName = $"{info.CharacterName} ({info.Username})";
|
var displayName = $"{info.CharacterName} ({info.Username})";
|
||||||
if (!string.IsNullOrEmpty(FilterLineEdit.Text) &&
|
if (!string.IsNullOrEmpty(FilterLineEdit.Text) &&
|
||||||
@@ -65,11 +72,13 @@ namespace Content.Client.Administration.UI.CustomControls
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerItemList.Add(new ItemList.Item(PlayerItemList)
|
var item = new ItemList.Item(PlayerItemList)
|
||||||
{
|
{
|
||||||
Metadata = info,
|
Metadata = info,
|
||||||
Text = displayName
|
Text = displayName
|
||||||
});
|
};
|
||||||
|
DecoratePlayer?.Invoke(info, item);
|
||||||
|
PlayerItemList.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
|||||||
SubmitButton.Disabled = string.IsNullOrEmpty(PlayerNameLine.Text);
|
SubmitButton.Disabled = string.IsNullOrEmpty(PlayerNameLine.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayerSelectionChanged(PlayerInfo? player)
|
public void OnPlayerSelectionChanged(PlayerInfo? player)
|
||||||
{
|
{
|
||||||
PlayerNameLine.Text = player?.Username ?? string.Empty;
|
PlayerNameLine.Text = player?.Username ?? string.Empty;
|
||||||
OnPlayerNameChanged();
|
OnPlayerNameChanged();
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<cc:PlayerListControl Name="PlayerList" VerticalExpand="True" />
|
<cc:PlayerListControl Name="PlayerList" VerticalExpand="True" />
|
||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<Button Name="SubmitKickButton" Text="{Loc admin-player-actions-window-kick-text}" Disabled="True"/>
|
<Button Name="SubmitKickButton" Text="{Loc admin-player-actions-kick}" Disabled="True"/>
|
||||||
<Button Name="SubmitAHelpButton" Text="{Loc admin-player-actions-window-ahelp-text}" Disabled="True"/>
|
<Button Name="SubmitAHelpButton" Text="{Loc admin-player-actions-ahelp}" Disabled="True"/>
|
||||||
<Button Name="SubmitRespawnButton" Text="{Loc admin-player-actions-window-respawn-text}" Disabled="True"/>
|
<Button Name="SubmitRespawnButton" Text="{Loc admin-player-actions-respawn}" Disabled="True"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</SS14Window>
|
</SS14Window>
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ namespace Content.Client.Commands
|
|||||||
}
|
}
|
||||||
if (args.Length == 0)
|
if (args.Length == 0)
|
||||||
{
|
{
|
||||||
EntitySystem.Get<BwoinkSystem>().EnsureWindowForLocalPlayer();
|
EntitySystem.Get<BwoinkSystem>().EnsurePanelForLocalPlayer();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Guid.TryParse(args[0], out var guid))
|
if (Guid.TryParse(args[0], out var guid))
|
||||||
{
|
{
|
||||||
EntitySystem.Get<BwoinkSystem>().EnsureWindow(new NetUserId(guid));
|
EntitySystem.Get<BwoinkSystem>().EnsurePanel(new NetUserId(guid));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace Content.Shared.Administration
|
|||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class BwoinkTextMessage : EntityEventArgs
|
public sealed class BwoinkTextMessage : EntityEventArgs
|
||||||
{
|
{
|
||||||
|
public DateTime SentAt { get; }
|
||||||
public NetUserId ChannelId { get; }
|
public NetUserId ChannelId { get; }
|
||||||
// This is ignored from the client.
|
// This is ignored from the client.
|
||||||
// It's checked by the client when receiving a message from the server for bwoink noises.
|
// It's checked by the client when receiving a message from the server for bwoink noises.
|
||||||
@@ -39,8 +40,9 @@ namespace Content.Shared.Administration
|
|||||||
public NetUserId TrueSender { get; }
|
public NetUserId TrueSender { get; }
|
||||||
public string Text { get; }
|
public string Text { get; }
|
||||||
|
|
||||||
public BwoinkTextMessage(NetUserId channelId, NetUserId trueSender, string text)
|
public BwoinkTextMessage(NetUserId channelId, NetUserId trueSender, string text, DateTime? sentAt = default)
|
||||||
{
|
{
|
||||||
|
SentAt = sentAt ?? DateTime.Now;
|
||||||
ChannelId = channelId;
|
ChannelId = channelId;
|
||||||
TrueSender = trueSender;
|
TrueSender = trueSender;
|
||||||
Text = text;
|
Text = text;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
bwoink-user-title = Admin Message
|
||||||
|
|
||||||
bwoink-system-starmute-message-no-other-users = *System: Nobody is available to receive your message. Try pinging Game Admins on Discord.
|
bwoink-system-starmute-message-no-other-users = *System: Nobody is available to receive your message. Try pinging Game Admins on Discord.
|
||||||
|
|
||||||
bwoink-system-starmute-message-no-other-users-webhook = *System: Your message has been relayed to the admins via discord.
|
bwoink-system-starmute-message-no-other-users-webhook = *System: Your message has been relayed to the admins via discord.
|
||||||
|
|||||||
5
Resources/Locale/en-US/administration/ui/actions.ftl
Normal file
5
Resources/Locale/en-US/administration/ui/actions.ftl
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
admin-player-actions-kick = Kick
|
||||||
|
admin-player-actions-ban = Ban
|
||||||
|
admin-player-actions-ahelp = AHelp
|
||||||
|
admin-player-actions-respawn = Respawn
|
||||||
|
admin-player-actions-teleport = Teleport To
|
||||||
@@ -1,4 +1 @@
|
|||||||
admin-player-actions-window-title = Player Actions Panel
|
admin-player-actions-window-title = Player Actions Panel
|
||||||
admin-player-actions-window-kick-text = Kick
|
|
||||||
admin-player-actions-window-ahelp-text = AHelp
|
|
||||||
admin-player-actions-window-respawn-text = Respawn
|
|
||||||
|
|||||||
Reference in New Issue
Block a user