Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular Computer System #1556

Merged
merged 16 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Content.Shared/_Arcadis/Computer/ComputerDiskComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared._Arcadis.Computer;

/// <summary>
/// Main component for the ComputerDisk system
/// </summary>
[RegisterComponent, NetworkedComponent]
//[Access(typeof(ComputerDiskSystem))]
public sealed partial class ComputerDiskComponent : Component
{
/// <summary>
/// The prototype of the computer that will be used
/// </summary>
[DataField]
public EntProtoId ProgramPrototype;
public EntityUid? ProgramPrototypeEntity;

[DataField]
public bool PersistState;
}
20 changes: 20 additions & 0 deletions Content.Shared/_Arcadis/Computer/ModularComputerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Content.Shared.Containers.ItemSlots;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared._Arcadis.Computer;

/// <summary>
/// Main component for the ComputerDisk system
/// </summary>
[RegisterComponent, NetworkedComponent]
//[Access(typeof(ComputerDiskSystem))]
public sealed partial class ModularComputerComponent : Component
{
[DataField]
public string DiskSlot = "modularComputerDiskSlot";

[DataField]
public SoundSpecifier? DiskInsertSound = new SoundPathSpecifier("/Audio/_Arcadis/computer_startup.ogg");
}
131 changes: 131 additions & 0 deletions Content.Shared/_Arcadis/Computer/ModularComputerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Coordinates;
using Robust.Shared.Audio;
using Content.Shared.Audio;
using Robust.Shared.Network;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Audio.Systems;
using Content.Shared.Popups;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Robust.Shared.Timing;

namespace Content.Shared._Arcadis.Computer;

public sealed class ModularComputerSystem : EntitySystem
{
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;

[Dependency] private readonly SharedAudioSystem _audioSystem = default!;

[Dependency] private readonly SharedPopupSystem _popupSystem = default!;

[Dependency] private readonly INetManager _netMan = default!;

[Dependency] private readonly SharedTransformSystem _transform = default!;

[Dependency] private readonly IGameTiming _gameTiming = default!;

public string BlankDiskPrototype = "UnburnedDiskPrototype";
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<ModularComputerComponent, EntInsertedIntoContainerMessage>(InsertDisk);
SubscribeLocalEvent<ModularComputerComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<ModularComputerComponent, ExaminedEvent>(OnExamined);
}

public override void Update(float frameTime)
{
base.Update(frameTime);
}

private void OnExamined(EntityUid uid, ModularComputerComponent component, ExaminedEvent args)
{
if (!TryComp(uid, out ItemSlotsComponent? slots)
|| !_itemSlots.TryGetSlot(uid, component.DiskSlot, out var diskSlot, slots))
return;

if (diskSlot.Item == null || !TryComp(diskSlot.Item, out ComputerDiskComponent? diskComp))
{
args.PushMarkup(Loc.GetString("modular-computer-examine-no-disk"));
return;
}

if (diskComp.ProgramPrototypeEntity == null)
{
args.PushMarkup(Loc.GetString("modular-computer-examine-disk-error"));
return;
}

args.PushMarkup(Loc.GetString("modular-computer-examine-has-program", ("program", EntityManager.GetComponent<MetaDataComponent>(diskComp.ProgramPrototypeEntity.Value).EntityName)));
}
private void OnActivate(EntityUid uid, ModularComputerComponent component, ActivateInWorldEvent args)
{
// go figure it out yourself
if (!TryComp(uid, out ItemSlotsComponent? slots)
|| !_itemSlots.TryGetSlot(uid, component.DiskSlot, out var diskSlot, slots))
return;

if (diskSlot.Item == null || !TryComp(diskSlot.Item, out ComputerDiskComponent? diskComp))
{
_popupSystem.PopupPredicted(Loc.GetString("modular-computer-no-program"), uid, args.User);
return;
}

if (diskComp.ProgramPrototypeEntity == null)
{
_popupSystem.PopupPredicted(Loc.GetString("modular-computer-no-program-on-disk"), uid, args.User);
return;
}

if (_gameTiming.IsFirstTimePredicted || _netMan.IsServer) {
var activateMsg = new ActivateInWorldEvent(args.User, diskComp.ProgramPrototypeEntity.Value, true);
RaiseLocalEvent(diskComp.ProgramPrototypeEntity.Value, activateMsg);
}
}

private void InsertDisk(EntityUid uid, ModularComputerComponent component, EntInsertedIntoContainerMessage args)
{
if (args.Container.ID != component.DiskSlot
|| !TryComp(uid, out ItemSlotsComponent? slots)
|| !_itemSlots.TryGetSlot(uid, component.DiskSlot, out var diskSlot, slots)
|| diskSlot.Item is null
|| !TryComp(diskSlot.Item, out ComputerDiskComponent? diskComp))
return;

UpdateComputer((uid, component), diskComp, diskSlot);

if (diskComp.ProgramPrototypeEntity is null
|| _netMan.IsClient)
return;

_audioSystem.PlayPvs(component.DiskInsertSound, uid, AudioParams.Default.WithVolume(+4f));
}


private void UpdateComputer(Entity<ModularComputerComponent> computer, ComputerDiskComponent diskComp, ItemSlot diskSlot)
{
if (diskSlot.Item is null
|| diskComp.ProgramPrototype == BlankDiskPrototype)
return;

EntityUid magicComputerEntity;

if (diskComp.ProgramPrototypeEntity == null || diskComp.PersistState != true)
{
if (diskComp.ProgramPrototypeEntity != null)
QueueDel(diskComp.ProgramPrototypeEntity.Value);

magicComputerEntity = Spawn(diskComp.ProgramPrototype, computer.Owner.ToCoordinates());
diskComp.ProgramPrototypeEntity = magicComputerEntity;
}
else
magicComputerEntity = diskComp.ProgramPrototypeEntity.Value;

_transform.SetParent(magicComputerEntity, diskSlot.Item.Value);
}
}
Binary file added Resources/Audio/_Arcadis/computer_startup.ogg
Binary file not shown.
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/_Arcadis/modularComputer.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
modular-computer-no-program = ERROR: No program loaded!
modular-computer-no-program-on-disk = ERROR: No program on disk!
modular-computer-examine-no-disk = This computer doesn't have a program loaded.
modular-computer-examine-disk-error = This computer doesn't have a program loaded. An error on the display reports that the loaded disk has no program.
modular-computer-examine-has-program = This computer has the {$program} program loaded.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
- type: entity
parent: BaseComputer
id: BaseComputerModular
name: modular computer
description: Part of a recent initiative to make computers less static. Comes with a disk slot for various "program disks".
components:
- type: ModularComputer
# I plan to make modular itemslots a thing in the future for stuff like the fax machine. Coming Soon:tm:
- type: ItemSlots
slots:
modularComputerDiskSlot:
name: Disk
insertSound:
path: /Audio/Machines/terminal_insert_disc.ogg
ejectSound:
path: /Audio/Machines/terminal_insert_disc.ogg



Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- type: entity
id: UnburnedDiskPrototype
name: unburned disk dummy prototype
categories: [HideSpawnMenu]

- type: entity
id: CrewMonitorDiskPrototype
name: Crew Monitor
categories: [HideSpawnMenu]
components:
- type: ActivatableUI
key: enum.CrewMonitoringUIKey.Key
- type: UserInterface
interfaces:
enum.CrewMonitoringUIKey.Key:
type: CrewMonitoringBoundUserInterface
- type: CrewMonitoringConsole
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: CrewMonitor
- type: WirelessNetworkConnection
range: 1200

- type: entity
id: CommunicationsConsoleDiskPrototype
name: Communications Console
categories: [HideSpawnMenu]
components:
- type: AccessReader
access: [["Command"]]
- type: CommunicationsConsole
title: comms-console-announcement-title-station
- type: DeviceNetwork
transmitFrequencyId: ShuttleTimer
- type: ActivatableUI
key: enum.CommunicationsConsoleUiKey.Key
- type: UserInterface
interfaces:
enum.CommunicationsConsoleUiKey.Key:
type: CommunicationsConsoleBoundUserInterface
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- type: entity
parent: BaseItem
id: BaseProgramDisk
abstract: true
name: program disk
components:
- type: Sprite
sprite: Objects/Misc/cd.rsi
state: icon
- type: ComputerDisk
saveData: false

- type: entity
parent: BaseProgramDisk
id: ProgramDiskCrewMonitor
name: program disk (crew monitor)
description: A diskette for usage in a computer. This one has the "Crew Monitor" program burnt to it.
components:
- type: ComputerDisk
programPrototype: CrewMonitorDiskPrototype
persistState: true

- type: entity
parent: BaseProgramDisk
id: ProgramDiskCommunicationsConsole
name: program disk (communications console)
description: A diskette for usage in a computer. This one has the "Communications Console" program burnt to it.
components:
- type: ComputerDisk
programPrototype: CommunicationsConsoleDiskPrototype
persistState: true

- type: entity
parent: BaseProgramDisk
id: ProgramDiskUnburnt
name: program disk
description: A diskette for usage in a computer. This one has no program burnt to it.
components:
- type: ComputerDisk
programPrototype: UnburnedDiskPrototype
Loading