PDA UI refactor and cartridges (#11335)

* Work on cartridges

* Work on PDA UI

* Work on PDA UIs program list

* Work on PDA UI borders

* Add DeviceNetworkingComponent to the pda base prototype

* Fix submodule version

* Fix cartridge loader ui key

* Fix pda menu xaml

* Implement relaying ui messages

* Finish implementing the notekeeper cartridge

* Fix submodule version

* Fix errors from merging master

* Fix test failing

* Implement setting preinstalled programs

* Add some documentation to CartridgeLoaderSystem

* Add more doc comments

* Add localization to program names

* Implement review suggestions

* Fix background programs receiving events twice when active
This commit is contained in:
Julian Giebel
2022-11-08 21:00:20 +01:00
committed by GitHub
parent 1151ca42e5
commit e11cf969fa
79 changed files with 2323 additions and 94 deletions

View File

@@ -0,0 +1,35 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.CartridgeLoader;
/// <summary>
/// This is used for defining values used for displaying in the program ui in yaml
/// </summary>
[NetworkedComponent]
[RegisterComponent]
public sealed class CartridgeComponent : Component
{
[DataField("programName", required: true)]
public string ProgramName = "default-program-name";
[DataField("icon")]
public SpriteSpecifier? Icon;
public InstallationStatus InstallationStatus = InstallationStatus.Cartridge;
}
[Serializable, NetSerializable]
public sealed class CartridgeComponentState : ComponentState
{
public InstallationStatus InstallationStatus;
}
[Serializable, NetSerializable]
public enum InstallationStatus
{
Cartridge,
Installed,
Readonly
}

View File

@@ -0,0 +1,26 @@
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader;
[Serializable, NetSerializable]
public sealed class CartridgeLoaderUiMessage : BoundUserInterfaceMessage
{
public readonly EntityUid CartridgeUid;
public readonly CartridgeUiMessageAction Action;
public CartridgeLoaderUiMessage(EntityUid cartridgeUid, CartridgeUiMessageAction action)
{
CartridgeUid = cartridgeUid;
Action = action;
}
}
[Serializable, NetSerializable]
public enum CartridgeUiMessageAction
{
Activate,
Deactivate,
Install,
Uninstall,
UIReady
}

View File

@@ -0,0 +1,12 @@
using System.Collections.Immutable;
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader;
[Virtual]
[Serializable, NetSerializable]
public class CartridgeLoaderUiState : BoundUserInterfaceState
{
public EntityUid? ActiveUI;
public List<EntityUid> Programs = new();
}

View File

@@ -0,0 +1,9 @@
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader;
[Serializable, NetSerializable]
public enum CartridgeLoaderVisuals
{
CartridgeInserted
}

View File

@@ -0,0 +1,20 @@
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader;
[Serializable, NetSerializable]
public sealed class CartridgeUiMessage : BoundUserInterfaceMessage
{
public CartridgeMessageEvent MessageEvent;
public CartridgeUiMessage(CartridgeMessageEvent messageEvent)
{
MessageEvent = messageEvent;
}
}
[Serializable, NetSerializable]
public abstract class CartridgeMessageEvent : EntityEventArgs
{
public EntityUid LoaderUid;
}

View File

@@ -0,0 +1,23 @@
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class NotekeeperUiMessageEvent : CartridgeMessageEvent
{
public readonly NotekeeperUiAction Action;
public readonly string Note;
public NotekeeperUiMessageEvent(NotekeeperUiAction action, string note)
{
Action = action;
Note = note;
}
}
[Serializable, NetSerializable]
public enum NotekeeperUiAction
{
Add,
Remove
}

View File

@@ -0,0 +1,14 @@
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class NotekeeperUiState : BoundUserInterfaceState
{
public List<String> Notes;
public NotekeeperUiState(List<string> notes)
{
Notes = notes;
}
}

View File

@@ -0,0 +1,36 @@
using Content.Shared.Containers.ItemSlots;
namespace Content.Shared.CartridgeLoader;
[Access(typeof(SharedCartridgeLoaderSystem))]
public abstract class SharedCartridgeLoaderComponent : Component
{
public const string CartridgeSlotId = "Cartridge-Slot";
[DataField("cartridgeSlot")]
public ItemSlot CartridgeSlot = new();
/// <summary>
/// List of programs that come preinstalled with this cartridge loader
/// </summary>
[DataField("preinstalled")]
public List<string> PreinstalledPrograms = new();
/// <summary>
/// The currently running program that has its ui showing
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public EntityUid? ActiveProgram = default;
/// <summary>
/// The list of programs running in the background, listening to certain events
/// </summary>
[ViewVariables]
public readonly List<EntityUid> BackgroundPrograms = new();
/// <summary>
/// The list of program entities that are spawned into the cartridge loaders program container
/// </summary>
[DataField("installedCartridges")]
public List<EntityUid> InstalledPrograms = new();
}

View File

@@ -0,0 +1,147 @@
using Content.Shared.Containers.ItemSlots;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
namespace Content.Shared.CartridgeLoader;
public abstract class SharedCartridgeLoaderSystem : EntitySystem
{
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SharedCartridgeLoaderComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<SharedCartridgeLoaderComponent, ComponentRemove>(OnComponentRemove);
SubscribeLocalEvent<SharedCartridgeLoaderComponent, EntInsertedIntoContainerMessage>(OnItemInserted);
SubscribeLocalEvent<SharedCartridgeLoaderComponent, EntRemovedFromContainerMessage>(OnItemRemoved);
SubscribeLocalEvent<CartridgeComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<CartridgeComponent, ComponentHandleState>(OnHandleState);
}
private void OnComponentInit(EntityUid uid, SharedCartridgeLoaderComponent loader, ComponentInit args)
{
_itemSlotsSystem.AddItemSlot(uid, SharedCartridgeLoaderComponent.CartridgeSlotId, loader.CartridgeSlot);
}
/// <summary>
/// Marks installed program entities for deletion when the component gets removed
/// </summary>
private void OnComponentRemove(EntityUid uid, SharedCartridgeLoaderComponent loader, ComponentRemove args)
{
_itemSlotsSystem.RemoveItemSlot(uid, loader.CartridgeSlot);
foreach (var program in loader.InstalledPrograms)
{
EntityManager.QueueDeleteEntity(program);
}
}
protected virtual void OnItemInserted(EntityUid uid, SharedCartridgeLoaderComponent loader, EntInsertedIntoContainerMessage args)
{
UpdateAppearanceData(uid, loader);
}
protected virtual void OnItemRemoved(EntityUid uid, SharedCartridgeLoaderComponent loader, EntRemovedFromContainerMessage args)
{
UpdateAppearanceData(uid, loader);
}
private void OnGetState(EntityUid uid, CartridgeComponent component, ref ComponentGetState args)
{
var state = new CartridgeComponentState();
state.InstallationStatus = component.InstallationStatus;
args.State = state;
}
private void OnHandleState(EntityUid uid, CartridgeComponent component, ref ComponentHandleState args)
{
if (args.Current is not CartridgeComponentState state)
return;
component.InstallationStatus = state.InstallationStatus;
}
private void UpdateAppearanceData(EntityUid uid, SharedCartridgeLoaderComponent loader)
{
_appearanceSystem.SetData(uid, CartridgeLoaderVisuals.CartridgeInserted, loader.CartridgeSlot.HasItem);
}
}
/// <summary>
/// Gets sent to program / cartridge entities when they get inserted or installed
/// </summary>
public sealed class CartridgeAddedEvent : EntityEventArgs
{
public readonly EntityUid Loader;
public CartridgeAddedEvent(EntityUid loader)
{
Loader = loader;
}
}
/// <summary>
/// Gets sent to cartridge entities when they get ejected
/// </summary>
public sealed class CartridgeRemovedEvent : EntityEventArgs
{
public readonly EntityUid Loader;
public CartridgeRemovedEvent(EntityUid loader)
{
Loader = loader;
}
}
/// <summary>
/// Gets sent to program / cartridge entities when they get activated
/// </summary>
/// <remarks>
/// Don't update the programs ui state in this events listener
/// </remarks>
public sealed class CartridgeActivatedEvent : EntityEventArgs
{
public readonly EntityUid Loader;
public CartridgeActivatedEvent(EntityUid loader)
{
Loader = loader;
}
}
/// <summary>
/// Gets sent to program / cartridge entities when they get deactivated
/// </summary>
public sealed class CartridgeDeactivatedEvent : EntityEventArgs
{
public readonly EntityUid Loader;
public CartridgeDeactivatedEvent(EntityUid loader)
{
Loader = loader;
}
}
/// <summary>
/// Gets sent to program / cartridge entities when the ui is ready to be updated by the cartridge.
/// </summary>
/// <remarks>
/// This is used for the initial ui state update because updating the ui in the activate event doesn't work
/// </remarks>
public sealed class CartridgeUiReadyEvent : EntityEventArgs
{
public readonly EntityUid Loader;
public CartridgeUiReadyEvent(EntityUid loader)
{
Loader = loader;
}
}