UI to edit silicon laws from admin verb (#28483)
* UI to edit silicon laws from admin verb (peak shitcode) * Improve UI * Use Moderator admin flag * Reviews
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<BoxContainer
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
HorizontalExpand="True"
|
||||
Orientation="Vertical"
|
||||
>
|
||||
<customControls:HSeparator></customControls:HSeparator>
|
||||
<BoxContainer>
|
||||
<Label StyleClasses="SiliconLawPositionLabel" Name="PositionText" Margin="5 0 0 0"></Label>
|
||||
<PanelContainer
|
||||
Margin="20 10 0 0"
|
||||
MinHeight="128"
|
||||
>
|
||||
<PanelContainer.PanelOverride>
|
||||
<graphics:StyleBoxFlat BackgroundColor="#1B1B1B"></graphics:StyleBoxFlat>
|
||||
</PanelContainer.PanelOverride>
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="5">
|
||||
<TextEdit Name="LawContent" HorizontalExpand="True" Editable="True" MinWidth="500" MinHeight="80"></TextEdit>
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" Margin="0 5 0 0" MaxHeight="64" Align="Begin">
|
||||
<Button Name="MoveUp" Text="{Loc silicon-law-ui-minus-one}" StyleClasses="OpenRight"></Button>
|
||||
<Button Name="MoveDown" Text="{Loc silicon-law-ui-plus-one}" StyleClasses="OpenLeft"></Button>
|
||||
<CheckBox Name="Corrupted" Text="{Loc silicon-law-ui-check-corrupted}" ToolTip="{Loc silicon-law-ui-check-corrupted-tooltip}"></CheckBox>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" Align="End" Margin="0 10 5 10">
|
||||
<Button Name="Delete" Text="{Loc silicon-law-ui-delete}" ModulateSelfOverride="Red"></Button>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
@@ -0,0 +1,61 @@
|
||||
using Content.Shared.Silicons.Laws;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Silicons.Laws.SiliconLawEditUi;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SiliconLawContainer : BoxContainer
|
||||
{
|
||||
public const string StyleClassSiliconLawPositionLabel = "SiliconLawPositionLabel";
|
||||
|
||||
public static readonly string CorruptedString =
|
||||
Loc.GetString("ion-storm-law-scrambled-number", ("length", 5));
|
||||
|
||||
private SiliconLaw? _law;
|
||||
|
||||
public event Action<SiliconLaw>? MoveLawUp;
|
||||
public event Action<SiliconLaw>? MoveLawDown;
|
||||
public event Action<SiliconLaw>? DeleteAction;
|
||||
|
||||
|
||||
public SiliconLawContainer()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
MoveUp.OnPressed += _ => MoveLawUp?.Invoke(_law!);
|
||||
MoveDown.OnPressed += _ => MoveLawDown?.Invoke(_law!);
|
||||
Corrupted.OnPressed += _ =>
|
||||
{
|
||||
if (Corrupted.Pressed)
|
||||
{
|
||||
_law!.LawIdentifierOverride = CorruptedString;
|
||||
}
|
||||
else
|
||||
{
|
||||
_law!.LawIdentifierOverride = null;
|
||||
}
|
||||
};
|
||||
|
||||
LawContent.OnTextChanged += _ => _law!.LawString = Rope.Collapse(LawContent.TextRope).Trim();
|
||||
LawContent.Placeholder = new Rope.Leaf(Loc.GetString("silicon-law-ui-placeholder"));
|
||||
Delete.OnPressed += _ => DeleteAction?.Invoke(_law!);
|
||||
}
|
||||
|
||||
public void SetLaw(SiliconLaw law)
|
||||
{
|
||||
_law = law;
|
||||
LawContent.TextRope = new Rope.Leaf(Loc.GetString(law.LawString));
|
||||
PositionText.Text = law.Order.ToString();
|
||||
if (!string.IsNullOrEmpty(law.LawIdentifierOverride))
|
||||
{
|
||||
Corrupted.Pressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Corrupted.Pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Content.Client.Eui;
|
||||
using Content.Shared.Eui;
|
||||
using Content.Shared.Silicons.Laws;
|
||||
|
||||
namespace Content.Client.Silicons.Laws.SiliconLawEditUi;
|
||||
|
||||
public sealed class SiliconLawEui : BaseEui
|
||||
{
|
||||
public readonly EntityManager _entityManager = default!;
|
||||
|
||||
private SiliconLawUi _siliconLawUi;
|
||||
private EntityUid _target;
|
||||
|
||||
public SiliconLawEui()
|
||||
{
|
||||
_entityManager = IoCManager.Resolve<EntityManager>();
|
||||
|
||||
_siliconLawUi = new SiliconLawUi();
|
||||
_siliconLawUi.OnClose += () => SendMessage(new CloseEuiMessage());
|
||||
_siliconLawUi.Save.OnPressed += _ => SendMessage(new SiliconLawsSaveMessage(_siliconLawUi.GetLaws(), _entityManager.GetNetEntity(_target)));
|
||||
}
|
||||
|
||||
public override void HandleState(EuiStateBase state)
|
||||
{
|
||||
if (state is not SiliconLawsEuiState s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_target = _entityManager.GetEntity(s.Target);
|
||||
_siliconLawUi.SetLaws(s.Laws);
|
||||
}
|
||||
|
||||
public override void Opened()
|
||||
{
|
||||
_siliconLawUi.OpenCentered();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<controls:FancyWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc silicon-law-ui-title}"
|
||||
MinSize="560 400"
|
||||
>
|
||||
<!-->
|
||||
this shit does not layout properly unless I put the horizontal boxcontainer inside of a vertical one
|
||||
????
|
||||
<!-->
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal" Align="End">
|
||||
<Button Name="NewLawButton" Text="{Loc silicon-law-ui-new-law}" MaxSize="256 64" StyleClasses="OpenRight"></Button>
|
||||
<Button Name="Save" Text="{Loc silicon-law-ui-save}" MaxSize="256 64" Access="Public" StyleClasses="OpenLeft"></Button>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" Margin="4 60 0 0">
|
||||
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
|
||||
<BoxContainer Orientation="Vertical" Name="LawContainer" Access="Public" VerticalExpand="True" />
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Linq;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Silicons.Laws;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Silicons.Laws.SiliconLawEditUi;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class SiliconLawUi : FancyWindow
|
||||
{
|
||||
private List<SiliconLaw> _laws = new();
|
||||
|
||||
public SiliconLawUi()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
NewLawButton.OnPressed += _ => AddNewLaw();
|
||||
}
|
||||
|
||||
private void AddNewLaw()
|
||||
{
|
||||
var newLaw = new SiliconLaw();
|
||||
newLaw.Order = FixedPoint2.New(_laws.Count + 1);
|
||||
_laws.Add(newLaw);
|
||||
SetLaws(_laws);
|
||||
}
|
||||
|
||||
public void SetLaws(List<SiliconLaw> sLaws)
|
||||
{
|
||||
_laws = sLaws;
|
||||
LawContainer.RemoveAllChildren();
|
||||
foreach (var law in sLaws.OrderBy(l => l.Order))
|
||||
{
|
||||
var lawControl = new SiliconLawContainer();
|
||||
lawControl.SetLaw(law);
|
||||
lawControl.MoveLawDown += MoveLawDown;
|
||||
lawControl.MoveLawUp += MoveLawUp;
|
||||
lawControl.DeleteAction += DeleteLaw;
|
||||
|
||||
LawContainer.AddChild(lawControl);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteLaw(SiliconLaw law)
|
||||
{
|
||||
_laws.Remove(law);
|
||||
SetLaws(_laws);
|
||||
}
|
||||
|
||||
public void MoveLawDown(SiliconLaw law)
|
||||
{
|
||||
if (_laws.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var index = _laws.IndexOf(law);
|
||||
if (index == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_laws[index].Order += FixedPoint2.New(1);
|
||||
SetLaws(_laws);
|
||||
}
|
||||
|
||||
public void MoveLawUp(SiliconLaw law)
|
||||
{
|
||||
if (_laws.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var index = _laws.IndexOf(law);
|
||||
if (index == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_laws[index].Order += FixedPoint2.New(-1);
|
||||
SetLaws(_laws);
|
||||
}
|
||||
|
||||
public List<SiliconLaw> GetLaws()
|
||||
{
|
||||
return _laws;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Content.Client.ContextMenu.UI;
|
||||
using Content.Client.Examine;
|
||||
using Content.Client.PDA;
|
||||
using Content.Client.Resources;
|
||||
using Content.Client.Silicons.Laws.SiliconLawEditUi;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.UserInterface.Controls.FancyTree;
|
||||
using Content.Client.Verbs.UI;
|
||||
@@ -1613,6 +1614,10 @@ namespace Content.Client.Stylesheets
|
||||
{
|
||||
BackgroundColor = FancyTreeSelectedRowColor,
|
||||
}),
|
||||
|
||||
// Silicon law edit ui
|
||||
Element<Label>().Class(SiliconLawContainer.StyleClassSiliconLawPositionLabel)
|
||||
.Prop(Label.StylePropertyFontColor, NanoGold),
|
||||
// Pinned button style
|
||||
new StyleRule(
|
||||
new SelectorElement(typeof(TextureButton), new[] { StyleClassPinButtonPinned }, null, null),
|
||||
|
||||
@@ -35,6 +35,9 @@ using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Silicons.Laws;
|
||||
using Content.Shared.Silicons.Laws.Components;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||
|
||||
@@ -68,6 +71,8 @@ namespace Content.Server.Administration.Systems
|
||||
[Dependency] private readonly StationSpawningSystem _spawning = default!;
|
||||
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
||||
[Dependency] private readonly AdminFrozenSystem _freeze = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly SiliconLawSystem _siliconLawSystem = default!;
|
||||
|
||||
private readonly Dictionary<ICommonSession, List<EditSolutionsEui>> _openSolutionUis = new();
|
||||
|
||||
@@ -338,6 +343,25 @@ namespace Content.Server.Administration.Systems
|
||||
Impact = LogImpact.Low
|
||||
});
|
||||
|
||||
if (TryComp<SiliconLawBoundComponent>(args.Target, out var lawBoundComponent))
|
||||
{
|
||||
args.Verbs.Add(new Verb()
|
||||
{
|
||||
Text = Loc.GetString("silicon-law-ui-verb"),
|
||||
Category = VerbCategory.Admin,
|
||||
Act = () =>
|
||||
{
|
||||
var ui = new SiliconLawEui(_siliconLawSystem, EntityManager, _adminManager);
|
||||
if (!_playerManager.TryGetSessionByEntity(args.User, out var session))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_euiManager.OpenEui(ui, session);
|
||||
ui.UpdateLaws(lawBoundComponent, args.Target);
|
||||
},
|
||||
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/Interface/Actions/actions_borg.rsi"), "state-laws"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
70
Content.Server/Silicons/Laws/SiliconLawEui.cs
Normal file
70
Content.Server/Silicons/Laws/SiliconLawEui.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.EUI;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Eui;
|
||||
using Content.Shared.Silicons.Laws;
|
||||
using Content.Shared.Silicons.Laws.Components;
|
||||
|
||||
namespace Content.Server.Silicons.Laws;
|
||||
|
||||
public sealed class SiliconLawEui : BaseEui
|
||||
{
|
||||
private readonly SiliconLawSystem _siliconLawSystem;
|
||||
private readonly EntityManager _entityManager;
|
||||
private readonly IAdminManager _adminManager;
|
||||
|
||||
private List<SiliconLaw> _laws = new();
|
||||
private ISawmill _sawmill = default!;
|
||||
private EntityUid _target;
|
||||
|
||||
public SiliconLawEui(SiliconLawSystem siliconLawSystem, EntityManager entityManager, IAdminManager manager)
|
||||
{
|
||||
_siliconLawSystem = siliconLawSystem;
|
||||
_adminManager = manager;
|
||||
_entityManager = entityManager;
|
||||
_sawmill = Logger.GetSawmill("silicon-law-eui");
|
||||
}
|
||||
|
||||
public override EuiStateBase GetNewState()
|
||||
{
|
||||
return new SiliconLawsEuiState(_laws, _entityManager.GetNetEntity(_target));
|
||||
}
|
||||
|
||||
public void UpdateLaws(SiliconLawBoundComponent? lawBoundComponent, EntityUid player)
|
||||
{
|
||||
if (!IsAllowed())
|
||||
return;
|
||||
|
||||
var laws = _siliconLawSystem.GetLaws(player, lawBoundComponent);
|
||||
_laws = laws.Laws;
|
||||
_target = player;
|
||||
StateDirty();
|
||||
}
|
||||
|
||||
public override void HandleMessage(EuiMessageBase msg)
|
||||
{
|
||||
if (msg is not SiliconLawsSaveMessage message)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsAllowed())
|
||||
return;
|
||||
|
||||
var player = _entityManager.GetEntity(message.Target);
|
||||
|
||||
_siliconLawSystem.SetLaws(message.Laws, player);
|
||||
}
|
||||
|
||||
private bool IsAllowed()
|
||||
{
|
||||
var adminData = _adminManager.GetAdminData(Player);
|
||||
if (adminData == null || !adminData.HasFlag(AdminFlags.Moderator))
|
||||
{
|
||||
_sawmill.Warning("Player {0} tried to open / use silicon law UI without permission.", Player.UserId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Silicons.Laws;
|
||||
|
||||
@@ -278,6 +279,21 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
|
||||
return laws;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the laws of a silicon entity while notifying the player.
|
||||
/// </summary>
|
||||
public void SetLaws(List<SiliconLaw> newLaws, EntityUid target)
|
||||
{
|
||||
if (!TryComp<SiliconLawProviderComponent>(target, out var component))
|
||||
return;
|
||||
|
||||
if (component.Lawset == null)
|
||||
component.Lawset = new SiliconLawset();
|
||||
|
||||
component.Lawset.Laws = newLaws;
|
||||
NotifyLawsChanged(target);
|
||||
}
|
||||
}
|
||||
|
||||
[ToolshedCommand, AdminCommand(AdminFlags.Admin)]
|
||||
|
||||
29
Content.Shared/Silicons/Laws/SiliconLawEditEuiState.cs
Normal file
29
Content.Shared/Silicons/Laws/SiliconLawEditEuiState.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Content.Shared.Eui;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Silicons.Laws;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SiliconLawsEuiState : EuiStateBase
|
||||
{
|
||||
public List<SiliconLaw> Laws { get; }
|
||||
public NetEntity Target { get; }
|
||||
public SiliconLawsEuiState(List<SiliconLaw> laws, NetEntity target)
|
||||
{
|
||||
Laws = laws;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class SiliconLawsSaveMessage : EuiMessageBase
|
||||
{
|
||||
public List<SiliconLaw> Laws { get; }
|
||||
public NetEntity Target { get; }
|
||||
|
||||
public SiliconLawsSaveMessage(List<SiliconLaw> laws, NetEntity target)
|
||||
{
|
||||
Laws = laws;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
10
Resources/Locale/en-US/administration/ui/silicon-law-ui.ftl
Normal file
10
Resources/Locale/en-US/administration/ui/silicon-law-ui.ftl
Normal file
@@ -0,0 +1,10 @@
|
||||
silicon-law-ui-verb = Manage laws
|
||||
silicon-law-ui-title = Silicon laws
|
||||
silicon-law-ui-new-law = New law
|
||||
silicon-law-ui-save = Save changes
|
||||
silicon-law-ui-plus-one = +1
|
||||
silicon-law-ui-minus-one = -1
|
||||
silicon-law-ui-delete = Delete
|
||||
silicon-law-ui-check-corrupted = Corrupted law
|
||||
silicon-law-ui-check-corrupted-tooltip = If the law identifier should be set as 'corrupted', so symbols shuffling around.
|
||||
silicon-law-ui-placeholder = Type here to change law text...
|
||||
Reference in New Issue
Block a user