From bd368512296c19a1cca7a946094b9df8d68f1f70 Mon Sep 17 00:00:00 2001 From: Livyathan Date: Wed, 13 May 2026 22:17:40 -0400 Subject: [PATCH 1/4] re-enable mail services --- Resources/Prototypes/_NF/SectorServices/services.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/_NF/SectorServices/services.yml b/Resources/Prototypes/_NF/SectorServices/services.yml index 12314b05047..973fc3a672e 100644 --- a/Resources/Prototypes/_NF/SectorServices/services.yml +++ b/Resources/Prototypes/_NF/SectorServices/services.yml @@ -7,6 +7,7 @@ id: Mail components: - type: SectorLogisticStats + - type: SectorMail # Contains sector-wide mail parameters - type: sectorService id: ShuttleRecords From 1ac929691a376cfecdcbbc276ca2bfd57730dec1 Mon Sep 17 00:00:00 2001 From: Livyathan Date: Wed, 13 May 2026 23:07:40 -0400 Subject: [PATCH 2/4] theoretical improvements --- .../_DV/Mail/EntitySystems/MailSystem.cs | 99 +++++++++++-------- Content.Server/_DV/Mail/MailCommands.cs | 4 +- 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/Content.Server/_DV/Mail/EntitySystems/MailSystem.cs b/Content.Server/_DV/Mail/EntitySystems/MailSystem.cs index 534b9c4ad29..63ac33d8d51 100644 --- a/Content.Server/_DV/Mail/EntitySystems/MailSystem.cs +++ b/Content.Server/_DV/Mail/EntitySystems/MailSystem.cs @@ -7,7 +7,6 @@ using Content.Server.Destructible.Thresholds.Triggers; using Content.Server.Destructible.Thresholds; using Content.Server.Destructible; -using Content.Server.Mind; using Content.Server.Popups; using Content.Server.Spawners.EntitySystems; using Content.Server.Station.Systems; @@ -64,7 +63,6 @@ public sealed class MailSystem : EntitySystem [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IdCardSystem _idCardSystem = default!; [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; - // [Dependency] private readonly MindSystem _mindSystem = default!; // Frontier: warning suppression [Dependency] private readonly OpenableSystem _openable = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; @@ -85,6 +83,8 @@ public sealed class MailSystem : EntitySystem private static readonly ProtoId MailTag = "Mail"; // Frontier private static readonly ProtoId TrashTag = "Trash"; // Frontier private static readonly ProtoId RecyclableTag = "Recyclable"; // Frontier + private bool _loggedNoValidTeleporters; // HardLight + private bool _loggedNoCandidates; // HardLight public override void Initialize() { @@ -461,6 +461,34 @@ private bool TryMatchJobTitleToPrototype(string jobTitle, [NotNullWhen(true)] ou return jobPrototype != null; } + // HardLight start + private static void MergeParcelWeights(Dictionary target, IReadOnlyDictionary source) + { + foreach (var (key, value) in source) + { + target[key] = value; + } + } + + private void LogNoValidTeleportersOnce() + { + if (_loggedNoValidTeleporters) + return; + + _loggedNoValidTeleporters = true; + _sawmill.Info("List of valid mail teleporters was empty!"); + } + + private void LogNoCandidatesOnce() + { + if (_loggedNoCandidates) + return; + + _loggedNoCandidates = true; + _sawmill.Info("List of mail candidates was empty!"); + } + // HardLight end + /// /// Handle all the gritty details particular to a new mail entity. /// @@ -554,29 +582,27 @@ public void SetupMail(EntityUid uid, SectorMailComponent component, MailRecipien } /// - /// Return the parcels waiting for delivery. + /// Return how many parcels are waiting for delivery on this teleporter's tile. // HardLight: Rephrased /// - /// The mail teleporter to check. - private List GetUndeliveredParcels(EntityUid uid) + private uint GetUndeliveredParcelCount(EntityUid uid) // HardLight { // An alternative solution would be to keep a list of the unopened // parcels spawned by the teleporter and see if they're not carried // by someone, but this is simple, and simple is good. var coordinates = Transform(uid).Coordinates; const LookupFlags lookupFlags = LookupFlags.Dynamic | LookupFlags.Sundries; - var entitiesInTile = _lookup.GetEntitiesIntersecting(coordinates, lookupFlags); - return entitiesInTile.Where(HasComp).ToList(); - } + // HardLight start + uint count = 0; + foreach (var entity in entitiesInTile) + { + if (HasComp(entity)) + count++; + } - /// - /// Return how many parcels are waiting for delivery. - /// - /// The mail teleporter to check. - private uint GetUndeliveredParcelCount(EntityUid uid) - { - return (uint)GetUndeliveredParcels(uid).Count; + return count; + // HardLight end } /// @@ -642,7 +668,6 @@ public bool TryGetMailRecipientForReceiver(EntityUid receiverUid, [NotNullWhen(t // End Frontier var accessTags = access.Tags; - //var mayReceivePriorityMail = !(_mindSystem.GetMind(receiverUid) == null); recipient = new MailRecipient( idCard.Comp.FullName, @@ -665,25 +690,12 @@ private List GetMailRecipientCandidates() // Frontier: remove Ent { var candidateList = new List(); var query = EntityQueryEnumerator(); - //var teleporterStation = _stationSystem.GetOwningStation(uid); // Frontier: unnecessary while (query.MoveNext(out var receiverUid, out _)) { - var location = Transform(receiverUid); - - // Frontier: sector-wide mail - // var receiverStation = _stationSystem.GetOwningStation(receiverUid); - // if (receiverStation != teleporterStation) - // continue; - - // Are you on expedition or in FTL? No mail for you. - if (location.MapID != Transform(receiverUid).MapID) - continue; - // Is this player displaying as SSD? If so, skip 'em. if (TryComp(receiverUid, out SSDIndicatorComponent? ssd) && ssd.IsSSD) continue; - // End Frontier // Skip ghosts and adminghosts if (HasComp(receiverUid) || HasComp(receiverUid)) @@ -723,17 +735,19 @@ private void SpawnMail(SectorMailComponent component) // If list of teleporters is empty, return. if (validTeleporters.Count <= 0) { - _sawmill.Info("List of valid mail teleporters was empty!"); + LogNoValidTeleportersOnce(); // HardLight return; } + _loggedNoValidTeleporters = false; // HardLight var candidateList = GetMailRecipientCandidates(); if (candidateList.Count <= 0) { - _sawmill.Info("List of mail candidates was empty!"); + LogNoCandidatesOnce(); // HardLight return; } + _loggedNoCandidates = false; // HardLight if (!_prototypeManager.TryIndex(component.MailPool, out var pool)) { @@ -742,28 +756,33 @@ private void SpawnMail(SectorMailComponent component) } var deliveryCount = component.MinimumDeliveriesPerTeleport + candidateList.Count / component.CandidatesPerDelivery; + var remainingCandidates = new List(candidateList); // HardLight + _random.Shuffle(remainingCandidates); // HardLight for (var i = 0; i < deliveryCount; i++) { - var candidate = _random.Pick(candidateList); + // HardLight start + if (remainingCandidates.Count == 0) + { + remainingCandidates = new List(candidateList); + _random.Shuffle(remainingCandidates); + } + + var candidate = remainingCandidates[^1]; + remainingCandidates.RemoveAt(remainingCandidates.Count - 1); + // HardLight end var possibleParcels = new Dictionary(pool.Everyone); if (TryMatchJobTitleToPrototype(candidate.Job, out var jobPrototype) && pool.Jobs.TryGetValue(jobPrototype.ID, out var jobParcels)) { - possibleParcels = possibleParcels - .Concat(jobParcels) - .GroupBy(g => g.Key) - .ToDictionary(pair => pair.Key, pair => pair.First().Value); + MergeParcelWeights(possibleParcels, jobParcels); // HardLight } if (TryMatchJobTitleToDepartment(candidate.Job, out var department) && pool.Departments.TryGetValue(department, out var departmentParcels)) { - possibleParcels = possibleParcels - .Concat(departmentParcels) - .GroupBy(g => g.Key) - .ToDictionary(pair => pair.Key, pair => pair.First().Value); + MergeParcelWeights(possibleParcels, departmentParcels); // HardLight } var accumulated = 0f; diff --git a/Content.Server/_DV/Mail/MailCommands.cs b/Content.Server/_DV/Mail/MailCommands.cs index 29900f9001e..169222aa9a5 100644 --- a/Content.Server/_DV/Mail/MailCommands.cs +++ b/Content.Server/_DV/Mail/MailCommands.cs @@ -111,7 +111,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args) return; } - if (!mailSystem.TryGetMailTeleporterForReceiver(recipientUid, out var teleporterComponent, out var teleporterUid)) + if (!mailSystem.TryGetMailTeleporterForReceiver(recipientUid, out _, out var teleporterUid)) // HardLight: var teleporterComponent<_ { shell.WriteLine(Loc.GetString("command-mailto-no-teleporter-found")); return; @@ -183,7 +183,7 @@ public sealed class MailNowCommand : IConsoleCommand [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; // Frontier - public async void Execute(IConsoleShell shell, string argStr, string[] args) + public void Execute(IConsoleShell shell, string argStr, string[] args) // HardLight: Removed async { var sectorService = _entitySystemManager.GetEntitySystem(); // Frontier: sector-wide mail From b6e0308830941607f92fb8abcd16e511bdd1bee2 Mon Sep 17 00:00:00 2001 From: Livyathan Date: Thu, 14 May 2026 01:14:55 -0400 Subject: [PATCH 3/4] Port WizDen Station Map Improvements PR #39393 & #43877 --- .../Structures/Wallmounts/station_map.yml | 190 +++++++++--------- 1 file changed, 97 insertions(+), 93 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml index 19efb4ff18a..155a9d7f978 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml @@ -6,33 +6,33 @@ placement: mode: SnapgridCenter components: - - type: InteractionOutline - - type: Clickable - - type: Transform - anchored: true - - type: Sprite - sprite: Structures/Machines/station_map.rsi - drawdepth: WallMountedItems - layers: - - state: station_map_broken - - type: Damageable - damageContainer: StructuralInorganic - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:PlaySoundBehavior - sound: - collection: GlassBreak - - !type:DoActsBehavior - acts: [ "Destruction" ] - # Mono - - type: ShipRepairable - repairTo: StationMap - repairTime: 3 - repairCost: 6 + - type: InteractionOutline + - type: Clickable + - type: Transform + anchored: true + - type: Sprite + sprite: Structures/Machines/station_map.rsi + drawdepth: WallMountedItems + layers: + - state: station_map_broken + - type: Damageable + damageContainer: StructuralInorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: GlassBreak + - !type:DoActsBehavior + acts: [ "Destruction" ] + # Mono + - type: ShipRepairable + repairTo: StationMap + repairTime: 3 + repairCost: 6 - type: entity id: StationMap @@ -43,73 +43,77 @@ placement: mode: SnapgridCenter components: - - type: StationMap - - type: EdgeConnection # HardLight - connectionKey: wallmount_computers - allowedDirections: East, West - - type: Transform - anchored: true - - type: Sprite - sprite: Structures/Machines/station_map.rsi - layers: - - map: [ "computerLayerBody" ] - state: station_map0 - - map: [ "computerLayerScreen" ] - state: unshaded - # HardLight start - - type: GenericVisualizer - visuals: - enum.EdgeConnectionVisuals.ConnectionMask: - computerLayerBody: - None: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - East: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - East, West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - # HardLight end - - type: Icon - sprite: Structures/Machines/station_map.rsi + - type: StationMap + - type: EdgeConnection # HardLight + connectionKey: wallmount_computers + allowedDirections: East, West + - type: Transform + anchored: true + - type: Sprite + sprite: Structures/Machines/station_map.rsi + layers: + - map: [ "computerLayerBody" ] state: station_map0 - - type: ContainerFill - containers: - board: [ StationMapCircuitboard ] - - type: ContainerContainer - containers: - board: !type:Container - - type: ApcPowerReceiver - powerLoad: 200 - - type: WallMount - arc: 360 - - type: ExtensionCableReceiver - - type: Construction - graph: StationMap - node: station_map - - type: ActivatableUIRequiresPower - - type: ActivatableUI - key: enum.StationMapUiKey.Key - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:PlaySoundBehavior - sound: - collection: GlassBreak - - !type:SpawnEntitiesBehavior - spawn: - StationMapBroken: - min: 1 - max: 1 - - !type:DoActsBehavior - acts: [ "Destruction" ] - - type: UserInterface - interfaces: - enum.StationMapUiKey.Key: - type: StationMapBoundUserInterface - # Mono - - type: ShipRepairable - repairTime: 3 - repairCost: 6 + - map: [ "computerLayerScreen" ] + state: unshaded + - type: Icon + sprite: Structures/Machines/station_map.rsi + state: station_map0 + - type: GenericVisualizer + visuals: + # HardLight start + enum.ComputerVisuals.Powered: + computerLayerScreen: + True: { visible: true, shader: unshaded } + False: { visible: false } + enum.EdgeConnectionVisuals.ConnectionMask: + computerLayerBody: + None: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + East: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + East, West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + # HardLight end + - type: ContainerFill + containers: + board: [ StationMapCircuitboard ] + - type: ContainerContainer + containers: + board: !type:Container + - type: ApcPowerReceiver + powerLoad: 200 + - type: WallMount + arc: 360 + - type: ExtensionCableReceiver + - type: Construction + graph: StationMap + node: station_map + - type: ActivatableUIRequiresPower + - type: ActivatableUI + key: enum.StationMapUiKey.Key + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: GlassBreak + - !type:SpawnEntitiesBehavior + spawn: + StationMapBroken: + min: 1 + max: 1 + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: UserInterface + interfaces: + enum.StationMapUiKey.Key: + type: StationMapBoundUserInterface + # Mono + - type: ShipRepairable + repairTime: 3 + repairCost: 6 - type: entity id: StationMapAssembly From eb63cb01e887427d8b0f3da1c4cb6839c2575cd2 Mon Sep 17 00:00:00 2001 From: Livyathan Date: Thu, 14 May 2026 01:15:09 -0400 Subject: [PATCH 4/4] Revert "Port WizDen Station Map Improvements PR #39393 & #43877" This reverts commit b6e0308830941607f92fb8abcd16e511bdd1bee2. --- .../Structures/Wallmounts/station_map.yml | 190 +++++++++--------- 1 file changed, 93 insertions(+), 97 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml index 155a9d7f978..19efb4ff18a 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/station_map.yml @@ -6,33 +6,33 @@ placement: mode: SnapgridCenter components: - - type: InteractionOutline - - type: Clickable - - type: Transform - anchored: true - - type: Sprite - sprite: Structures/Machines/station_map.rsi - drawdepth: WallMountedItems - layers: - - state: station_map_broken - - type: Damageable - damageContainer: StructuralInorganic - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:PlaySoundBehavior - sound: - collection: GlassBreak - - !type:DoActsBehavior - acts: [ "Destruction" ] - # Mono - - type: ShipRepairable - repairTo: StationMap - repairTime: 3 - repairCost: 6 + - type: InteractionOutline + - type: Clickable + - type: Transform + anchored: true + - type: Sprite + sprite: Structures/Machines/station_map.rsi + drawdepth: WallMountedItems + layers: + - state: station_map_broken + - type: Damageable + damageContainer: StructuralInorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: GlassBreak + - !type:DoActsBehavior + acts: [ "Destruction" ] + # Mono + - type: ShipRepairable + repairTo: StationMap + repairTime: 3 + repairCost: 6 - type: entity id: StationMap @@ -43,77 +43,73 @@ placement: mode: SnapgridCenter components: - - type: StationMap - - type: EdgeConnection # HardLight - connectionKey: wallmount_computers - allowedDirections: East, West - - type: Transform - anchored: true - - type: Sprite - sprite: Structures/Machines/station_map.rsi - layers: - - map: [ "computerLayerBody" ] + - type: StationMap + - type: EdgeConnection # HardLight + connectionKey: wallmount_computers + allowedDirections: East, West + - type: Transform + anchored: true + - type: Sprite + sprite: Structures/Machines/station_map.rsi + layers: + - map: [ "computerLayerBody" ] + state: station_map0 + - map: [ "computerLayerScreen" ] + state: unshaded + # HardLight start + - type: GenericVisualizer + visuals: + enum.EdgeConnectionVisuals.ConnectionMask: + computerLayerBody: + None: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + East: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + East, West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } + # HardLight end + - type: Icon + sprite: Structures/Machines/station_map.rsi state: station_map0 - - map: [ "computerLayerScreen" ] - state: unshaded - - type: Icon - sprite: Structures/Machines/station_map.rsi - state: station_map0 - - type: GenericVisualizer - visuals: - # HardLight start - enum.ComputerVisuals.Powered: - computerLayerScreen: - True: { visible: true, shader: unshaded } - False: { visible: false } - enum.EdgeConnectionVisuals.ConnectionMask: - computerLayerBody: - None: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - East: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - East, West: { state: station_map0, sprite: Structures/Machines/station_map.rsi } - # HardLight end - - type: ContainerFill - containers: - board: [ StationMapCircuitboard ] - - type: ContainerContainer - containers: - board: !type:Container - - type: ApcPowerReceiver - powerLoad: 200 - - type: WallMount - arc: 360 - - type: ExtensionCableReceiver - - type: Construction - graph: StationMap - node: station_map - - type: ActivatableUIRequiresPower - - type: ActivatableUI - key: enum.StationMapUiKey.Key - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:PlaySoundBehavior - sound: - collection: GlassBreak - - !type:SpawnEntitiesBehavior - spawn: - StationMapBroken: - min: 1 - max: 1 - - !type:DoActsBehavior - acts: [ "Destruction" ] - - type: UserInterface - interfaces: - enum.StationMapUiKey.Key: - type: StationMapBoundUserInterface - # Mono - - type: ShipRepairable - repairTime: 3 - repairCost: 6 + - type: ContainerFill + containers: + board: [ StationMapCircuitboard ] + - type: ContainerContainer + containers: + board: !type:Container + - type: ApcPowerReceiver + powerLoad: 200 + - type: WallMount + arc: 360 + - type: ExtensionCableReceiver + - type: Construction + graph: StationMap + node: station_map + - type: ActivatableUIRequiresPower + - type: ActivatableUI + key: enum.StationMapUiKey.Key + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: GlassBreak + - !type:SpawnEntitiesBehavior + spawn: + StationMapBroken: + min: 1 + max: 1 + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: UserInterface + interfaces: + enum.StationMapUiKey.Key: + type: StationMapBoundUserInterface + # Mono + - type: ShipRepairable + repairTime: 3 + repairCost: 6 - type: entity id: StationMapAssembly