+using Content.Client.BarSign.Ui;
using Content.Shared.BarSign;
using Content.Shared.Power;
using Robust.Client.GameObjects;
public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ [Dependency] private readonly UserInterfaceSystem _ui = default!;
public override void Initialize()
{
private void OnAfterAutoHandleState(EntityUid uid, BarSignComponent component, ref AfterAutoHandleStateEvent args)
{
+ if (_ui.TryGetOpenUi<BarSignBoundUserInterface>(uid, BarSignUiKey.Key, out var bui))
+ bui.Update(component.Current);
+
UpdateAppearance(uid, component);
}
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
--- /dev/null
+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<BarSignComponent>(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<BarSignPrototype>? 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();
+ }
+}
+
--- /dev/null
+<controls:FancyWindow
+ xmlns="https://spacestation14.io"
+ xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+ xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
+ Title="{Loc 'barsign-ui-menu'}"
+ MinSize="280 180"
+ SetSize="280 180">
+ <BoxContainer VerticalExpand="True" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10 5 10 10">
+ <BoxContainer Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
+ <BoxContainer Orientation="Vertical" HorizontalAlignment="Center">
+ <Label Text="{Loc 'barsign-ui-set-label'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="30 0"/>
+ <customControls:HSeparator Margin="0 0 0 5"/>
+ </BoxContainer>
+ <OptionButton Name="SignOptions" HorizontalAlignment="Center" VerticalAlignment="Center" MinSize="175 60" Margin="0 0 0 20"/>
+ </BoxContainer>
+ </BoxContainer>
+</controls:FancyWindow>
+
+
--- /dev/null
+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<BarSignPrototype> _cachedPrototypes = new();
+
+ public event Action<string>? OnSignSelected;
+
+ public BarSignMenu(BarSignPrototype? currentSign, List<BarSignPrototype> 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);
+ }
+}
+++ /dev/null
-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<BarSignComponent, MapInitEvent>(OnMapInit);
- }
-
- private void OnMapInit(EntityUid uid, BarSignComponent component, MapInitEvent args)
- {
- if (component.Current != null)
- return;
-
- var prototypes = _prototypeManager
- .EnumeratePrototypes<BarSignPrototype>()
- .Where(p => !p.Hidden)
- .ToList();
-
- var newPrototype = _random.Pick(prototypes);
-
- var meta = Comp<MetaDataComponent>(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);
- }
- }
-}
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<BarSignPrototype>? Current;
+ /// <summary>
+ /// The current bar sign prototype being displayed.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public ProtoId<BarSignPrototype>? Current;
+}
+
+[Serializable, NetSerializable]
+public enum BarSignUiKey : byte
+{
+ Key
+}
+
+[Serializable, NetSerializable]
+public sealed class SetBarSignMessage(ProtoId<BarSignPrototype> sign) : BoundUserInterfaceMessage
+{
+ public ProtoId<BarSignPrototype> Sign = sign;
}
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; }
}
--- /dev/null
+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<BarSignComponent, MapInitEvent>(OnMapInit);
+ Subs.BuiEvents<BarSignComponent>(BarSignUiKey.Key,
+ subs =>
+ {
+ subs.Event<SetBarSignMessage>(OnSetBarSignMessage);
+ });
+ }
+
+ private void OnMapInit(Entity<BarSignComponent> ent, ref MapInitEvent args)
+ {
+ if (ent.Comp.Current != null)
+ return;
+
+ var newPrototype = _random.Pick(GetAllBarSigns(_prototypeManager));
+ SetBarSign(ent, newPrototype);
+ }
+
+ private void OnSetBarSignMessage(Entity<BarSignComponent> ent, ref SetBarSignMessage args)
+ {
+ if (!_prototypeManager.TryIndex(args.Sign, out var signPrototype))
+ return;
+
+ SetBarSign(ent, signPrototype);
+ }
+
+ public void SetBarSign(Entity<BarSignComponent> 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<BarSignPrototype> GetAllBarSigns(IPrototypeManager prototypeManager)
+ {
+ return prototypeManager
+ .EnumeratePrototypes<BarSignPrototype>()
+ .Where(p => !p.Hidden)
+ .ToList();
+ }
+}
barsign-component-name = bar sign
+barsign-ui-menu = Bar Sign Configuration
+barsign-ui-set-label = Set Sign:
# Bar signs prototypes
Brute:
collection: GlassSmash
- type: WallMount
+ arc: 360
- type: Sprite
drawdepth: Objects
sprite: Structures/Wallmounts/barsign.rsi
- 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:
- 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