fix cargo teleporter (#27255)

* fix cargo teleporter

* don't delete orders

* basado
This commit is contained in:
Nemanja
2024-04-23 08:07:12 -04:00
committed by GitHub
parent 8117131c91
commit 1bfc63c546
8 changed files with 133 additions and 37 deletions

View File

@@ -1,4 +1,6 @@
using Content.Server.Station.Components;
using Content.Shared.Cargo; using Content.Shared.Cargo;
using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Prototypes; using Content.Shared.Cargo.Prototypes;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
@@ -38,3 +40,17 @@ public sealed partial class StationCargoOrderDatabaseComponent : Component
[DataField] [DataField]
public EntProtoId PrinterOutput = "PaperCargoInvoice"; public EntProtoId PrinterOutput = "PaperCargoInvoice";
} }
/// <summary>
/// Event broadcast before a cargo order is fulfilled, allowing alternate systems to fulfill the order.
/// </summary>
[ByRefEvent]
public record struct FulfillCargoOrderEvent(Entity<StationDataComponent> Station, CargoOrderData Order, Entity<CargoOrderConsoleComponent> OrderConsole)
{
public Entity<CargoOrderConsoleComponent> OrderConsole = OrderConsole;
public Entity<StationDataComponent> Station = Station;
public CargoOrderData Order = Order;
public EntityUid? FulfillmentEntity;
public bool Handled = false;
}

View File

@@ -170,14 +170,21 @@ namespace Content.Server.Cargo.Systems
return; return;
} }
var tradeDestination = TryFulfillOrder(stationData, order, orderDatabase); var ev = new FulfillCargoOrderEvent((station.Value, stationData), order, (uid, component));
RaiseLocalEvent(ref ev);
ev.FulfillmentEntity ??= station.Value;
if (tradeDestination == null) if (!ev.Handled)
{
ev.FulfillmentEntity = TryFulfillOrder((station.Value, stationData), order, orderDatabase);
if (ev.FulfillmentEntity == null)
{ {
ConsolePopup(args.Session, Loc.GetString("cargo-console-unfulfilled")); ConsolePopup(args.Session, Loc.GetString("cargo-console-unfulfilled"));
PlayDenySound(uid, component); PlayDenySound(uid, component);
return; return;
} }
}
_idCardSystem.TryFindIdCard(player, out var idCard); _idCardSystem.TryFindIdCard(player, out var idCard);
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
@@ -193,7 +200,7 @@ namespace Content.Server.Cargo.Systems
("approverJob", approverJob), ("approverJob", approverJob),
("cost", cost)); ("cost", cost));
_radio.SendRadioMessage(uid, message, component.AnnouncementChannel, uid, escapeMarkup: false); _radio.SendRadioMessage(uid, message, component.AnnouncementChannel, uid, escapeMarkup: false);
ConsolePopup(args.Session, Loc.GetString("cargo-console-trade-station", ("destination", MetaData(tradeDestination.Value).EntityName))); ConsolePopup(args.Session, Loc.GetString("cargo-console-trade-station", ("destination", MetaData(ev.FulfillmentEntity.Value).EntityName)));
// Log order approval // Log order approval
_adminLogger.Add(LogType.Action, LogImpact.Low, _adminLogger.Add(LogType.Action, LogImpact.Low,
@@ -201,10 +208,10 @@ namespace Content.Server.Cargo.Systems
orderDatabase.Orders.Remove(order); orderDatabase.Orders.Remove(order);
DeductFunds(bank, cost); DeductFunds(bank, cost);
UpdateOrders(station.Value, orderDatabase); UpdateOrders(station.Value);
} }
private EntityUid? TryFulfillOrder(StationDataComponent stationData, CargoOrderData order, StationCargoOrderDatabaseComponent orderDatabase) private EntityUid? TryFulfillOrder(Entity<StationDataComponent> stationData, CargoOrderData order, StationCargoOrderDatabaseComponent orderDatabase)
{ {
// No slots at the trade station // No slots at the trade station
_listEnts.Clear(); _listEnts.Clear();
@@ -357,7 +364,7 @@ namespace Content.Server.Cargo.Systems
/// Updates all of the cargo-related consoles for a particular station. /// Updates all of the cargo-related consoles for a particular station.
/// This should be called whenever orders change. /// This should be called whenever orders change.
/// </summary> /// </summary>
private void UpdateOrders(EntityUid dbUid, StationCargoOrderDatabaseComponent _) private void UpdateOrders(EntityUid dbUid)
{ {
// Order added so all consoles need updating. // Order added so all consoles need updating.
var orderQuery = AllEntityQuery<CargoOrderConsoleComponent>(); var orderQuery = AllEntityQuery<CargoOrderConsoleComponent>();
@@ -392,7 +399,7 @@ namespace Content.Server.Cargo.Systems
string description, string description,
string dest, string dest,
StationCargoOrderDatabaseComponent component, StationCargoOrderDatabaseComponent component,
StationDataComponent stationData Entity<StationDataComponent> stationData
) )
{ {
DebugTools.Assert(_protoMan.HasIndex<EntityPrototype>(spawnId)); DebugTools.Assert(_protoMan.HasIndex<EntityPrototype>(spawnId));
@@ -414,7 +421,7 @@ namespace Content.Server.Cargo.Systems
private bool TryAddOrder(EntityUid dbUid, CargoOrderData data, StationCargoOrderDatabaseComponent component) private bool TryAddOrder(EntityUid dbUid, CargoOrderData data, StationCargoOrderDatabaseComponent component)
{ {
component.Orders.Add(data); component.Orders.Add(data);
UpdateOrders(dbUid, component); UpdateOrders(dbUid);
return true; return true;
} }
@@ -432,7 +439,7 @@ namespace Content.Server.Cargo.Systems
{ {
orderDB.Orders.RemoveAt(sequenceIdx); orderDB.Orders.RemoveAt(sequenceIdx);
} }
UpdateOrders(dbUid, orderDB); UpdateOrders(dbUid);
} }
public void ClearOrders(StationCargoOrderDatabaseComponent component) public void ClearOrders(StationCargoOrderDatabaseComponent component)

View File

@@ -1,9 +1,13 @@
using System.Linq;
using Content.Server.Cargo.Components; using Content.Server.Cargo.Components;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Station.Components;
using Content.Shared.Cargo; using Content.Shared.Cargo;
using Content.Shared.Cargo.Components; using Content.Shared.Cargo.Components;
using Content.Shared.DeviceLinking; using Content.Shared.DeviceLinking;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Server.Cargo.Systems; namespace Content.Server.Cargo.Systems;
@@ -13,10 +17,44 @@ public sealed partial class CargoSystem
private void InitializeTelepad() private void InitializeTelepad()
{ {
SubscribeLocalEvent<CargoTelepadComponent, ComponentInit>(OnInit); SubscribeLocalEvent<CargoTelepadComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<CargoTelepadComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<CargoTelepadComponent, PowerChangedEvent>(OnTelepadPowerChange); SubscribeLocalEvent<CargoTelepadComponent, PowerChangedEvent>(OnTelepadPowerChange);
// Shouldn't need re-anchored event // Shouldn't need re-anchored event
SubscribeLocalEvent<CargoTelepadComponent, AnchorStateChangedEvent>(OnTelepadAnchorChange); SubscribeLocalEvent<CargoTelepadComponent, AnchorStateChangedEvent>(OnTelepadAnchorChange);
SubscribeLocalEvent<FulfillCargoOrderEvent>(OnTelepadFulfillCargoOrder);
} }
private void OnTelepadFulfillCargoOrder(ref FulfillCargoOrderEvent 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;
// todo cannot be fucking asked to figure out device linking rn but this shouldn't just default to the first port.
if (!TryComp<DeviceLinkSinkComponent>(uid, out var sinkComponent) ||
sinkComponent.LinkedSources.FirstOrNull() is not { } console ||
console != args.OrderConsole.Owner)
continue;
for (var i = 0; i < args.Order.OrderQuantity; i++)
{
tele.CurrentOrders.Add(args.Order);
}
tele.Accumulator = tele.Delay;
args.Handled = true;
args.FulfillmentEntity = uid;
return;
}
}
private void UpdateTelepad(float frameTime) private void UpdateTelepad(float frameTime)
{ {
var query = EntityQueryEnumerator<CargoTelepadComponent>(); var query = EntityQueryEnumerator<CargoTelepadComponent>();
@@ -33,14 +71,6 @@ public sealed partial class CargoSystem
continue; continue;
} }
if (!TryComp<DeviceLinkSinkComponent>(uid, out var sinkComponent) ||
sinkComponent.LinkedSources.FirstOrNull() is not { } console ||
!HasComp<CargoOrderConsoleComponent>(console))
{
comp.Accumulator = comp.Delay;
continue;
}
comp.Accumulator -= frameTime; comp.Accumulator -= frameTime;
// Uhh listen teleporting takes time and I just want the 1 float. // Uhh listen teleporting takes time and I just want the 1 float.
@@ -51,21 +81,22 @@ public sealed partial class CargoSystem
continue; continue;
} }
var station = _station.GetOwningStation(console); if (comp.CurrentOrders.Count == 0)
if (!TryComp<StationCargoOrderDatabaseComponent>(station, out var orderDatabase) ||
orderDatabase.Orders.Count == 0)
{ {
comp.Accumulator += comp.Delay; comp.Accumulator += comp.Delay;
continue; continue;
} }
var xform = Transform(uid); var xform = Transform(uid);
if (FulfillNextOrder(orderDatabase, xform.Coordinates, comp.PrinterOutput)) var currentOrder = comp.CurrentOrders.First();
if (FulfillOrder(currentOrder, xform.Coordinates, comp.PrinterOutput))
{ {
_audio.PlayPvs(_audio.GetSound(comp.TeleportSound), uid, AudioParams.Default.WithVolume(-8f)); _audio.PlayPvs(_audio.GetSound(comp.TeleportSound), uid, AudioParams.Default.WithVolume(-8f));
UpdateOrders(station.Value, orderDatabase);
if (_station.GetOwningStation(uid) is { } station)
UpdateOrders(station);
comp.CurrentOrders.Remove(currentOrder);
comp.CurrentState = CargoTelepadState.Teleporting; comp.CurrentState = CargoTelepadState.Teleporting;
_appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Teleporting, appearance); _appearance.SetData(uid, CargoTelepadVisuals.State, CargoTelepadState.Teleporting, appearance);
} }
@@ -79,6 +110,29 @@ public sealed partial class CargoSystem
_linker.EnsureSinkPorts(uid, telepad.ReceiverPort); _linker.EnsureSinkPorts(uid, telepad.ReceiverPort);
} }
private void OnShutdown(Entity<CargoTelepadComponent> ent, ref ComponentShutdown args)
{
if (ent.Comp.CurrentOrders.Count == 0)
return;
if (_station.GetStations().Count == 0)
return;
if (_station.GetOwningStation(ent) is not { } station)
{
station = _random.Pick(_station.GetStations().Where(HasComp<StationCargoOrderDatabaseComponent>).ToList());
}
if (!TryComp<StationCargoOrderDatabaseComponent>(station, out var db) ||
!TryComp<StationDataComponent>(station, out var data))
return;
foreach (var order in ent.Comp.CurrentOrders)
{
TryFulfillOrder((station, data), order, db);
}
}
private void SetEnabled(EntityUid uid, CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null, private void SetEnabled(EntityUid uid, CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null,
TransformComponent? xform = null) TransformComponent? xform = null)
{ {

View File

@@ -69,7 +69,7 @@ public sealed class CargoGiftsRule : StationEventSystem<CargoGiftsRuleComponent>
Loc.GetString(component.Description), Loc.GetString(component.Description),
Loc.GetString(component.Dest), Loc.GetString(component.Dest),
cargoDb, cargoDb,
stationData! (station.Value, stationData)
)) ))
{ {
break; break;

View File

@@ -1,47 +1,55 @@
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Content.Shared.Access.Components;
using System.Text; using System.Text;
namespace Content.Shared.Cargo namespace Content.Shared.Cargo
{ {
[NetSerializable, Serializable] [DataDefinition, NetSerializable, Serializable]
public sealed class CargoOrderData public sealed partial class CargoOrderData
{ {
/// <summary> /// <summary>
/// Price when the order was added. /// Price when the order was added.
/// </summary> /// </summary>
[DataField]
public int Price; public int Price;
/// <summary> /// <summary>
/// A unique (arbitrary) ID which identifies this order. /// A unique (arbitrary) ID which identifies this order.
/// </summary> /// </summary>
public readonly int OrderId; [DataField]
public int OrderId { get; private set; }
/// <summary> /// <summary>
/// Prototype Id for the item to be created /// Prototype Id for the item to be created
/// </summary> /// </summary>
public readonly string ProductId; [DataField]
public string ProductId { get; private set; }
/// <summary> /// <summary>
/// Prototype Name /// Prototype Name
/// </summary> /// </summary>
public readonly string ProductName; [DataField]
public string ProductName { get; private set; }
/// <summary> /// <summary>
/// The number of items in the order. Not readonly, as it might change /// The number of items in the order. Not readonly, as it might change
/// due to caps on the amount of orders that can be placed. /// due to caps on the amount of orders that can be placed.
/// </summary> /// </summary>
[DataField]
public int OrderQuantity; public int OrderQuantity;
/// <summary> /// <summary>
/// How many instances of this order that we've already dispatched /// How many instances of this order that we've already dispatched
/// </summary> /// </summary>
[DataField]
public int NumDispatched = 0; public int NumDispatched = 0;
public readonly string Requester; [DataField]
public string Requester { get; private set; }
// public String RequesterRank; // TODO Figure out how to get Character ID card data // public String RequesterRank; // TODO Figure out how to get Character ID card data
// public int RequesterId; // public int RequesterId;
public readonly string Reason; [DataField]
public string Reason { get; private set; }
public bool Approved => Approver is not null; public bool Approved => Approver is not null;
[DataField]
public string? Approver; public string? Approver;
public CargoOrderData(int orderId, string productId, string productName, int price, int amount, string requester, string reason) public CargoOrderData(int orderId, string productId, string productName, int price, int amount, string requester, string reason)

View File

@@ -12,11 +12,14 @@ namespace Content.Shared.Cargo.Components;
[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem))] [RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem))]
public sealed partial class CargoTelepadComponent : Component public sealed partial class CargoTelepadComponent : Component
{ {
[DataField]
public List<CargoOrderData> CurrentOrders = new();
/// <summary> /// <summary>
/// The actual amount of time it takes to teleport from the telepad /// The actual amount of time it takes to teleport from the telepad
/// </summary> /// </summary>
[DataField("delay"), ViewVariables(VVAccess.ReadWrite)] [DataField("delay"), ViewVariables(VVAccess.ReadWrite)]
public float Delay = 10f; public float Delay = 5f;
/// <summary> /// <summary>
/// How much time we've accumulated until next teleport. /// How much time we've accumulated until next teleport.

View File

@@ -47,3 +47,5 @@
board: CargoTelepadMachineCircuitboard board: CargoTelepadMachineCircuitboard
- type: Appearance - type: Appearance
- type: CollideOnAnchor - type: CollideOnAnchor
- type: NameIdentifier
group: CargoTelepads

View File

@@ -37,3 +37,9 @@
id: Bounty id: Bounty
minValue: 0 minValue: 0
maxValue: 999 maxValue: 999
- type: nameIdentifierGroup
id: CargoTelepads
prefix: TELE
minValue: 0
maxValue: 999