Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Content.Server.PDA.Ringer;

/// <summary>
/// Marker that specifies a map should block access to lockable uplinks
/// </summary>
[RegisterComponent]
public sealed partial class LockableUplinkBlockedMapComponent : Component
{
}
71 changes: 71 additions & 0 deletions Content.Server/PDA/Ringer/RingerSystem.PdaConnectionLocking.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Content.Shared.PDA;
using Content.Shared.Popups;
using Content.Shared.Shuttles.Components;

namespace Content.Server.PDA.Ringer;

public sealed partial class RingerSystem
{
/// <summary>
/// Returns if the map supplied allows open uplinks.
/// </summary>
/// <param name="map">Map to be checked.</param>
/// <returns></returns>
private bool CanUplinkBeOpenedOnMap(EntityUid? map)
{
// Uh... I'm just going to put this here as default behaviour since I think this is what used to happen...
if (map is null)
return true;

return !HasComp<LockableUplinkBlockedMapComponent>(map);
}

/// <summary>
/// Checks that a map allows for uplinks to be opened before opening an uplink.
/// </summary>
/// <param name="ent">PDA that holds the uplink</param>
/// <param name="args"></param>
private void CheckMapBeforeOpenUplink(Entity<RingerUplinkComponent> ent, ref BeforeUplinkOpenEvent args)
{
var map = _transform.GetMap((EntityUid)ent);
if (CanUplinkBeOpenedOnMap(map))
return;
args.Canceled = true;
_popupSystem.PopupEntity(Loc.GetString("uplink-no-connection"),
ent,
args.AttemptingClient,
PopupType.LargeCaution);
}

/// <summary>
/// Locks all open uplinks whenever they are on a map that blocks uplinks.
/// </summary>
private void LockUplinksBasedOnMap()
{
// Surely there has to be a better way to check if the map has changed...
// Eh, surely someone will catch it in reviews and tell me how to do it right?
var uplinkPdaQuery = EntityQueryEnumerator<RingerUplinkComponent>();
while (uplinkPdaQuery.MoveNext(out var uid, out var ringer))
{
if (!ringer.Unlocked)
continue;

var map = _transform.GetMap(uid);
if (CanUplinkBeOpenedOnMap(map))
continue;

LockUplink(uid, ringer);
if (TryComp(uid, out PdaComponent? pda))
_pda.UpdatePdaUi(uid, pda);

// "Find" the person holding onto this PDA
// Again, I feel there must be a better way of doing this, hopefully review will let me know!
var owner = _transform.GetParentUid(uid);
_popupSystem.PopupEntity(
Loc.GetString("uplink-lose-connection"),
uid,
owner,
PopupType.LargeCaution);
}
}
}
26 changes: 22 additions & 4 deletions Content.Server/PDA/Ringer/RingerSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Content.Shared.PDA;
using Content.Shared.PDA.Ringer;
using Content.Shared.Popups;
using Content.Shared.Shuttles.Components;
using Content.Shared.Store;
using Content.Shared.Store.Components;
using Robust.Server.GameObjects;
Expand All @@ -18,7 +19,7 @@

namespace Content.Server.PDA.Ringer
{
public sealed class RingerSystem : SharedRingerSystem
public sealed partial class RingerSystem : SharedRingerSystem
{
[Dependency] private readonly PdaSystem _pda = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
Expand All @@ -40,6 +41,7 @@ public override void Initialize()
// RingerBoundUserInterface Subscriptions
SubscribeLocalEvent<RingerComponent, RingerSetRingtoneMessage>(OnSetRingtone);
SubscribeLocalEvent<RingerUplinkComponent, BeforeRingtoneSetEvent>(OnSetUplinkRingtone);
SubscribeLocalEvent<RingerUplinkComponent, BeforeUplinkOpenEvent>(CheckMapBeforeOpenUplink);
SubscribeLocalEvent<RingerComponent, RingerPlayRingtoneMessage>(RingerPlayRingtone);
SubscribeLocalEvent<RingerComponent, RingerRequestUpdateInterfaceMessage>(UpdateRingerUserInterfaceDriver);

Expand Down Expand Up @@ -104,7 +106,7 @@ private void OnSetRingtone(EntityUid uid, RingerComponent ringer, RingerSetRingt
if (args.Ringtone.Length != RingtoneLength)
return;

var ev = new BeforeRingtoneSetEvent(args.Ringtone);
var ev = new BeforeRingtoneSetEvent(args.Ringtone, actorComp.PlayerSession);
RaiseLocalEvent(uid, ref ev);
if (ev.Handled)
return;
Expand All @@ -116,7 +118,18 @@ private void OnSetUplinkRingtone(EntityUid uid, RingerUplinkComponent uplink, re
{
if (uplink.Code.SequenceEqual(args.Ringtone) && HasComp<StoreComponent>(uid))
{
uplink.Unlocked = !uplink.Unlocked;
if (!uplink.Unlocked)
{
var ev = new BeforeUplinkOpenEvent(args.AttemptingClient);
RaiseLocalEvent(uid, ref ev);
if (!ev.Canceled)
uplink.Unlocked = true;
}
else
{
uplink.Unlocked = false;
}

if (TryComp<PdaComponent>(uid, out var pda))
_pda.UpdatePdaUi(uid, pda);

Expand Down Expand Up @@ -240,6 +253,8 @@ public bool ToggleRingerUI(EntityUid uid, EntityUid actor)
{
RemComp<ActiveRingerComponent>(ent);
}

LockUplinksBasedOnMap();
}

private static string GetSound(Note note)
Expand All @@ -249,5 +264,8 @@ private static string GetSound(Note note)
}

[ByRefEvent]
public record struct BeforeRingtoneSetEvent(Note[] Ringtone, bool Handled = false);
public record struct BeforeRingtoneSetEvent(Note[] Ringtone, ICommonSession AttemptingClient, bool Handled = false);

[ByRefEvent]
public record struct BeforeUplinkOpenEvent(ICommonSession AttemptingClient, bool Canceled = false);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using Content.Server.PDA.Ringer;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
using Content.Server.Station.Events;
Expand Down Expand Up @@ -135,6 +136,7 @@ private EntityUid EnsureFTLMap()

var mapUid = _mapSystem.CreateMap(out var mapId);
var ftlMap = AddComp<FTLMapComponent>(mapUid);
AddComp<LockableUplinkBlockedMapComponent>(mapUid);

_metadata.SetEntityName(mapUid, "FTL");
Log.Debug($"Setup hyperspace map at {mapUid}");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uplink-no-connection = The uplink fails to connect!
uplink-lose-connection = The uplink loses connection and locks!
Loading