uplink locking/unlocking, minor pda refactor (#15842)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-05-01 06:30:08 +00:00
committed by GitHub
parent 904d61baee
commit 44f9c098ec
13 changed files with 134 additions and 49 deletions

View File

@@ -53,11 +53,14 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
_menu.UpdateBalance(msg.Balance); _menu.UpdateBalance(msg.Balance);
_menu.PopulateStoreCategoryButtons(msg.Listings); _menu.PopulateStoreCategoryButtons(msg.Listings);
_menu.UpdateListing(msg.Listings.ToList()); _menu.UpdateListing(msg.Listings.ToList());
_menu.SetFooterVisibility(msg.ShowFooter);
break; break;
case StoreInitializeState msg: case StoreInitializeState msg:
_windowName = msg.Name; _windowName = msg.Name;
if (_menu != null && _menu.Window != null) if (_menu != null && _menu.Window != null)
{
_menu.Window.Title = msg.Name; _menu.Window.Title = msg.Name;
}
break; break;
} }
} }

View File

@@ -50,5 +50,15 @@
</BoxContainer> </BoxContainer>
</PanelContainer> </PanelContainer>
</BoxContainer> </BoxContainer>
<!-- Footer -->
<BoxContainer Orientation="Vertical" Name="TraitorFooter">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'store-ui-traitor-flavor'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'store-ui-traitor-warning'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
</BoxContainer>
</BoxContainer>
</BoxContainer> </BoxContainer>
</DefaultWindow> </DefaultWindow>

View File

@@ -77,6 +77,11 @@ public sealed partial class StoreMenu : DefaultWindow
} }
} }
public void SetFooterVisibility(bool visible)
{
TraitorFooter.Visible = visible;
}
private void OnWithdrawButtonDown(BaseButton.ButtonEventArgs args) private void OnWithdrawButtonDown(BaseButton.ButtonEventArgs args)
{ {
// check if window is already open // check if window is already open

View File

@@ -82,11 +82,13 @@ public sealed class RenameCommand : IConsoleCommand
// PDAs // PDAs
if (entSysMan.TryGetEntitySystem<PDASystem>(out var pdaSystem)) if (entSysMan.TryGetEntitySystem<PDASystem>(out var pdaSystem))
{ {
foreach (var pdaComponent in entMan.EntityQuery<PDAComponent>()) var query = entMan.EntityQueryEnumerator<PDAComponent>();
while (query.MoveNext(out var uid, out var pda))
{ {
if (pdaComponent.OwnerName != oldName) if (pda.OwnerName == oldName)
continue; {
pdaSystem.SetOwner(pdaComponent, name); pdaSystem.SetOwner(uid, pda, name);
}
} }
} }

View File

@@ -6,6 +6,8 @@ using Content.Server.Light.EntitySystems;
using Content.Server.Light.Events; using Content.Server.Light.Events;
using Content.Server.PDA.Ringer; using Content.Server.PDA.Ringer;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Server.Store.Components;
using Content.Server.Store.Systems;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.PDA; using Content.Shared.PDA;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -18,12 +20,13 @@ namespace Content.Server.PDA
{ {
public sealed class PDASystem : SharedPDASystem public sealed class PDASystem : SharedPDASystem
{ {
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
[Dependency] private readonly InstrumentSystem _instrument = default!;
[Dependency] private readonly RingerSystem _ringer = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly StoreSystem _store = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly UnpoweredFlashlightSystem _unpoweredFlashlight = default!; [Dependency] private readonly UnpoweredFlashlightSystem _unpoweredFlashlight = default!;
[Dependency] private readonly RingerSystem _ringerSystem = default!;
[Dependency] private readonly InstrumentSystem _instrumentSystem = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -40,43 +43,46 @@ namespace Content.Server.PDA
if (!TryComp(uid, out ServerUserInterfaceComponent? uiComponent)) if (!TryComp(uid, out ServerUserInterfaceComponent? uiComponent))
return; return;
UpdateStationName(pda); UpdateStationName(uid, pda);
if (_uiSystem.TryGetUi(uid, PDAUiKey.Key, out var ui, uiComponent)) if (_ui.TryGetUi(uid, PDAUiKey.Key, out var ui, uiComponent))
ui.OnReceiveMessage += (msg) => OnUIMessage(pda, msg); ui.OnReceiveMessage += (msg) => OnUIMessage(pda, msg);
} }
protected override void OnItemInserted(EntityUid uid, PDAComponent pda, EntInsertedIntoContainerMessage args) protected override void OnItemInserted(EntityUid uid, PDAComponent pda, EntInsertedIntoContainerMessage args)
{ {
base.OnItemInserted(uid, pda, args); base.OnItemInserted(uid, pda, args);
UpdatePDAUserInterface(pda); UpdatePdaUi(uid, pda);
} }
protected override void OnItemRemoved(EntityUid uid, PDAComponent pda, EntRemovedFromContainerMessage args) protected override void OnItemRemoved(EntityUid uid, PDAComponent pda, EntRemovedFromContainerMessage args)
{ {
base.OnItemRemoved(uid, pda, args); base.OnItemRemoved(uid, pda, args);
UpdatePDAUserInterface(pda); UpdatePdaUi(uid, pda);
} }
private void OnLightToggle(EntityUid uid, PDAComponent pda, LightToggleEvent args) private void OnLightToggle(EntityUid uid, PDAComponent pda, LightToggleEvent args)
{ {
pda.FlashlightOn = args.IsOn; pda.FlashlightOn = args.IsOn;
UpdatePDAUserInterface(pda); UpdatePdaUi(uid, pda);
} }
public void SetOwner(PDAComponent pda, string ownerName) public void SetOwner(EntityUid uid, PDAComponent pda, string ownerName)
{ {
pda.OwnerName = ownerName; pda.OwnerName = ownerName;
UpdatePDAUserInterface(pda); UpdatePdaUi(uid, pda);
} }
private void OnGridChanged(EntityUid uid, PDAComponent pda, GridModifiedEvent args) private void OnGridChanged(EntityUid uid, PDAComponent pda, GridModifiedEvent args)
{ {
UpdateStationName(pda); UpdateStationName(uid, pda);
UpdatePDAUserInterface(pda); UpdatePdaUi(uid, pda);
} }
private void UpdatePDAUserInterface(PDAComponent pda) /// <summary>
/// Send new UI state to clients, call if you modify something like uplink.
/// </summary>
public void UpdatePdaUi(EntityUid uid, PDAComponent pda)
{ {
var ownerInfo = new PDAIdInfoText var ownerInfo = new PDAIdInfoText
{ {
@@ -85,49 +91,62 @@ namespace Content.Server.PDA
JobTitle = pda.ContainedID?.JobTitle JobTitle = pda.ContainedID?.JobTitle
}; };
if (!_uiSystem.TryGetUi(pda.Owner, PDAUiKey.Key, out var ui)) if (!_ui.TryGetUi(uid, PDAUiKey.Key, out var ui))
return; return;
var address = GetDeviceNetAddress(pda.Owner); var address = GetDeviceNetAddress(uid);
var hasInstrument = HasComp<InstrumentComponent>(pda.Owner); var hasInstrument = HasComp<InstrumentComponent>(uid);
var state = new PDAUpdateState(pda.FlashlightOn, pda.PenSlot.HasItem, ownerInfo, pda.StationName, false, hasInstrument, address); var showUplink = HasComp<StoreComponent>(uid) && IsUnlocked(uid);
_cartridgeLoaderSystem?.UpdateUiState(pda.Owner, state); var state = new PDAUpdateState(pda.FlashlightOn, pda.PenSlot.HasItem, ownerInfo, pda.StationName, showUplink, hasInstrument, address);
_cartridgeLoader?.UpdateUiState(uid, state);
} }
private void OnUIMessage(PDAComponent pda, ServerBoundUserInterfaceMessage msg) private void OnUIMessage(PDAComponent pda, ServerBoundUserInterfaceMessage msg)
{ {
var pdaEnt = pda.Owner; var uid = pda.Owner;
// todo: move this to entity events // todo: move this to entity events
switch (msg.Message) switch (msg.Message)
{ {
case PDARequestUpdateInterfaceMessage _: case PDARequestUpdateInterfaceMessage _:
UpdatePDAUserInterface(pda); UpdatePdaUi(uid, pda);
break; break;
case PDAToggleFlashlightMessage _: case PDAToggleFlashlightMessage _:
{ {
if (EntityManager.TryGetComponent(pdaEnt, out UnpoweredFlashlightComponent? flashlight)) if (TryComp<UnpoweredFlashlightComponent>(uid, out var flashlight))
_unpoweredFlashlight.ToggleLight(pdaEnt, flashlight); _unpoweredFlashlight.ToggleLight(uid, flashlight);
break; break;
} }
case PDAShowRingtoneMessage _: case PDAShowRingtoneMessage _:
{ {
if (EntityManager.TryGetComponent(pdaEnt, out RingerComponent? ringer)) if (TryComp<RingerComponent>(uid, out var ringer))
_ringerSystem.ToggleRingerUI(ringer, msg.Session); _ringer.ToggleRingerUI(ringer, msg.Session);
break; break;
} }
case PDAShowMusicMessage _: case PDAShowMusicMessage _:
{ {
if (TryComp(pdaEnt, out InstrumentComponent? instrument)) if (TryComp<InstrumentComponent>(uid, out var instrument))
_instrumentSystem.ToggleInstrumentUi(pdaEnt, msg.Session, instrument); _instrument.ToggleInstrumentUi(uid, msg.Session, instrument);
break;
}
case PDAShowUplinkMessage _:
{
// check if its locked again to prevent malicious clients opening locked uplinks
if (TryComp<StoreComponent>(uid, out var store) && IsUnlocked(uid))
_store.ToggleUi(msg.Session.AttachedEntity!.Value, uid, store);
break; break;
} }
} }
} }
private void UpdateStationName(PDAComponent pda) private bool IsUnlocked(EntityUid uid)
{ {
var station = _stationSystem.GetOwningStation(pda.Owner); return TryComp<RingerUplinkComponent>(uid, out var uplink) ? uplink.Unlocked : true;
}
private void UpdateStationName(EntityUid uid, PDAComponent pda)
{
var station = _station.GetOwningStation(uid);
pda.StationName = station is null ? null : Name(station.Value); pda.StationName = station is null ? null : Name(station.Value);
} }

View File

@@ -3,6 +3,8 @@ using Content.Server.Store.Systems;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.PDA; using Content.Shared.PDA;
using Content.Shared.PDA.Ringer; using Content.Shared.PDA.Ringer;
using Content.Shared.Store;
using Robust.Server.GameObjects;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Player; using Robust.Shared.Player;
@@ -14,8 +16,10 @@ namespace Content.Server.PDA.Ringer
{ {
public sealed class RingerSystem : SharedRingerSystem public sealed class RingerSystem : SharedRingerSystem
{ {
[Dependency] private readonly PDASystem _pda = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly StoreSystem _store = default!; [Dependency] private readonly StoreSystem _store = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -26,7 +30,7 @@ namespace Content.Server.PDA.Ringer
SubscribeLocalEvent<RingerUplinkComponent, ComponentInit>(RandomizeUplinkCode); SubscribeLocalEvent<RingerUplinkComponent, ComponentInit>(RandomizeUplinkCode);
// RingerBoundUserInterface Subscriptions // RingerBoundUserInterface Subscriptions
SubscribeLocalEvent<RingerComponent, RingerSetRingtoneMessage>(OnSetRingtone); SubscribeLocalEvent<RingerComponent, RingerSetRingtoneMessage>(OnSetRingtone);
SubscribeLocalEvent<RingerUplinkComponent, RingerSetRingtoneMessage>(OnSetUplinkRingtone); SubscribeLocalEvent<RingerUplinkComponent, BeforeRingtoneSetEvent>(OnSetUplinkRingtone);
SubscribeLocalEvent<RingerComponent, RingerPlayRingtoneMessage>(RingerPlayRingtone); SubscribeLocalEvent<RingerComponent, RingerPlayRingtoneMessage>(RingerPlayRingtone);
SubscribeLocalEvent<RingerComponent, RingerRequestUpdateInterfaceMessage>(UpdateRingerUserInterfaceDriver); SubscribeLocalEvent<RingerComponent, RingerRequestUpdateInterfaceMessage>(UpdateRingerUserInterfaceDriver);
@@ -50,17 +54,28 @@ namespace Content.Server.PDA.Ringer
// Client sent us an updated ringtone so set it to that. // Client sent us an updated ringtone so set it to that.
if (args.Ringtone.Length != RingtoneLength) return; if (args.Ringtone.Length != RingtoneLength) return;
var ev = new BeforeRingtoneSetEvent(args.Ringtone);
RaiseLocalEvent(uid, ref ev);
if (ev.Handled)
return;
UpdateRingerRingtone(ringer, args.Ringtone); UpdateRingerRingtone(ringer, args.Ringtone);
} }
private void OnSetUplinkRingtone(EntityUid uid, RingerUplinkComponent uplink, RingerSetRingtoneMessage args) private void OnSetUplinkRingtone(EntityUid uid, RingerUplinkComponent uplink, ref BeforeRingtoneSetEvent args)
{ {
if (uplink.Code.SequenceEqual(args.Ringtone) && if (uplink.Code.SequenceEqual(args.Ringtone) && TryComp<StoreComponent>(uid, out var store))
args.Session.AttachedEntity != null &&
TryComp<StoreComponent>(uid, out var store))
{ {
var user = args.Session.AttachedEntity.Value; uplink.Unlocked = !uplink.Unlocked;
_store.ToggleUi(args.Session.AttachedEntity.Value, uid, store); if (TryComp<PDAComponent>(uid, out var pda))
_pda.UpdatePdaUi(uid, pda);
// can't keep store open after locking it
if (!uplink.Unlocked)
_ui.TryCloseAll(uid, StoreUiKey.Key);
// no saving the code to prevent meta click set on sus guys pda -> wewlad
args.Handled = true;
} }
} }
@@ -161,3 +176,6 @@ namespace Content.Server.PDA.Ringer
} }
} }
} }
[ByRefEvent]
public record struct BeforeRingtoneSetEvent(Note[] Ringtone, bool Handled = false);

View File

@@ -10,9 +10,15 @@ namespace Content.Server.PDA.Ringer;
public sealed class RingerUplinkComponent : Component public sealed class RingerUplinkComponent : Component
{ {
/// <summary> /// <summary>
/// Notes to set ringtone to in order to open the uplink. /// Notes to set ringtone to in order to lock or unlock the uplink.
/// Automatically initialized to random notes. /// Automatically initialized to random notes.
/// </summary> /// </summary>
[DataField("code")] [DataField("code")]
public Note[] Code = new Note[RingerSystem.RingtoneLength]; public Note[] Code = new Note[RingerSystem.RingtoneLength];
/// <summary>
/// Whether to show the toggle uplink button in pda settings.
/// </summary>
[DataField("unlocked"), ViewVariables(VVAccess.ReadWrite)]
public bool Unlocked;
} }

View File

@@ -231,7 +231,7 @@ public sealed class StationSpawningSystem : EntitySystem
_accessSystem.SetAccessToJob(cardId, jobPrototype, extendedAccess); _accessSystem.SetAccessToJob(cardId, jobPrototype, extendedAccess);
_pdaSystem.SetOwner(pdaComponent, characterName); _pdaSystem.SetOwner(idUid.Value, pdaComponent, characterName);
} }

View File

@@ -1,5 +1,6 @@
using Content.Server.Actions; using Content.Server.Actions;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.PDA.Ringer;
using Content.Server.Stack; using Content.Server.Stack;
using Content.Server.Store.Components; using Content.Server.Store.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
@@ -49,6 +50,17 @@ public sealed partial class StoreSystem
UpdateUserInterface(user, storeEnt, component); UpdateUserInterface(user, storeEnt, component);
} }
/// <summary>
/// Closes the store UI for everyone, if it's open
/// </summary>
public void CloseUi(EntityUid uid, StoreComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
_ui.TryCloseAll(uid, StoreUiKey.Key);
}
/// <summary> /// <summary>
/// Updates the user interface for a store and refreshes the listings /// Updates the user interface for a store and refreshes the listings
/// </summary> /// </summary>
@@ -83,7 +95,9 @@ public sealed partial class StoreSystem
// TODO: if multiple users are supposed to be able to interact with a single BUI & see different // TODO: if multiple users are supposed to be able to interact with a single BUI & see different
// stores/listings, this needs to use session specific BUI states. // stores/listings, this needs to use session specific BUI states.
var state = new StoreUpdateState(component.LastAvailableListings, allCurrency); // only tell operatives to lock their uplink if it can be locked
var showFooter = HasComp<RingerUplinkComponent>(store);
var state = new StoreUpdateState(component.LastAvailableListings, allCurrency, showFooter);
_ui.SetUiState(ui, state); _ui.SetUiState(ui, state);
} }

View File

@@ -1,4 +1,5 @@
using Content.Server.Mind.Components; using Content.Server.Mind.Components;
using Content.Server.PDA.Ringer;
using Content.Server.Store.Components; using Content.Server.Store.Components;
using Content.Server.UserInterface; using Content.Server.UserInterface;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
@@ -72,9 +73,9 @@ public sealed partial class StoreSystem : EntitySystem
if (args.Target == null || !TryComp<StoreComponent>(args.Target, out var store)) if (args.Target == null || !TryComp<StoreComponent>(args.Target, out var store))
return; return;
// require the store to be open before inserting currency // if the store can be locked, it must be unlocked first before inserting currency
var user = args.User; var user = args.User;
if (!TryComp<ActorComponent>(user, out var actor) || !_ui.SessionHasOpenUi(uid, StoreUiKey.Key, actor.PlayerSession)) if (TryComp<RingerUplinkComponent>(args.Target, out var uplink) && !uplink.Unlocked)
return; return;
args.Handled = TryAddCurrency(GetCurrencyValue(uid, component), args.Target.Value, store); args.Handled = TryAddCurrency(GetCurrencyValue(uid, component), args.Target.Value, store);
@@ -183,6 +184,8 @@ public sealed partial class StoreSystem : EntitySystem
var ui = _ui.GetUiOrNull(uid, StoreUiKey.Key); var ui = _ui.GetUiOrNull(uid, StoreUiKey.Key);
if (ui != null) if (ui != null)
{
_ui.SetUiState(ui, new StoreInitializeState(preset.StoreName)); _ui.SetUiState(ui, new StoreInitializeState(preset.StoreName));
} }
} }
}

View File

@@ -16,10 +16,13 @@ public sealed class StoreUpdateState : BoundUserInterfaceState
public readonly Dictionary<string, FixedPoint2> Balance; public readonly Dictionary<string, FixedPoint2> Balance;
public StoreUpdateState(HashSet<ListingData> listings, Dictionary<string, FixedPoint2> balance) public readonly bool ShowFooter;
public StoreUpdateState(HashSet<ListingData> listings, Dictionary<string, FixedPoint2> balance, bool showFooter)
{ {
Listings = listings; Listings = listings;
Balance = balance; Balance = balance;
ShowFooter = showFooter;
} }
} }

View File

@@ -53,7 +53,7 @@ traitor-role-codewords =
Listen for them, and keep them secret. Listen for them, and keep them secret.
traitor-role-uplink-code = traitor-role-uplink-code =
Set your ringtone to the notes {$code} to lock or unlock your uplink. Set your ringtone to the notes {$code} to lock or unlock your uplink.
Remember to lock it and change it, or the stations crew will easily open it too! Remember to lock it after, or the stations crew will easily open it too!
# don't need all the flavour text for character menu # don't need all the flavour text for character menu
traitor-role-codewords-short = traitor-role-codewords-short =

View File

@@ -2,5 +2,7 @@ store-ui-default-title = Store
store-ui-default-withdraw-text = Withdraw store-ui-default-withdraw-text = Withdraw
store-ui-balance-display = {$currency}: {$amount} store-ui-balance-display = {$currency}: {$amount}
store-ui-price-display = {$amount} {$currency} store-ui-price-display = {$amount} {$currency}
store-ui-traitor-flavor = Copyright (C) NT -30643
store-ui-traitor-warning = Operatives must lock their uplinks after use to avoid detection.
store-withdraw-button-ui = Withdraw {$currency} store-withdraw-button-ui = Withdraw {$currency}