Skip to content

Commit

Permalink
Mail Metrics: access from anywhere, consistent error tracking. (new-f…
Browse files Browse the repository at this point in the history
…rontiers-14#1885)

* mail sector service, log only first failure

* MailSystem: missed damaged check

* Update mail.yml

* Update pda.yml

* Frontier: better(?) comments on MailMetrics chngs

---------

Co-authored-by: Dvir <[email protected]>
  • Loading branch information
whatston3 and dvir001 authored Aug 18, 2024
1 parent 659e36b commit 2b7039f
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
namespace Content.Server.DeltaV.Cargo.Components;

/// <summary>
/// Added to the abstract representation of a station to track stats related to mail delivery and income
/// Tracks all mail statistics for mail activity in the sector.
/// </summary>
[RegisterComponent, Access(typeof(SharedCargoSystem))]
public sealed partial class StationLogisticStatsComponent : Component
public sealed partial class SectorLogisticStatsComponent : Component // Frontier: Station->Sector
{
[DataField]
public MailStats Metrics { get; set; }
Expand Down
23 changes: 11 additions & 12 deletions Content.Server/DeltaV/Cargo/Systems/LogisticStatsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,57 +12,56 @@ public override void Initialize()
}

[PublicAPI]
public void AddOpenedMailEarnings(EntityUid uid, StationLogisticStatsComponent component, int earnedMoney)
public void AddOpenedMailEarnings(SectorLogisticStatsComponent component, int earnedMoney) // Frontier: remove EntityUid as first arg
{
component.Metrics = component.Metrics with
{
Earnings = component.Metrics.Earnings + earnedMoney,
OpenedCount = component.Metrics.OpenedCount + 1
};
UpdateLogisticsStats(uid);
UpdateLogisticsStats(); // Frontier: remove EntityUid from args
}

[PublicAPI]
public void AddExpiredMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
public void AddExpiredMailLosses(SectorLogisticStatsComponent component, int lostMoney) // Frontier: remove EntityUid as first arg
{
component.Metrics = component.Metrics with
{
ExpiredLosses = component.Metrics.ExpiredLosses + lostMoney,
ExpiredCount = component.Metrics.ExpiredCount + 1
};
UpdateLogisticsStats(uid);
UpdateLogisticsStats(); // Frontier: remove EntityUid from args
}

[PublicAPI]
public void AddDamagedMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
public void AddDamagedMailLosses(SectorLogisticStatsComponent component, int lostMoney) // Frontier: remove EntityUid as first arg
{
component.Metrics = component.Metrics with
{
DamagedLosses = component.Metrics.DamagedLosses + lostMoney,
DamagedCount = component.Metrics.DamagedCount + 1
};
UpdateLogisticsStats(uid);
UpdateLogisticsStats(); // Frontier: remove EntityUid from args
}

[PublicAPI]
public void AddTamperedMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
public void AddTamperedMailLosses(SectorLogisticStatsComponent component, int lostMoney) // Frontier: remove EntityUid as first arg
{
component.Metrics = component.Metrics with
{
TamperedLosses = component.Metrics.TamperedLosses + lostMoney,
TamperedCount = component.Metrics.TamperedCount + 1
};
UpdateLogisticsStats(uid);
UpdateLogisticsStats(); // Frontier: remove EntityUid from args
}

private void UpdateLogisticsStats(EntityUid uid) => RaiseLocalEvent(new LogisticStatsUpdatedEvent(uid));
private void UpdateLogisticsStats() => RaiseLocalEvent(new LogisticStatsUpdatedEvent()); // Frontier: remove EntityUid from args
}

// Frontier: removed station EntityUid as an argument in LogisticStatsUpdatedEvent
public sealed class LogisticStatsUpdatedEvent : EntityEventArgs
{
public EntityUid Station;
public LogisticStatsUpdatedEvent(EntityUid station)
public LogisticStatsUpdatedEvent()
{
Station = station;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
namespace Content.Server.DeltaV.CartridgeLoader.Cartridges;

// Frontier: removed the EntityUid of the station from the component
[RegisterComponent, Access(typeof(MailMetricsCartridgeSystem))]
public sealed partial class MailMetricsCartridgeComponent : Component
{
/// <summary>
/// Station entity keeping track of logistics stats
/// </summary>
[DataField]
public EntityUid? Station;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using Content.Server.DeltaV.Cargo.Components;
using Content.Server.DeltaV.Cargo.Systems;
using Content.Server.Station.Systems;
using Content.Server.CartridgeLoader;
using Content.Shared.CartridgeLoader;
using Content.Shared.CartridgeLoader.Cartridges;
using Content.Server.Mail.Components;
using Content.Server._NF.SectorServices; // Frontier

namespace Content.Server.DeltaV.CartridgeLoader.Cartridges;

public sealed class MailMetricsCartridgeSystem : EntitySystem
{
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly SectorServiceSystem _sectorService = default!; // Frontier

public override void Initialize()
{
Expand All @@ -24,58 +24,59 @@ public override void Initialize()

private void OnUiReady(Entity<MailMetricsCartridgeComponent> ent, ref CartridgeUiReadyEvent args)
{
UpdateUI(ent, args.Loader);
UpdateUI(args.Loader); // Frontier: remove station as first arg
}

private void OnLogisticsStatsUpdated(LogisticStatsUpdatedEvent args)
{
UpdateAllCartridges(args.Station);
UpdateAllCartridges(); // Frontier: remove station
}

private void OnMapInit(EntityUid uid, MailComponent mail, MapInitEvent args)
{
if (_station.GetOwningStation(uid) is { } station)
UpdateAllCartridges(station);
UpdateAllCartridges(); // Frontier: remove station, no owner check
}

private void UpdateAllCartridges(EntityUid station)
private void UpdateAllCartridges() // Frontier: remove station
{
var query = EntityQueryEnumerator<MailMetricsCartridgeComponent, CartridgeComponent>();
while (query.MoveNext(out var uid, out var comp, out var cartridge))
{
if (cartridge.LoaderUid is not { } loader || comp.Station != station)
if (cartridge.LoaderUid is not { } loader)
continue;
UpdateUI((uid, comp), loader);
UpdateUI(loader);
}
}

private void UpdateUI(Entity<MailMetricsCartridgeComponent> ent, EntityUid loader)
private void UpdateUI(EntityUid loader)
{
if (_station.GetOwningStation(loader) is { } station)
ent.Comp.Station = station;
//if (_station.GetOwningStation(loader) is { } station) // Frontier
// ent.Comp.Station = station; // Frontier

if (!TryComp<StationLogisticStatsComponent>(ent.Comp.Station, out var logiStats))
return;
if (!TryComp<SectorLogisticStatsComponent>(_sectorService.GetServiceEntity(), out var logiStats)) // Frontier
return; // Frontier

// Get station's logistic stats
var unopenedMailCount = GetUnopenedMailCount(ent.Comp.Station);
var unopenedMailCount = GetUnopenedMailCount(); // Frontier: no station arg

// Send logistic stats to cartridge client
var state = new MailMetricUiState(logiStats.Metrics, unopenedMailCount);
_cartridgeLoader.UpdateCartridgeUiState(loader, state);
}


private int GetUnopenedMailCount(EntityUid? station)
private int GetUnopenedMailCount() // Frontier: remove EntityUid param
{
var unopenedMail = 0;

var query = EntityQueryEnumerator<MailComponent>();

while (query.MoveNext(out var uid, out var comp))
while (query.MoveNext(out var _, out var comp))
{
if (comp.IsLocked && _station.GetOwningStation(uid) == station)
// Frontier: remove station check, add profitable check (consider only possible profit as unopened)
if (comp.IsLocked && comp.IsProfitable)
unopenedMail++;
// End Frontier
}

return unopenedMail;
Expand Down
103 changes: 52 additions & 51 deletions Content.Server/Nyanotrasen/Mail/MailSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
using Robust.Shared.Audio.Systems;
using Timer = Robust.Shared.Timing.Timer;
using Content.Server.DeltaV.Cargo.Systems;
using Content.Server._NF.SectorServices;

namespace Content.Server.Mail
{
Expand All @@ -77,6 +78,7 @@ public sealed class MailSystem : EntitySystem
[Dependency] private readonly MindSystem _mindSystem = default!;
[Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
[Dependency] private readonly IEntityManager _entManager = default!; // Frontier
[Dependency] private readonly SectorServiceSystem _sectorService = default!; // Frontier

// DeltaV - system that keeps track of mail and cargo stats
[Dependency] private readonly LogisticStatsSystem _logisticsStatsSystem = default!;
Expand Down Expand Up @@ -231,13 +233,15 @@ private void OnAfterInteractUsing(EntityUid uid, MailComponent component, AfterI
}

UnlockMail(uid, component);
// DeltaV - Add earnings to logistic stats
ExecuteForEachLogisticsStats(uid, (station, logisticStats) =>
if (component.IsProfitable) // Frontier: update only when profitable
{
_logisticsStatsSystem.AddOpenedMailEarnings(station,
logisticStats,
component.IsProfitable ? component.Bounty : 0);
});
// DeltaV - Add earnings to logistic stats
ExecuteForEachLogisticsStats((logisticStats) =>
{
_logisticsStatsSystem.AddOpenedMailEarnings(logisticStats,
component.Bounty);
});
}

if (!component.IsProfitable)
{
Expand Down Expand Up @@ -320,17 +324,18 @@ private void OnDestruction(EntityUid uid, MailComponent component, DestructionEv
{
if (component.IsLocked)
{
bool wasProfitable = component.IsProfitable; // Frontier: cache mail profitability
PenalizeStationFailedDelivery(uid, component, "mail-penalty-lock");

// DeltaV - Damaged mail recorded to logistic stats
component.IsLocked = false; // Frontier: do not count this package as unopened.
ExecuteForEachLogisticsStats(uid, (station, logisticStats) =>
if (component.IsProfitable) // Frontier: update only when profitable
{
_logisticsStatsSystem.AddDamagedMailLosses(station,
logisticStats,
wasProfitable ? component.Penalty : 0);
});
PenalizeStationFailedDelivery(uid, component, "mail-penalty-lock");

// DeltaV - Damaged mail recorded to logistic stats
component.IsLocked = false; // Frontier: do not count this package as unopened.
ExecuteForEachLogisticsStats((logisticStats) =>
{
_logisticsStatsSystem.AddDamagedMailLosses(logisticStats,
component.Penalty);
});
}
}

// if (component.IsEnabled)
Expand Down Expand Up @@ -359,17 +364,15 @@ private void OnBreak(EntityUid uid, MailComponent component, BreakageEventArgs a
{
_appearanceSystem.SetData(uid, MailVisuals.IsBroken, true);

if (component.IsFragile)
if (component.IsFragile && component.IsProfitable) // Frontier: update only when profitable
{
bool wasProfitable = component.IsProfitable; // Frontier: cache mail profitability
PenalizeStationFailedDelivery(uid, component, "mail-penalty-fragile");

// DeltaV - Broken mail recorded to logistic stats
ExecuteForEachLogisticsStats(uid, (station, logisticStats) =>
ExecuteForEachLogisticsStats((logisticStats) =>
{
_logisticsStatsSystem.AddDamagedMailLosses(station,
logisticStats,
wasProfitable ? component.Penalty : 0);
_logisticsStatsSystem.AddDamagedMailLosses(logisticStats,
component.Penalty);
});
}
}
Expand All @@ -381,17 +384,19 @@ private void OnMailEmagged(EntityUid uid, MailComponent component, ref GotEmagge

UnlockMail(uid, component);

// Frontier: ding station on emag
bool wasProfitable = component.IsProfitable; // Frontier: cache mail profitability
PenalizeStationFailedDelivery(uid, component, "mail-penalty-lock");

// DeltaV - Tampered mail recorded to logistic stats
ExecuteForEachLogisticsStats(uid, (station, logisticStats) =>
// Frontier: penalize station on emag, but only if profitable
if (component.IsProfitable)
{
_logisticsStatsSystem.AddTamperedMailLosses(station,
logisticStats,
wasProfitable ? component.Penalty : 0);
});
PenalizeStationFailedDelivery(uid, component, "mail-penalty-lock");

// DeltaV - Tampered mail recorded to logistic stats
ExecuteForEachLogisticsStats((logisticStats) =>
{
_logisticsStatsSystem.AddTamperedMailLosses(logisticStats,
component.Penalty);
});
}
// End Frontier

_popupSystem.PopupEntity(Loc.GetString("mail-unlocked-by-emag"), uid, args.UserUid);

Expand Down Expand Up @@ -546,16 +551,17 @@ public void SetupMail(EntityUid uid, MailTeleporterComponent component, MailReci
Timer.Spawn((int) component.priorityDuration.TotalMilliseconds,
() =>
{
bool wasProfitable = mailComp.IsProfitable; // Frontier: cache mail profitability
PenalizeStationFailedDelivery(uid, mailComp, "mail-penalty-expired");

// DeltaV - Expired mail recorded to logistic stats
ExecuteForEachLogisticsStats(uid, (station, logisticStats) =>
if (mailComp.IsProfitable) // Frontier: only penalize and adjust stats if profitable
{
_logisticsStatsSystem.AddExpiredMailLosses(station,
logisticStats,
wasProfitable ? mailComp.Penalty : 0);
});
PenalizeStationFailedDelivery(uid, mailComp, "mail-penalty-expired");

// DeltaV - Expired mail recorded to logistic stats
ExecuteForEachLogisticsStats((logisticStats) =>
{
_logisticsStatsSystem.AddExpiredMailLosses(logisticStats,
mailComp.Penalty);
});
}
},
mailComp.priorityCancelToken.Token);
}
Expand Down Expand Up @@ -823,17 +829,12 @@ private void UpdateMailTrashState(EntityUid uid, bool isTrash)

// DeltaV - Helper function that executes for each StationLogisticsStatsComponent
// For updating MailMetrics stats
private void ExecuteForEachLogisticsStats(EntityUid uid,
Action<EntityUid, StationLogisticStatsComponent> action)
private void ExecuteForEachLogisticsStats(Action<SectorLogisticStatsComponent> action)
{

var query = EntityQueryEnumerator<StationLogisticStatsComponent>();
while (query.MoveNext(out var station, out var logisticStats))
{
//if (_stationSystem.GetOwningStation(uid) != station) # Frontier - No need for this test
// continue;
action(station, logisticStats);
}
// Frontier: use service entity - there should be only one
if (TryComp(_sectorService.GetServiceEntity(), out SectorLogisticStatsComponent? logisticStats))
action(logisticStats);
// End Frontier
}
}

Expand Down
2 changes: 1 addition & 1 deletion Resources/Prototypes/Entities/Objects/Devices/pda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
# - type: WirelessNetworkConnection # Frontier
# range: 500 # Frontier
- type: CartridgeLoader
diskSpace: 7 # Frontier - Too many programs 5<7
diskSpace: 8 # Frontier - Too many programs 5<8
uiKey: enum.PdaUiKey.Key
preinstalled:
- CrewManifestCartridge
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
abstract: true
components:
- type: StationMailRouter
- type: StationLogisticStats # DeltaV - Tracks statistics related to mail and income
1 change: 1 addition & 0 deletions Resources/Prototypes/_NF/Catalog/Fills/Lockers/mail.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
contents:
- id: ClothingOuterWinterCoatMail
- id: ClothingEyesHudMail
- id: MailMetricsCartridge
- id: WeaponMailLake
- id: BoxMailCapsulePrimed
amount: 2
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
id: PirateBounties
components:
- type: SectorPirateBountyDatabase

- type: sectorService
id: MailMetrics
components:
- type: SectorLogisticStats

0 comments on commit 2b7039f

Please sign in to comment.