diff --git a/Content.Client/BarSign/BarSignSystem.cs b/Content.Client/BarSign/BarSignSystem.cs index 05db00d819..9fd8ba2e4b 100644 --- a/Content.Client/BarSign/BarSignSystem.cs +++ b/Content.Client/BarSign/BarSignSystem.cs @@ -1,3 +1,4 @@ +using Content.Client.BarSign.Ui; using Content.Shared.BarSign; using Content.Shared.Power; using Robust.Client.GameObjects; @@ -8,6 +9,7 @@ namespace Content.Client.BarSign; public sealed class BarSignSystem : VisualizerSystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; public override void Initialize() { @@ -17,6 +19,9 @@ public sealed class BarSignSystem : VisualizerSystem private void OnAfterAutoHandleState(EntityUid uid, BarSignComponent component, ref AfterAutoHandleStateEvent args) { + if (_ui.TryGetOpenUi(uid, BarSignUiKey.Key, out var bui)) + bui.Update(component.Current); + UpdateAppearance(uid, component); } @@ -34,9 +39,9 @@ public sealed class BarSignSystem : VisualizerSystem if (powered && sign.Current != null - && _prototypeManager.TryIndex(sign.Current, out BarSignPrototype? proto)) + && _prototypeManager.TryIndex(sign.Current, out var proto)) { - sprite.LayerSetState(0, proto.Icon); + sprite.LayerSetSprite(0, proto.Icon); sprite.LayerSetShader(0, "unshaded"); } else diff --git a/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs b/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs new file mode 100644 index 0000000000..1d1280b2f3 --- /dev/null +++ b/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs @@ -0,0 +1,50 @@ +using System.Linq; +using Content.Shared.BarSign; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; + +namespace Content.Client.BarSign.Ui; + +[UsedImplicitly] +public sealed class BarSignBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey) +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private BarSignMenu? _menu; + + protected override void Open() + { + base.Open(); + + var sign = EntMan.GetComponentOrNull(Owner)?.Current is { } current + ? _prototype.Index(current) + : null; + var allSigns = Shared.BarSign.BarSignSystem.GetAllBarSigns(_prototype) + .OrderBy(p => Loc.GetString(p.Name)) + .ToList(); + _menu = new(sign, allSigns); + + _menu.OnSignSelected += id => + { + SendMessage(new SetBarSignMessage(id)); + }; + + _menu.OnClose += Close; + _menu.OpenCentered(); + } + + public void Update(ProtoId? sign) + { + if (_prototype.TryIndex(sign, out var signPrototype)) + _menu?.UpdateState(signPrototype); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Dispose(); + } +} + diff --git a/Content.Client/BarSign/Ui/BarSignMenu.xaml b/Content.Client/BarSign/Ui/BarSignMenu.xaml new file mode 100644 index 0000000000..5b1155ae35 --- /dev/null +++ b/Content.Client/BarSign/Ui/BarSignMenu.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/Content.Client/BarSign/Ui/BarSignMenu.xaml.cs b/Content.Client/BarSign/Ui/BarSignMenu.xaml.cs new file mode 100644 index 0000000000..a9333339b7 --- /dev/null +++ b/Content.Client/BarSign/Ui/BarSignMenu.xaml.cs @@ -0,0 +1,50 @@ +using Content.Client.UserInterface.Controls; +using Content.Shared.BarSign; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.BarSign.Ui; + +[GenerateTypedNameReferences] +public sealed partial class BarSignMenu : FancyWindow +{ + private string? _currentId; + + private readonly List _cachedPrototypes = new(); + + public event Action? OnSignSelected; + + public BarSignMenu(BarSignPrototype? currentSign, List signs) + { + RobustXamlLoader.Load(this); + _currentId = currentSign?.ID; + + _cachedPrototypes.Clear(); + _cachedPrototypes = signs; + foreach (var proto in _cachedPrototypes) + { + SignOptions.AddItem(Loc.GetString(proto.Name)); + } + + SignOptions.OnItemSelected += idx => + { + OnSignSelected?.Invoke(_cachedPrototypes[idx.Id].ID); + SignOptions.SelectId(idx.Id); + }; + + if (currentSign != null) + { + var idx = _cachedPrototypes.IndexOf(currentSign); + SignOptions.TrySelectId(idx); + } + } + + public void UpdateState(BarSignPrototype newSign) + { + if (_currentId != null && newSign.ID == _currentId) + return; + _currentId = newSign.ID; + var idx = _cachedPrototypes.IndexOf(newSign); + SignOptions.TrySelectId(idx); + } +} diff --git a/Content.Server/BarSign/Systems/BarSignSystem.cs b/Content.Server/BarSign/Systems/BarSignSystem.cs deleted file mode 100644 index e42394f5a3..0000000000 --- a/Content.Server/BarSign/Systems/BarSignSystem.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Linq; -using Content.Shared.BarSign; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.BarSign.Systems -{ - public sealed class BarSignSystem : EntitySystem - { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly MetaDataSystem _metaData = default!; - - public override void Initialize() - { - SubscribeLocalEvent(OnMapInit); - } - - private void OnMapInit(EntityUid uid, BarSignComponent component, MapInitEvent args) - { - if (component.Current != null) - return; - - var prototypes = _prototypeManager - .EnumeratePrototypes() - .Where(p => !p.Hidden) - .ToList(); - - var newPrototype = _random.Pick(prototypes); - - var meta = Comp(uid); - var name = newPrototype.Name != string.Empty ? newPrototype.Name : "barsign-component-name"; - _metaData.SetEntityName(uid, Loc.GetString(name), meta); - _metaData.SetEntityDescription(uid, Loc.GetString(newPrototype.Description), meta); - - component.Current = newPrototype.ID; - Dirty(uid, component); - } - } -} diff --git a/Content.Shared/BarSign/BarSignComponent.cs b/Content.Shared/BarSign/BarSignComponent.cs index d50726216e..98c6e815cc 100644 --- a/Content.Shared/BarSign/BarSignComponent.cs +++ b/Content.Shared/BarSign/BarSignComponent.cs @@ -1,10 +1,27 @@ using Robust.Shared.GameStates; using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; namespace Content.Shared.BarSign; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] public sealed partial class BarSignComponent : Component { - [DataField, AutoNetworkedField] public ProtoId? Current; + /// + /// The current bar sign prototype being displayed. + /// + [DataField, AutoNetworkedField] + public ProtoId? Current; +} + +[Serializable, NetSerializable] +public enum BarSignUiKey : byte +{ + Key +} + +[Serializable, NetSerializable] +public sealed class SetBarSignMessage(ProtoId sign) : BoundUserInterfaceMessage +{ + public ProtoId Sign = sign; } diff --git a/Content.Shared/BarSign/BarSignPrototype.cs b/Content.Shared/BarSign/BarSignPrototype.cs index a0566d9f46..d63ebda4a7 100644 --- a/Content.Shared/BarSign/BarSignPrototype.cs +++ b/Content.Shared/BarSign/BarSignPrototype.cs @@ -1,23 +1,23 @@ using Robust.Shared.Prototypes; +using Robust.Shared.Utility; -namespace Content.Shared.BarSign +namespace Content.Shared.BarSign; + +[Prototype] +public sealed partial class BarSignPrototype : IPrototype { - [Prototype("barSign")] - public sealed partial class BarSignPrototype : IPrototype - { - [ViewVariables] - [IdDataField] - public string ID { get; private set; } = default!; + [IdDataField, ViewVariables] + public string ID { get; private set; } = default!; + [DataField(required: true)] + public SpriteSpecifier Icon { get; private set; } = default!; - [DataField("icon")] public string Icon { get; private set; } = string.Empty; + [DataField] + public LocId Name { get; private set; } = "barsign-component-name"; - [DataField("name")] public string Name { get; set; } = ""; - [DataField("description")] public string Description { get; set; } = ""; + [DataField] + public LocId Description { get; private set; } - [DataField("renameArea")] - public bool RenameArea { get; private set; } = true; - [DataField("hidden")] - public bool Hidden { get; private set; } - } + [DataField] + public bool Hidden { get; private set; } } diff --git a/Content.Shared/BarSign/BarSignSystem.cs b/Content.Shared/BarSign/BarSignSystem.cs new file mode 100644 index 0000000000..bf28cfe6b7 --- /dev/null +++ b/Content.Shared/BarSign/BarSignSystem.cs @@ -0,0 +1,58 @@ +using System.Linq; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.BarSign; + +public sealed class BarSignSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly MetaDataSystem _metaData = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnMapInit); + Subs.BuiEvents(BarSignUiKey.Key, + subs => + { + subs.Event(OnSetBarSignMessage); + }); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + if (ent.Comp.Current != null) + return; + + var newPrototype = _random.Pick(GetAllBarSigns(_prototypeManager)); + SetBarSign(ent, newPrototype); + } + + private void OnSetBarSignMessage(Entity ent, ref SetBarSignMessage args) + { + if (!_prototypeManager.TryIndex(args.Sign, out var signPrototype)) + return; + + SetBarSign(ent, signPrototype); + } + + public void SetBarSign(Entity ent, BarSignPrototype newPrototype) + { + var meta = MetaData(ent); + var name = Loc.GetString(newPrototype.Name); + _metaData.SetEntityName(ent, name, meta); + _metaData.SetEntityDescription(ent, Loc.GetString(newPrototype.Description), meta); + + ent.Comp.Current = newPrototype.ID; + Dirty(ent); + } + + public static List GetAllBarSigns(IPrototypeManager prototypeManager) + { + return prototypeManager + .EnumeratePrototypes() + .Where(p => !p.Hidden) + .ToList(); + } +} diff --git a/Resources/Locale/en-US/barsign/barsign-component.ftl b/Resources/Locale/en-US/barsign/barsign-component.ftl index 3451d70bc9..cf7ddd1e24 100644 --- a/Resources/Locale/en-US/barsign/barsign-component.ftl +++ b/Resources/Locale/en-US/barsign/barsign-component.ftl @@ -1,4 +1,6 @@ barsign-component-name = bar sign +barsign-ui-menu = Bar Sign Configuration +barsign-ui-set-label = Set Sign: # Bar signs prototypes diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/bar_sign.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/bar_sign.yml index 8e957abfe7..b2a0ffe592 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/bar_sign.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/bar_sign.yml @@ -9,6 +9,7 @@ Brute: collection: GlassSmash - type: WallMount + arc: 360 - type: Sprite drawdepth: Objects sprite: Structures/Wallmounts/barsign.rsi @@ -16,6 +17,17 @@ - type: ApcPowerReceiver - type: ExtensionCableReceiver - type: BarSign + - type: InteractionOutline + - type: AccessReader + access: [["Bar"]] + - type: ActivatableUIRequiresPower + - type: ActivatableUIRequiresAccess + - type: ActivatableUI + key: enum.BarSignUiKey.Key + - type: UserInterface + interfaces: + enum.BarSignUiKey.Key: + type: BarSignBoundUserInterface - type: Appearance - type: Destructible thresholds: diff --git a/Resources/Prototypes/bar_signs.yml b/Resources/Prototypes/bar_signs.yml index 8c6476831b..e3f9d30a42 100644 --- a/Resources/Prototypes/bar_signs.yml +++ b/Resources/Prototypes/bar_signs.yml @@ -1,154 +1,183 @@ - type: barSign id: Harmbaton name: barsign-prototype-name-harmbaton - icon: "theharmbaton" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: theharmbaton description: barsign-prototype-description-harmbaton - type: barSign id: TheSingulo name: barsign-prototype-name-singulo - icon: "thesingulo" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thesingulo description: barsign-prototype-description-singulo - type: barSign id: TheDrunkCarp name: barsign-prototype-name-drunk-carp - icon: "thedrunkcarp" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thedrunkcarp description: barsign-prototype-description-drunk-carp - type: barSign id: OfficerBeersky name: barsign-prototype-name-officer-beersky - icon: "officerbeersky" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: officerbeersky description: barsign-prototype-description-officer-beersky - type: barSign id: TheOuterSpess name: barsign-prototype-name-outer-spess - icon: "theouterspess" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: theouterspess description: barsign-prototype-description-outer-spess - type: barSign id: TheCoderbus name: barsign-prototype-name-coderbus - icon: "thecoderbus" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thecoderbus description: barsign-prototype-description-coderbus - type: barSign id: RobustaCafe name: barsign-prototype-name-robusta-cafe - icon: "robustacafe" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: robustacafe description: barsign-prototype-description-robusta-cafe - type: barSign id: EmergencyRumParty name: barsign-prototype-name-emergency-rum-party - icon: "emergencyrumparty" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: emergencyrumparty description: barsign-prototype-description-emergency-rum-party - type: barSign id: ComboCafe name: barsign-prototype-name-combo-cafe - icon: "combocafe" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: combocafe description: barsign-prototype-description-combo-cafe - type: barSign id: TheAleNath name: barsign-prototype-name-ale-nath - icon: "thealenath" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thealenath description: barsign-prototype-description-ale-nath - type: barSign id: TheNet name: barsign-prototype-name-the-net - icon: "thenet" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thenet description: barsign-prototype-description-the-net - type: barSign id: MaidCafe name: barsign-prototype-name-maid-cafe - icon: "maidcafe" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: maidcafe description: barsign-prototype-description-maid-cafe - type: barSign id: MalteseFalcon name: barsign-prototype-name-maltese-falcon - icon: "maltesefalcon" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: maltesefalcon description: barsign-prototype-description-maltese-falcon - type: barSign id: TheSun name: barsign-prototype-name-the-sun - icon: "thesun" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thesun description: barsign-prototype-description-the-sun - type: barSign id: TheBirdCage name: barsign-prototype-name-the-birdcage - icon: "birdcage" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: birdcage description: barsign-prototype-description-the-birdcage - type: barSign id: Zocalo name: barsign-prototype-name-zocalo - icon: "zocalo" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: zocalo description: barsign-prototype-description-zocalo - type: barSign id: LV426 name: barsign-prototype-name-lv426 - icon: "lv426" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: lv426 description: barsign-prototype-description-lv426 - type: barSign id: WiggleRoom name: barsign-prototype-name-wiggle-room - icon: "thewiggleroom" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: thewiggleroom description: barsign-prototype-description-wiggle-room - type: barSign id: TheLightbulb name: barsign-prototype-name-the-lightbulb - icon: "the_lightbulb" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: the_lightbulb description: barsign-prototype-description-the-lightbulb - type: barSign id: Goose name: barsign-prototype-name-goose - icon: "goose" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: goose description: barsign-prototype-description-goose - type: barSign id: EngineChange name: barsign-prototype-name-enginechange - icon: "enginechange" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: enginechange description: barsign-prototype-description-enginechange - type: barSign id: Emprah name: barsign-prototype-name-emprah - icon: "emprah" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: emprah description: barsign-prototype-description-emprah - type: barSign id: Spacebucks name: barsign-prototype-name-spacebucks - icon: "spacebucks" + icon: + sprite: Structures/Wallmounts/barsign.rsi + state: spacebucks description: barsign-prototype-description-spacebucks - -# Hidden signs list below this point -- type: barSign - id: EmpBarSign - name: "" - icon: "empbarsign" - description: barsign-prototype-description-empbarsign - renameArea: false - hidden: true - -- type: barSign - id: SignOff - name: "" - icon: "empty" - description: barsign-prototype-description-sign-off - renameArea: false - hidden: true