Crew manifest as a PDA cartridge program (#18498)

Co-authored-by: Phill101 <holypics4@gmail.com>
This commit is contained in:
Phill101
2023-08-05 13:37:08 +05:00
committed by GitHub
parent 0df383d7e1
commit 600621e7ee
18 changed files with 418 additions and 180 deletions

View File

@@ -6,6 +6,7 @@ using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Containers;
using Robust.Shared.Map;
using System.Diagnostics.CodeAnalysis;
namespace Content.Server.CartridgeLoader;
@@ -80,7 +81,7 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
return new List<EntityUid>();
//Don't count a cartridge that has already been installed as available to avoid confusion
if (loader.CartridgeSlot.HasItem && IsInstalled(Prototype(loader.CartridgeSlot.Item!.Value)?.ID, loader))
if (loader.CartridgeSlot.HasItem && TryFindInstalled(Prototype(loader.CartridgeSlot.Item!.Value)?.ID, loader, out _))
return loader.InstalledPrograms;
var available = new List<EntityUid>();
@@ -127,7 +128,13 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
return false;
//Prevent installing cartridges that have already been installed
if (IsInstalled(prototype, loader))
if (TryFindInstalled(prototype, loader, out _))
return false;
var ev = new ProgramInstallationAttempt(loaderUid, prototype);
RaiseLocalEvent(ref ev);
if (ev.Cancelled)
return false;
var installedProgram = Spawn(prototype, new EntityCoordinates(loaderUid, 0, 0));
@@ -141,6 +148,22 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
return true;
}
/// <summary>
/// Uninstalls a program using its prototype
/// </summary>
/// <param name="loaderUid">The cartridge loader uid</param>
/// <param name="prototype">The prototype name of the program to be uninstalled</param>
/// <param name="loader">The cartridge loader component</param>
/// <returns>Whether uninstalling the program was successful</returns>
public bool UninstallProgram(EntityUid loaderUid, string prototype, CartridgeLoaderComponent? loader = default!)
{
if (!Resolve(loaderUid, ref loader))
return false;
return TryFindInstalled(prototype, loader, out var programUid) &&
UninstallProgram(loaderUid, programUid.Value, loader);
}
/// <summary>
/// Uninstalls a program using its uid
/// </summary>
@@ -345,16 +368,20 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
}
/// <summary>
/// Checks if a program is already installed by searching for its prototype name in the list of installed programs
/// Searches for a program by its prototype name in the list of installed programs
/// </summary>
private bool IsInstalled(string? prototype, CartridgeLoaderComponent loader)
private bool TryFindInstalled(string? prototype, CartridgeLoaderComponent loader, [NotNullWhen(true)] out EntityUid? programUid)
{
foreach (var program in loader.InstalledPrograms)
{
if (Prototype(program)?.ID == prototype)
{
programUid = program;
return true;
}
}
programUid = default;
return false;
}
@@ -414,3 +441,9 @@ public sealed class CartridgeAfterInteractEvent : EntityEventArgs
InteractEvent = interactEvent;
}
}
/// <summary>
/// Raised on an attempt of program installation.
/// </summary>
[ByRefEvent]
public record struct ProgramInstallationAttempt(EntityUid LoaderUid, string Prototype, bool Cancelled = false);

View File

@@ -0,0 +1,6 @@
namespace Content.Server.CartridgeLoader.Cartridges;
[RegisterComponent]
public sealed class CrewManifestCartridgeComponent : Component
{
}

View File

@@ -0,0 +1,95 @@
using Content.Server.CrewManifest;
using Content.Server.Station.Systems;
using Content.Shared.CartridgeLoader;
using Content.Shared.CartridgeLoader.Cartridges;
using Content.Shared.CCVar;
using Robust.Shared.Configuration;
namespace Content.Server.CartridgeLoader.Cartridges;
public sealed class CrewManifestCartridgeSystem : EntitySystem
{
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly CrewManifestSystem _crewManifest = default!;
[Dependency] private readonly StationSystem _stationSystem = default!;
private const string CartridgePrototypeName = "CrewManifestCartridge";
/// <summary>
/// Flag that shows that if crew manifest is allowed to be viewed from 'unsecure' entities,
/// which is the keys for the cartridge.
/// </summary>
private bool _unsecureViewersAllowed = true;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CrewManifestCartridgeComponent, CartridgeMessageEvent>(OnUiMessage);
SubscribeLocalEvent<CrewManifestCartridgeComponent, CartridgeUiReadyEvent>(OnUiReady);
SubscribeLocalEvent<ProgramInstallationAttempt>(OnInstallationAttempt);
_configManager.OnValueChanged(CCVars.CrewManifestUnsecure, OnCrewManifestUnsecureChanged, true);
}
/// <summary>
/// The ui messages received here get wrapped by a CartridgeMessageEvent and are relayed from the <see cref="CartridgeLoaderSystem"/>
/// </summary>
/// <remarks>
/// The cartridge specific ui message event needs to inherit from the CartridgeMessageEvent
/// </remarks>
private void OnUiMessage(EntityUid uid, CrewManifestCartridgeComponent component, CartridgeMessageEvent args)
{
UpdateUiState(uid, args.LoaderUid, component);
}
/// <summary>
/// This gets called when the ui fragment needs to be updated for the first time after activating
/// </summary>
private void OnUiReady(EntityUid uid, CrewManifestCartridgeComponent component, CartridgeUiReadyEvent args)
{
UpdateUiState(uid, args.Loader, component);
}
private void UpdateUiState(EntityUid uid, EntityUid loaderUid, CrewManifestCartridgeComponent? component)
{
if (!Resolve(uid, ref component))
return;
var owningStation = _stationSystem.GetOwningStation(uid);
if (owningStation is null)
return;
var (stationName, entries) = _crewManifest.GetCrewManifest(owningStation.Value);
var state = new CrewManifestUiState(stationName, entries);
_cartridgeLoader.UpdateCartridgeUiState(loaderUid, state);
}
private void OnInstallationAttempt(ref ProgramInstallationAttempt args)
{
if (args.Prototype == CartridgePrototypeName && !_unsecureViewersAllowed)
args.Cancelled = true;
}
private void OnCrewManifestUnsecureChanged(bool unsecureViewersAllowed)
{
_unsecureViewersAllowed = unsecureViewersAllowed;
var allCartridgeLoaders = AllEntityQuery<CartridgeLoaderComponent>();
while (allCartridgeLoaders.MoveNext(out EntityUid loaderUid, out CartridgeLoaderComponent? comp))
{
if (_unsecureViewersAllowed)
_cartridgeLoader?.InstallProgram(loaderUid, CartridgePrototypeName, false, comp);
else
_cartridgeLoader?.UninstallProgram(loaderUid, CartridgePrototypeName, comp);
}
}
public override void Shutdown()
{
base.Shutdown();
_configManager.UnsubValueChanged(CCVars.CrewManifestUnsecure, OnCrewManifestUnsecureChanged);
}
}