CargoSystem.Telepad Cleanup (#46215)

* SubscribeLocalEvent attr

* reorder

* Entity<T>

* Accumulator is kill

* naming consistency

* combining if statements

* database is one word

* needed

* This is called in SetData anyway

* small things

* This need to be before

* AutoPausedField

* Fixed unpowered telepad still working (oops)

* delay after repowered

* Update CargoSystem.Telepad.cs

---------

Co-authored-by: Pok245 <113675512+Pok27@users.noreply.github.com>
This commit is contained in:
riccardi48 2026-09-29 20:55:10 +00:00 • committed by GitHub
parent d3049a530e
commit 801c900b42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 108 additions and 137 deletions

View file

@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Cargo.Components;
using Content.Server.Power.Components;
@ -8,131 +7,35 @@ using Content.Shared.Cargo.Components;
using Content.Shared.DeviceLinking;
using Content.Shared.Power;
using Content.Shared.Station.Components;
using Robust.Shared.Audio;
using Robust.Shared.Random;
namespace Content.Server.Cargo.Systems;
public sealed partial class CargoSystem
{
private void InitializeTelepad()
[SubscribeLocalEvent]
private void OnInit(Entity<CargoTelepadComponent> ent, ref ComponentInit args)
{
SubscribeLocalEvent<CargoTelepadComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<CargoTelepadComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<CargoTelepadComponent, PowerChangedEvent>(OnTelepadPowerChange);
// Shouldn't need re-anchored event
SubscribeLocalEvent<CargoTelepadComponent, AnchorStateChangedEvent>(OnTelepadAnchorChange);
SubscribeLocalEvent<FulfillCargoOrderEvent>(OnTelepadFulfillCargoOrder);
_linker.EnsureSinkPorts(ent.Owner, ent.Comp.ReceiverPort);
}
private void OnTelepadFulfillCargoOrder(ref FulfillCargoOrderEvent args)
[SubscribeLocalEvent]
private void OnTelepadPowerChange(Entity<CargoTelepadComponent> ent, ref PowerChangedEvent args)
{
var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var tele, out var xform))
{
if (tele.CurrentState != CargoTelepadState.Idle)
continue;
if (!this.IsPowered(uid, EntityManager))
continue;
if (_station.GetOwningStation(uid, xform) != args.Station)
continue;
if (!IsLinkedToConsole(uid, GetEntity(args.Order.ApprovingConsole)))
continue;
tele.CurrentOrders.Add(args.Order);
tele.Accumulator = tele.Delay;
args.Handled = true;
args.FulfillmentEntity = uid;
return;
}
SetEnabled(ent);
}
private bool IsLinkedToConsole(
EntityUid uid,
EntityUid? approvingConsole
)
[SubscribeLocalEvent]
private void OnTelepadAnchorChange(Entity<CargoTelepadComponent> ent, ref AnchorStateChangedEvent args)
{
if (approvingConsole is null)
return false;
if (!TryComp<DeviceLinkSinkComponent>(uid, out var sinkComponent))
return false;
return sinkComponent.LinkedSources.Any(ent => ent == approvingConsole.Value);
}
private void UpdateTelepad(float frameTime)
{
var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var comp, out var xform))
{
// Don't EntityQuery for it as it's not required.
TryComp<AppearanceComponent>(uid, out var appearance);
if (comp.CurrentState == CargoTelepadState.Unpowered)
{
comp.Accumulator = comp.Delay;
continue;
}
comp.Accumulator -= frameTime;
// Uhh listen teleporting takes time and I just want the 1 float.
if (comp.Accumulator > 0f)
{
comp.CurrentState = CargoTelepadState.Idle;
_appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Idle, appearance);
continue;
}
if (comp.CurrentOrders.Count == 0)
{
comp.Accumulator += comp.Delay;
continue;
}
var currentOrder = comp.CurrentOrders.First();
if (currentOrder.NumDispatched >= currentOrder.OrderQuantity)
{
comp.CurrentOrders.Remove(currentOrder);
}
else if (FulfillOrder(currentOrder, currentOrder.Account, xform.Coordinates, comp.PrinterOutput))
{
currentOrder.NumDispatched++;
if (currentOrder.NumDispatched >= currentOrder.OrderQuantity)
comp.CurrentOrders.Remove(currentOrder);
var teleportSound = comp.TeleportSound;
var audioParams = teleportSound?.Params ?? AudioParams.Default;
audioParams = audioParams.AddVolume(-8f);
_audio.PlayPvs(_audio.ResolveSound(comp.TeleportSound), uid, audioParams);
if (_station.GetOwningStation(uid) is { } station)
UpdateOrders(station);
comp.CurrentState = CargoTelepadState.Teleporting;
_appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Teleporting, appearance);
}
comp.Accumulator += comp.Delay;
}
}
private void OnInit(EntityUid uid, CargoTelepadComponent telepad, ComponentInit args)
{
_linker.EnsureSinkPorts(uid, telepad.ReceiverPort);
SetEnabled(ent);
}
[SubscribeLocalEvent]
private void OnShutdown(Entity<CargoTelepadComponent> ent, ref ComponentShutdown args)
{
if (ent.Comp.CurrentOrders.Count == 0)
return;
if (_station.GetStations().Count == 0)
if (ent.Comp.CurrentOrders.Count == 0
|| _station.GetStations().Count == 0)
return;
if (_station.GetOwningStation(ent) is not { } station)
@ -140,21 +43,94 @@ public sealed partial class CargoSystem
station = _random.Pick(_station.GetStations().Where(x => _orderQuery.HasComp(x.Owner)).ToList());
}
if (!_orderQuery.TryComp(station, out var db) ||
!TryComp<StationDataComponent>(station, out var data))
if (!_orderQuery.TryComp(station, out var orderDatabase)
|| !TryComp<StationDataComponent>(station, out var data))
return;
foreach (var order in ent.Comp.CurrentOrders)
{
TryFulfillOrder((station, data), order.Account, order, db);
TryFulfillOrder((station, data), order.Account, order, orderDatabase);
}
}
private void SetEnabled(EntityUid uid, CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null,
TransformComponent? xform = null)
[SubscribeLocalEvent]
private void OnTelepadFulfillCargoOrder(ref FulfillCargoOrderEvent args)
{
var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var telepad, out var xform))
{
if (telepad.CurrentState != CargoTelepadState.Idle
|| !this.IsPowered(uid, EntityManager)
|| _station.GetOwningStation(uid, xform) != args.Station
|| !IsLinkedToConsole(uid, GetEntity(args.Order.ApprovingConsole)))
continue;
telepad.NextTeleport = Timing.CurTime + telepad.Delay;
telepad.CurrentOrders.Add(args.Order);
args.Handled = true;
args.FulfillmentEntity = uid;
return;
}
}
private void UpdateTelepad()
{
var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var telepad, out var xform))
{
if (telepad.CurrentState == CargoTelepadState.Unpowered)
continue;
if (Timing.CurTime < telepad.NextTeleport)
{
telepad.CurrentState = CargoTelepadState.Idle;
_appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Idle);
continue;
}
telepad.NextTeleport = Timing.CurTime + telepad.Delay;
if (telepad.CurrentOrders.Count == 0)
continue;
var currentOrder = telepad.CurrentOrders.First();
if (currentOrder.NumDispatched >= currentOrder.OrderQuantity)
{
telepad.CurrentOrders.Remove(currentOrder);
}
else if (FulfillOrder(currentOrder, currentOrder.Account, xform.Coordinates, telepad.PrinterOutput))
{
currentOrder.NumDispatched++;
if (currentOrder.NumDispatched >= currentOrder.OrderQuantity)
telepad.CurrentOrders.Remove(currentOrder);
var teleportSound = telepad.TeleportSound;
var audioParams = teleportSound.Params;
audioParams = audioParams.AddVolume(-8f);
_audio.PlayPvs(_audio.ResolveSound(telepad.TeleportSound), uid, audioParams);
if (_station.GetOwningStation(uid) is { } station)
UpdateOrders(station);
telepad.CurrentState = CargoTelepadState.Teleporting;
_appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Teleporting);
}
}
}
private bool IsLinkedToConsole(EntityUid uid, EntityUid? approvingConsole)
{
if (approvingConsole is null
|| !TryComp<DeviceLinkSinkComponent>(uid, out var sinkComponent))
return false;
return sinkComponent.LinkedSources.Any(ent => ent == approvingConsole.Value);
}
private void SetEnabled(Entity<CargoTelepadComponent> ent, ApcPowerReceiverComponent? receiver = null, TransformComponent? xform = null)
{
// False due to AllCompsOneEntity test where they may not have the powerreceiver.
if (!Resolve(uid, ref receiver, ref xform, false))
if (!Resolve(ent.Owner, ref receiver, ref xform, false))
return;
var disabled = !receiver.Powered || !xform.Anchored;
@ -163,20 +139,15 @@ public sealed partial class CargoSystem
// Only change to Idle if off
// don't overwrite teleporting state
if (disabled)
component.CurrentState = CargoTelepadState.Unpowered;
else if (component.CurrentState == CargoTelepadState.Unpowered)
component.CurrentState = CargoTelepadState.Idle;
{
ent.Comp.CurrentState = CargoTelepadState.Unpowered;
}
else if (ent.Comp.CurrentState == CargoTelepadState.Unpowered)
{
ent.Comp.NextTeleport = Timing.CurTime + ent.Comp.Delay;
ent.Comp.CurrentState = CargoTelepadState.Idle;
}
_appearance.SetData(uid, CargoTelepadVisuals.State, component.CurrentState);
}
private void OnTelepadPowerChange(EntityUid uid, CargoTelepadComponent component, ref PowerChangedEvent args)
{
SetEnabled(uid, component);
}
private void OnTelepadAnchorChange(EntityUid uid, CargoTelepadComponent component, ref AnchorStateChangedEvent args)
{
SetEnabled(uid, component);
_appearance.SetData(ent.Owner, CargoTelepadVisuals.State, ent.Comp.CurrentState);
}
}

View file

@ -62,7 +62,6 @@ public sealed partial class CargoSystem : SharedCargoSystem
{
base.Initialize();
InitializeShuttle();
InitializeTelepad();
InitializeBounty();
InitializeFunds();
}
@ -71,7 +70,7 @@ public sealed partial class CargoSystem : SharedCargoSystem
{
base.Update(frameTime);
UpdateConsole();
UpdateTelepad(frameTime);
UpdateTelepad();
UpdateBounty();
}
}

View file

@ -2,29 +2,30 @@ using Content.Shared.DeviceLinking;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Cargo.Components;
/// <summary>
/// Handles teleporting in requested cargo after the specified delay.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem))]
[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem)), AutoGenerateComponentPause]
public sealed partial class CargoTelepadComponent : Component
{
[DataField]
public List<CargoOrderData> CurrentOrders = new();
/// <summary>
/// The actual amount of time it takes to teleport from the telepad
/// The delay between each teleport in seconds
/// </summary>
[DataField]
public float Delay = 5f;
public TimeSpan Delay = TimeSpan.FromSeconds(5);
/// <summary>
/// How much time we've accumulated until next teleport.
/// The next time the teleporter can teleport.
/// </summary>
[DataField]
public float Accumulator;
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan NextTeleport;
[DataField]
public CargoTelepadState CurrentState = CargoTelepadState.Unpowered;