Skip to content

PORT: Sistema de Energia (Excess Power) do Funky Station#780

Open
cristalyssd wants to merge 2 commits into
Project-Dumont:dumontfrom
cristalyssd:port/power-system
Open

PORT: Sistema de Energia (Excess Power) do Funky Station#780
cristalyssd wants to merge 2 commits into
Project-Dumont:dumontfrom
cristalyssd:port/power-system

Conversation

@cristalyssd

Copy link
Copy Markdown
Contributor

Sobre a PR

Aonde foi portado: funky-station/funky-station#2330

Essa PR adiciona duas novas máquinas que usam a energia que está sobrando: uma para venda e outra para fazer combustível de AME.

Por quê? / Balanceamento

O nosso PTL atual é bem... paia. Não dá para configurar ele de forma decente, a quantidade de energia que a estação está gerando pouco interfere no valor pois sempre será 5% do PTL e sem falar da maracutaia para ele não comer a energia da estação. O PTL portado é totalmente configurável e gera de acordo com a energia que está sendo recebida. Ou seja, se tu está gerando 20 MW vai receber de acordo, se está gerando 100 KW vai receber de acordo, diferente do PTL que é um valor fixo. Agora os engenheiros têm um motivo para fazer diversos geradores (sem dizer que o dinheiro cai direto nas contas do departamento).

Sobre fabricar combustível de AME é bem interessante, mas acredito que talvez valha dar uma mudada. Pois o combustível fabricado tem bastante unidade, umas cerca de três vezes mais. Talvez adequar ao valor padrão, pois pelos meus testes, 1 MW de energia no fabricador dá um combustível de AME a cada 20 minutos.

Ok, muito divertido e tals... Mas essa mudança exige mapeamento. São duas máquinas ENORMES e que ocupam bastante espaço. Infelizmente, o nosso PTL atual está posicionado nos piores lugares possíveis... então deve fazer uma mudança para que fique legal. Eu resolvi jogar um mapa aleatório do Funky e notei que essas duas máquinas estão mapeadas no Box (só pra ter uma noção de qual mapa tem). Não acho que seja necessário ter uma em cada mapa, talvez ter o PTL novo já seja legal o suficiente.

Detalhes Técnicos

Foi meu primeiro Cherry-Pick e talvez tenha algum erro. Mas os arquivos modificados APARENTEMENTE não dão BO... eu acredito. Quando testei as duas máquinas funcionaram de forma perfeita sem erro.

Anexos

wooow O PTL como eu disse... Dá pra mudar de W, KW, MW e GW. FABRICADOOR Fabricador de combustível de AME.

Requerimentos

Changelog

🆑

  • add: Adiciona um PTL melhor e que pode ser ajustável (vende excesso de energia).
  • add: Adiciona Fabricador de Anti-Matéria (produz combustível para AME) em troca de energia e plastiaço.
  • remove: Removido os subframezados.

Origem: funky-station/funky-station#2330
- Adiciona um PTL melhor e que pode ser ajustável (vende excesso de energia)
- Adiciona Fabricador de Anti-Matéria (produz combustível para AME)

Autor original: @rottenheadphones (PR #2330 do Funky Station)
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

RSI Diff Bot; head commit 3c4c663 merging into 113fb93
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

Resources/Textures/_NF/Objects/Power/big_ame_jar.rsi

State Old New Status
inhand-left Added
inhand-right Added
jar Added

Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi

State Old New Status
dial-animated Added
dial Added
inserting Added
material-good Added
material-low Added
panel-unlit Added
slot-full Added
slot-unlit Added

Resources/Textures/_NF/Structures/Machines/AMEFab/64x32.rsi

State Old New Status
flywheel-animated Added
flywheel Added
press-animated Added
press Added

Resources/Textures/_NF/Structures/Machines/AMEFab/base.rsi

State Old New Status
base Added

Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi

State Old New Status
fan-animated Added
fan Added
front-panel-unlit Added
gas Added
panel-unlit Added
window-unlit Added

Resources/Textures/_NF/Structures/Machines/GasConverter/base.rsi

State Old New Status
base Added

Resources/Textures/_NF/Structures/Power/TransmissionPoint/32x32.rsi

State Old New Status
icon Added
panel-unlit Added

Resources/Textures/_NF/Structures/Power/TransmissionPoint/96x32.rsi

State Old New Status
base-foreground Added
base-unlit Added

Resources/Textures/_NF/Structures/Power/TransmissionPoint/base.rsi

State Old New Status
base Added

Resources/Textures/_NF/Structures/Power/bles.rsi

State Old New Status
bles-glass Added
bles-oc0 Added
bles-oc1 Added
bles-oc2 Added
bles-og1 Added
bles-og2 Added
bles-og3 Added
bles-og4 Added
bles-og5 Added
bles-op0 Added
bles-op1 Added
bles-op2 Added
bles-open Added
bles-unlit Added
bles Added

Edit: diff updated after 3c4c663

@CRISOOOOO

Copy link
Copy Markdown
Contributor

Poderia fazer com que cada máquina dessas precisasse pesquisar na sci, facilitaria não precisar ser mapeado em todo mapa

@CRISOOOOO

CRISOOOOO commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Mas daí a pesquisa seria tier 3, obviamente

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Esta PR introduz três novos sistemas de consumo de energia no servidor NF: EntitySpawnPowerConsumer (produz entidades como AmeJarBig consumindo energia e Plasteel), GasSpawnPowerConsumer (gera gás em canisters a partir de energia) e PowerTransmission (converte energia HV em créditos de cargo). Todos compartilham uma UI ajustável de draw de potência (XAML + BoundUserInterface). Inclui protótipos YAML e assets RSI para AntiMatterFabricator, SMESBig (BLES) e PowerTransmissionPoint.

Changes

UI Compartilhada de Ajuste de Consumo de Energia

Layer / File(s) Summary
Contratos compartilhados de UI e enumerações
Content.Shared/_NF/Power/SharedAdjustablePowerDraw.cs, Content.Shared/_NF/Manufacturing/SharedManufacturing.cs
Define AdjustablePowerDrawUiKey, estado AdjustablePowerDrawBuiState com On/Load/Text, mensagens SetEnabled/SetLoad e enum EntitySpawnMaterialVisuals.
Menu client-side e BoundUserInterface
Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml, Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml.cs, Content.Client/_NF/Power/AdjustablePowerDrawBoundUserInterface.cs, Resources/Locale/en-US/_NF/power/components/adjustable-power-draw-component.ftl
AdjustablePowerDrawMenu implementa dropdown W/kW/MW/GW, validação de entrada, indicador de alterações pendentes e toggle de energia; AdjustablePowerDrawBoundUserInterface instancia o menu e roteia eventos e estados.

Sistema EntitySpawnPowerConsumer (Anti-Matter Fabricator)

Layer / File(s) Summary
Componente compartilhado e sistema base
Content.Shared/_NF/Manufacturing/Components/EntitySpawnPowerConsumerComponent.cs, Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs, Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs
EntitySpawnPowerConsumerComponent define campos de acumulação, material, spawn, escalonamento logarítmico e limites; SharedEntitySpawnPowerConsumerSystem cancela inserção de itens em slot; stub client-side registra o sistema.
Sistema servidor EntitySpawnPowerConsumer
Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs, Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl
OnMapInit, OnExamined, OnMaterialInserted, Update com ciclo de spawn, GetEffectivePower (linear+logarítmico), GetGenerationTime, handlers de UI e UpdateAppearance com EntitySpawnMaterialVisuals.
Protótipo AntiMatterFabricator, AmeJarBig e assets
Resources/Prototypes/_NF/Entities/Structures/Machines/ame_fab.yml, Resources/Prototypes/_NF/Entities/Objects/Power/antimatter_jar.yml, Resources/Textures/_NF/Structures/Machines/AMEFab/..., Resources/Textures/_NF/Objects/Power/big_ame_jar.rsi/meta.json
Protótipo AntiMatterFabricator com HVPower, UI ajustável, ItemSlots para NFFuel, EntitySpawnPowerConsumer e MaterialStorage de Plasteel; AmeJarBig com 1500 de combustível; metadados RSI para AMEFab e big_ame_jar.

Sistema GasSpawnPowerConsumer (Gas Converter)

Layer / File(s) Summary
Componente GasSpawnPowerConsumer
Content.Server/_NF/Manufacturing/Components/GasSpawnPowerConsumerComponent.cs
Define GasSpawnPowerConsumerComponent com GasMixture, EnergyPerMole, acumuladores, parâmetros linear/logarítmico e MaximumMolesPerSecond.
Sistema servidor GasSpawnPowerConsumer
Content.Server/_NF/Manufacturing/EntitySystems/GasSpawnPowerConsumerSystem.cs, Resources/Locale/en-US/_NF/manufacturing/gas-spawn-power-consumer-component.ftl
Update acumula energia e gera gás periodicamente com merge atmosférico e limites de pressão; GetEffectivePower, GetGasSpawnRate, fluxo de UI com throttling.
Assets visuais GasConverter
Resources/Textures/_NF/Structures/Machines/GasConverter/...
Metadados RSI para GasConverter (base 96x96 e 32x32 com estados animados fan, gas, panel-unlit).

Sistema PowerTransmission (Ponto de Transmissão de Energia)

Layer / File(s) Summary
Componente PowerTransmission e auxiliares
Content.Server/_NF/Power/Components/PowerTransmissionComponent.cs, Content.Server/_NF/Power/Components/ChargingComponent.cs, Content.Server/_NF/Power/Components/MixedPowerRecieverComponent.cs
PowerTransmissionComponent com parâmetros linear/logarítmico, Account, DepositPeriod e limites de potência; ChargingComponent e MixedPowerReceiverComponent como markers auxiliares.
Sistema servidor PowerTransmission
Content.Server/_NF/Power/EntitySystems/PowerTransmissionSystem.cs, Resources/Locale/en-US/_NF/power/components/power-transmission-component.ftl
Update acumula energia e deposita periodicamente em CargoSystem.UpdateBankAccount (fallback para "Cargo"); GetPowerPayRate (linear+logarítmico); handlers de UI e FormatSpesos.
Protótipo PowerTransmissionPoint, SMESBig e assets
Resources/Prototypes/_NF/Entities/Structures/Power/transmission_point.yml, Resources/Prototypes/_NF/Entities/Structures/Power/smes.yml, Resources/Textures/_NF/Structures/Power/TransmissionPoint/..., Resources/Textures/_NF/Structures/Power/bles.rsi/meta.json
PowerTransmissionPoint com HVPower desabilitado por padrão, Electrified, PowerMonitoringDevice e UI ajustável; SMESBig (BLES) com BatteryInterface, Battery e PowerNetworkBattery; metadados RSI correspondentes.

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant AdjustablePowerDrawMenu
  participant AdjustablePowerDrawBoundUserInterface
  participant EntitySpawnPowerConsumerSystem

  rect rgba(0, 100, 200, 0.5)
    note over Player,AdjustablePowerDrawMenu: Ajuste de Carga pelo Jogador
    Player->>AdjustablePowerDrawMenu: Digite valor e clique Submit
    AdjustablePowerDrawMenu->>AdjustablePowerDrawBoundUserInterface: OnSetLoad(float watts)
    AdjustablePowerDrawBoundUserInterface->>EntitySpawnPowerConsumerSystem: AdjustablePowerDrawSetLoadMessage
    EntitySpawnPowerConsumerSystem->>EntitySpawnPowerConsumerSystem: HandleSetLoad → clamp DrawRate
    EntitySpawnPowerConsumerSystem->>AdjustablePowerDrawBoundUserInterface: AdjustablePowerDrawBuiState(On, Load, estimatedTime)
    AdjustablePowerDrawBoundUserInterface->>AdjustablePowerDrawMenu: Update(state)
  end

  rect rgba(0, 180, 100, 0.5)
    note over EntitySpawnPowerConsumerSystem: Ciclo de Spawn (Update)
    EntitySpawnPowerConsumerSystem->>EntitySpawnPowerConsumerSystem: AccumulatedEnergy += ReceivingPower * dt
    EntitySpawnPowerConsumerSystem->>EntitySpawnPowerConsumerSystem: AccumulatedEnergy >= EnergyPerSpawn?
    EntitySpawnPowerConsumerSystem->>EntitySpawnPowerConsumerSystem: SpawnEntity(Spawn) + reset acumuladores
    EntitySpawnPowerConsumerSystem->>EntitySpawnPowerConsumerSystem: TryConsumeResources (Plasteel)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

size/M, S: Needs Review

Suggested reviewers

  • O-Verdadeiro-Biel
  • Kyoth25f
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed O título resume corretamente o port do sistema de Excess Power do Funky Station.
Description check ✅ Passed A descrição corresponde às mudanças: PTL ajustável e fabricador de combustível de AME.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (2)
Content.Server/_NF/Power/Components/ChargingComponent.cs (1)

17-20: 🩺 Stability & Availability | 🔵 Trivial

Remova ChargerComponent de ChargingComponent se ele for apenas cache. O componente já guarda ChargerUid; manter a referência direta pode ficar desatualizada quando o carregador mudar ou for removido, e não há uso desse campo no restante do código.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Content.Server/_NF/Power/Components/ChargingComponent.cs` around lines 17 -
20, Remove the cached ChargerComponent field from ChargingComponent if it is
only duplicating state already tracked by ChargerUid; keep the UID as the source
of truth and update any code that reads or assigns ChargerComponent to resolve
the charger on demand instead. Check ChargingComponent and related
charger/battery interactions for any remaining references to ChargerComponent,
and replace them with logic based on ChargerUid so the component does not hold a
stale direct reference.
Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs (1)

25-27: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Restrinja o bloqueio ao slot configurado de saída.

Do jeito atual, qualquer inserção manual em qualquer ItemSlot da entidade é cancelada. Isso ignora SlotName e pode bloquear slots adicionais da máquina. Limite o cancelamento ao slot configurado para output.

💡 Ajuste sugerido
 private void OnItemSlotInsertAttempt(Entity<EntitySpawnPowerConsumerComponent> ent, ref ItemSlotInsertAttemptEvent args)
 {
-    if (args.User != null)
+    if (args.User != null && args.Slot.Name == ent.Comp.SlotName)
         args.Cancelled = true;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs`
around lines 25 - 27, The insert-cancel logic in
SharedEntitySpawnPowerConsumerSystem is too broad because it blocks any manual
interaction with any ItemSlot on the entity. Update the handler so it checks the
configured output slot name from the relevant setup/component and only sets
args.Cancelled for that specific slot, leaving other slots unaffected. Use the
existing slot-identifying symbols in this system, such as the slot/component
access around the current args.User check, to scope the cancellation to the
output slot only.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs`:
- Around line 5-8: The client-side entity system is declared as a standalone
EntitySystem instead of inheriting the shared implementation, so the shared
Initialize logic and subscriptions are not applied. Update
SharedEntitySpawnPowerConsumerSystem in
Content.Client._NF.Manufacturing.EntitySystems to derive from
Content.Shared._NF.Manufacturing.EntitySystems.SharedEntitySpawnPowerConsumerSystem,
and keep the client partial only for client-specific behavior if needed.

In `@Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml.cs`:
- Around line 46-48: The UI event handlers on PowerDropDown.OnItemSelected and
Load.OnTextChanged always call SetUnsavedChanges(), which causes programmatic
sync from Update() to be treated as user edits. Add a guard in
AdjustablePowerDrawMenu to distinguish internal UI updates from real user
interaction, and make Update() set Load.Text/select dropdown without triggering
SetUnsavedChanges() during synchronization. Ensure the handlers only mark
unsaved changes when the change comes from user input, not when SelectId or
Load.Text is being set by the control itself.
- Around line 131-132: The power status label in AdjustablePowerDrawMenu should
use this component’s new locale keys instead of the gas-pump ones. Update the
TogglePowerButton.Text assignment in the AdjustablePowerDrawMenu logic to
reference the adjustable-power-status enabled/disabled strings so the UI stays
consistent with the new translations and avoids leaving the new locale entries
unused.

In
`@Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs`:
- Around line 130-138: The spawn cycle in EntitySpawnPowerConsumerSystem should
not be finalized before confirming TrySpawnInContainer succeeds, and
AccumulatedEnergy should preserve any overflow instead of being reset. Update
the logic around TrySpawnInContainer, TryConsumeResources, and the
spawn.AccumulatedEnergy / spawn.Processing handling so the batch only advances
after a successful output-slot spawn. Keep the completed progress if the spawn
fails, and subtract EnergyPerSpawn rather than clearing all accumulated energy
to avoid losing excess energy.

In
`@Content.Server/_NF/Manufacturing/EntitySystems/GasSpawnPowerConsumerSystem.cs`:
- Around line 41-42: The UI throttle in GasSpawnPowerConsumerSystem is currently
shared across all instances because _lastUiUpdate is a single system field, so
one machine/BUI update can suppress another and leave it without an initial
refresh. Move the cooldown tracking to per-machine/per-UI state in the relevant
update path (for example in the methods that handle BUI refresh/state sync
around the current return guard), and ensure each opened interface can send its
initial state independently even if another update happened within
UiUpdateCooldown.
- Around line 137-142: The GasSpawnPowerConsumerSystem spawn path can produce a
negative moles amount when the canister pressure is already above the maximum,
which then feeds a negative factor into the mixture scaling before merge. Update
the logic around the deltaP/maxMoles calculation to clamp the allowed spawn
amount at zero (or return early when the canister is over MaxOutputPressure)
before calling _mixture.Multiply and _atmos.Merge, using the
GasSpawnPowerConsumerSystem spawn flow and the molesToSpawn/maxMoles variables
as the key points to adjust.
- Around line 166-173: A curva de potência em
GasSpawnPowerConsumerSystem.GasPowerConsumer provavelmente está usando a fórmula
logarítmica de forma invertida, causando uma queda abrupta logo após
LinearMaxValue. Ajuste o cálculo no ramo else para que a transição a partir de
LinearMaxValue seja contínua e crescente, revisando os termos usados em
ent.Comp.LogarithmCoefficient, ent.Comp.LogarithmRateBase e
ent.Comp.LogarithmSubtrahend. Verifique o comportamento do método/trecho que
calcula actualPower para que valores logo acima do limite não colapsem para
poucos watts.
- Around line 92-93: The power state check in GasSpawnPowerConsumerSystem is
comparing the same NetworkLoad values twice in the same update, so
PowerDeviceVisuals.Powered never changes. Update the logic around
wasPowered/isPowered to compare the current network state against the previously
stored visual state or another persisted source, and then set
PowerDeviceVisuals.Powered only when that state actually changes. Use the
existing symbols GasSpawnPowerConsumerSystem and PowerDeviceVisuals.Powered to
locate the affected update path.
- Around line 132-145: The spawn limit logic in GasSpawnPowerConsumerSystem is
treating MaximumMolesPerSecond as a per-tick cap and then clearing all
accumulated energy, which drops excess work. Update the spawn calculation so the
per-second limit is scaled by the actual elapsed spawn interval (for example,
using SpawnCheckPeriod or the current tick delta) before clamping molesToSpawn.
Also change the AccumulatedEnergy reset so only the energy actually consumed by
the spawned moles is removed, leaving any remainder buffered for the next cycle.

In `@Content.Server/_NF/Power/EntitySystems/PowerTransmissionSystem.cs`:
- Around line 101-114: The deposit calculation in PowerTransmissionSystem.Update
is using only one DepositPeriod even when the server has fallen behind and
AccumulatedEnergy spans multiple elapsed periods. Update the logic around
xmit.NextDeposit and xmit.AccumulatedEnergy so payment is based on the real time
since the last deposit, or iterate through all overdue deposit intervals and
consume energy per period instead of paying the same backlog once before zeroing
it.

In
`@Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl`:
- Line 2: The estimated-time label in entity-spawn-power-consumer-component.ftl
is formatting the TimeSpan with TOSTRING($time, "hh\\:mm\\:ss"), which wraps
after 24 hours and hides days. Update the localization string used by
entity-spawn-power-consumer-estimated-time so it formats long durations with
days included, and keep the change localized to the estimated-time output path
in the relevant manufacturing entity-spawn power consumer text.

In `@Resources/Prototypes/_NF/Entities/Structures/Power/smes.yml`:
- Around line 35-45: The SMES prototype has a charge-rate mismatch:
BatteryInterface.maxChargeRate is much higher than
PowerNetworkBattery.maxChargeRate, so the device advertises more charging
capacity than the network can actually apply. Update the PowerNetworkBattery
values in the smes prototype to match the intended BatteryInterface charging
limits, and keep the related charge/supply settings consistent so the runtime
behavior matches the prototype's advertised rate.

---

Nitpick comments:
In `@Content.Server/_NF/Power/Components/ChargingComponent.cs`:
- Around line 17-20: Remove the cached ChargerComponent field from
ChargingComponent if it is only duplicating state already tracked by ChargerUid;
keep the UID as the source of truth and update any code that reads or assigns
ChargerComponent to resolve the charger on demand instead. Check
ChargingComponent and related charger/battery interactions for any remaining
references to ChargerComponent, and replace them with logic based on ChargerUid
so the component does not hold a stale direct reference.

In
`@Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs`:
- Around line 25-27: The insert-cancel logic in
SharedEntitySpawnPowerConsumerSystem is too broad because it blocks any manual
interaction with any ItemSlot on the entity. Update the handler so it checks the
configured output slot name from the relevant setup/component and only sets
args.Cancelled for that specific slot, leaving other slots unaffected. Use the
existing slot-identifying symbols in this system, such as the slot/component
access around the current args.User check, to scope the cancellation to the
output slot only.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7a2ce547-a392-4bac-8fb0-055d0be0ddc4

📥 Commits

Reviewing files that changed from the base of the PR and between 113fb93 and 3c4c663.

⛔ Files ignored due to path filters (44)
  • Resources/Audio/_NF/Ambience/power-hum.ogg is excluded by !**/*.ogg
  • Resources/Textures/_NF/Objects/Power/big_ame_jar.rsi/inhand-left.png is excluded by !**/*.png
  • Resources/Textures/_NF/Objects/Power/big_ame_jar.rsi/inhand-right.png is excluded by !**/*.png
  • Resources/Textures/_NF/Objects/Power/big_ame_jar.rsi/jar.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/dial-animated.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/dial.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/inserting.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/material-good.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/material-low.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/panel-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/slot-full.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/slot-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/64x32.rsi/flywheel-animated.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/64x32.rsi/flywheel.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/64x32.rsi/press-animated.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/64x32.rsi/press.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/AMEFab/base.rsi/base.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/fan-animated.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/fan.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/front-panel-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/gas.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/panel-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/window-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Machines/GasConverter/base.rsi/base.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/32x32.rsi/icon.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/32x32.rsi/panel-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/96x32.rsi/base-foreground.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/96x32.rsi/base-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/base.rsi/base.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-glass.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-oc0.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-oc1.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-oc2.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-og1.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-og2.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-og3.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-og4.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-og5.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-op0.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-op1.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-op2.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-open.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles-unlit.png is excluded by !**/*.png
  • Resources/Textures/_NF/Structures/Power/bles.rsi/bles.png is excluded by !**/*.png
📒 Files selected for processing (35)
  • Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs
  • Content.Client/_NF/Power/AdjustablePowerDrawBoundUserInterface.cs
  • Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml
  • Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml.cs
  • Content.Server/_NF/Manufacturing/Components/GasSpawnPowerConsumerComponent.cs
  • Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs
  • Content.Server/_NF/Manufacturing/EntitySystems/GasSpawnPowerConsumerSystem.cs
  • Content.Server/_NF/Power/Components/ChargingComponent.cs
  • Content.Server/_NF/Power/Components/MixedPowerRecieverComponent.cs
  • Content.Server/_NF/Power/Components/PowerTransmissionComponent.cs
  • Content.Server/_NF/Power/EntitySystems/PowerTransmissionSystem.cs
  • Content.Shared/_NF/Manufacturing/Components/EntitySpawnPowerConsumerComponent.cs
  • Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs
  • Content.Shared/_NF/Manufacturing/SharedManufacturing.cs
  • Content.Shared/_NF/Power/SharedAdjustablePowerDraw.cs
  • Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl
  • Resources/Locale/en-US/_NF/manufacturing/gas-spawn-power-consumer-component.ftl
  • Resources/Locale/en-US/_NF/power/components/adjustable-power-draw-component.ftl
  • Resources/Locale/en-US/_NF/power/components/power-transmission-component.ftl
  • Resources/Locale/en-US/job/job-names.ftl
  • Resources/Prototypes/Catalog/Fills/Crates/engines.yml
  • Resources/Prototypes/_NF/Entities/Objects/Power/antimatter_jar.yml
  • Resources/Prototypes/_NF/Entities/Structures/Machines/ame_fab.yml
  • Resources/Prototypes/_NF/Entities/Structures/Power/smes.yml
  • Resources/Prototypes/_NF/Entities/Structures/Power/transmission_point.yml
  • Resources/Textures/_NF/Objects/Power/big_ame_jar.rsi/meta.json
  • Resources/Textures/_NF/Structures/Machines/AMEFab/32x32.rsi/meta.json
  • Resources/Textures/_NF/Structures/Machines/AMEFab/64x32.rsi/meta.json
  • Resources/Textures/_NF/Structures/Machines/AMEFab/base.rsi/meta.json
  • Resources/Textures/_NF/Structures/Machines/GasConverter/32x32.rsi/meta.json
  • Resources/Textures/_NF/Structures/Machines/GasConverter/base.rsi/meta.json
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/32x32.rsi/meta.json
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/96x32.rsi/meta.json
  • Resources/Textures/_NF/Structures/Power/TransmissionPoint/base.rsi/meta.json
  • Resources/Textures/_NF/Structures/Power/bles.rsi/meta.json

Comment on lines +5 to +8
namespace Content.Client._NF.Manufacturing.EntitySystems;

/// <inheritdoc/>
public sealed partial class SharedEntitySpawnPowerConsumerSystem : EntitySystem;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,120p' Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs
sed -n '1,120p' Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs

# Verifica onde existe herança explícita de SharedEntitySpawnPowerConsumerSystem
rg -nP --type=cs 'class\s+\w+\s*:\s*SharedEntitySpawnPowerConsumerSystem\b' Content.Client Content.Server Content.Shared

Repository: Project-Dumont/Dumont-Station

Length of output: 1590


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspeciona arquivos relacionados e padrões similares de sistema compartilhado/cliente
sed -n '1,120p' Content.Shared/_NF/Manufacturing/EntitySystems/SharedEntitySpawnPowerConsumerSystem.cs
sed -n '1,120p' Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs
sed -n '1,120p' Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs

printf '\n--- usages ---\n'
rg -n --type=cs 'EntitySpawnPowerConsumerSystem|SharedEntitySpawnPowerConsumerSystem' Content.Client Content.Server Content.Shared

printf '\n--- similar client/shared patterns ---\n'
rg -n --type=cs 'public sealed partial class Shared[A-Za-z0-9_]+System\s*:\s*EntitySystem;' Content.Client Content.Shared | sed -n '1,120p'

Repository: Project-Dumont/Dumont-Station

Length of output: 7120


Herda do sistema shared no cliente
Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs define um EntitySystem separado em vez de derivar de Content.Shared._NF.Manufacturing.EntitySystems.SharedEntitySpawnPowerConsumerSystem; assim, a lógica comum de Initialize() e as subscriptions do shared não entram no cliente.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Content.Client/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs`
around lines 5 - 8, The client-side entity system is declared as a standalone
EntitySystem instead of inheriting the shared implementation, so the shared
Initialize logic and subscriptions are not applied. Update
SharedEntitySpawnPowerConsumerSystem in
Content.Client._NF.Manufacturing.EntitySystems to derive from
Content.Shared._NF.Manufacturing.EntitySystems.SharedEntitySpawnPowerConsumerSystem,
and keep the client partial only for client-specific behavior if needed.

Comment on lines +46 to +48
PowerDropDown.OnItemSelected += x => PowerDropDown.SelectId(x.Id);
PowerDropDown.OnItemSelected += _ => SetUnsavedChanges();
Load.OnTextChanged += _ => SetUnsavedChanges();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Evite marcar alteração pendente durante sincronização de estado da UI

Em Line 78-99, o Update() altera Load.Text/dropdown programaticamente, mas em Line 46-48 esses eventos sempre chamam SetUnsavedChanges(). Isso gera falso “unsaved changes” e bloqueia futuras atualizações automáticas.

💡 Sugestão de correção
 public sealed partial class AdjustablePowerDrawMenu : FancyWindow
 {
+    private bool _syncingState;
@@
     public void Update(AdjustablePowerDrawBuiState msg)
     {
         SetPowered(msg.On);
@@
         if (!_unsavedChanges && msg.Load >= 0)
         {
-            if (msg.Load >= 1_000_000_000)
-            {
-                Load.Text = $"{msg.Load / 1_000_000_000:G3}";
-                PowerDropDown.TrySelect(3);
-            }
-            else if (msg.Load >= 1_000_000)
-            {
-                Load.Text = $"{msg.Load / 1_000_000:G3}";
-                PowerDropDown.TrySelect(2);
-            }
-            else if (msg.Load >= 1_000)
-            {
-                Load.Text = $"{msg.Load / 1_000:G3}";
-                PowerDropDown.TrySelect(1);
-            }
-            else
-            {
-                Load.Text = $"{msg.Load:G3}";
-                PowerDropDown.TrySelect(0);
-            }
+            _syncingState = true;
+            try
+            {
+                if (msg.Load >= 1_000_000_000)
+                {
+                    Load.Text = $"{msg.Load / 1_000_000_000:G3}";
+                    PowerDropDown.TrySelect(3);
+                }
+                else if (msg.Load >= 1_000_000)
+                {
+                    Load.Text = $"{msg.Load / 1_000_000:G3}";
+                    PowerDropDown.TrySelect(2);
+                }
+                else if (msg.Load >= 1_000)
+                {
+                    Load.Text = $"{msg.Load / 1_000:G3}";
+                    PowerDropDown.TrySelect(1);
+                }
+                else
+                {
+                    Load.Text = $"{msg.Load:G3}";
+                    PowerDropDown.TrySelect(0);
+                }
+            }
+            finally
+            {
+                _syncingState = false;
+            }
         }
     }
@@
     private void SetUnsavedChanges()
     {
+        if (_syncingState)
+            return;
         _unsavedChanges = true;
         UnsavedChanges.Visible = true;
     }

Also applies to: 78-99, 120-124

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml.cs` around lines 46 -
48, The UI event handlers on PowerDropDown.OnItemSelected and Load.OnTextChanged
always call SetUnsavedChanges(), which causes programmatic sync from Update() to
be treated as user edits. Add a guard in AdjustablePowerDrawMenu to distinguish
internal UI updates from real user interaction, and make Update() set
Load.Text/select dropdown without triggering SetUnsavedChanges() during
synchronization. Ensure the handlers only mark unsaved changes when the change
comes from user input, not when SelectId or Load.Text is being set by the
control itself.

Comment on lines +131 to +132
TogglePowerButton.Text = Loc.GetString(
on ? "comp-gas-pump-ui-status-enabled" : "comp-gas-pump-ui-status-disabled");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use as chaves de locale deste componente no status de energia

Em Line 131-132, a UI usa comp-gas-pump-ui-status-*, mas este PR adiciona adjustable-power-status-*. Isso deixa strings novas sem uso e pode quebrar consistência de tradução.

💡 Sugestão de correção
         TogglePowerButton.Text = Loc.GetString(
-            on ? "comp-gas-pump-ui-status-enabled" : "comp-gas-pump-ui-status-disabled");
+            on ? "adjustable-power-status-enabled" : "adjustable-power-status-disabled");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
TogglePowerButton.Text = Loc.GetString(
on ? "comp-gas-pump-ui-status-enabled" : "comp-gas-pump-ui-status-disabled");
TogglePowerButton.Text = Loc.GetString(
on ? "adjustable-power-status-enabled" : "adjustable-power-status-disabled");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Content.Client/_NF/Power/AdjustablePowerDrawMenu.xaml.cs` around lines 131 -
132, The power status label in AdjustablePowerDrawMenu should use this
component’s new locale keys instead of the gas-pump ones. Update the
TogglePowerButton.Text assignment in the AdjustablePowerDrawMenu logic to
reference the adjustable-power-status enabled/disabled strings so the UI stays
consistent with the new translations and avoids leaving the new locale entries
unused.

Comment on lines +130 to +138
if (spawn.AccumulatedEnergy >= spawn.EnergyPerSpawn)
{
// End current run.
spawn.AccumulatedEnergy = 0;
spawn.Processing = false;
TrySpawnInContainer(spawn.Spawn, uid, spawn.SlotName, out _);

// Try to start next run.
TryConsumeResources((uid, spawn));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Não descarte o lote antes de confirmar o spawn no slot.

Nas Lines 130-138, o ciclo é encerrado antes de checar o retorno de TrySpawnInContainer(...). Com o slot único output definido em Resources/Prototypes/_NF/Entities/Structures/Machines/ame_fab.yml nas Lines 128-139, basta deixar um jar no slot para a máquina zerar AccumulatedEnergy, perder o progresso concluído e potencialmente consumir mais plasteel sem produzir nada. Além disso, o = 0 descarta qualquer energia excedente do ciclo. Avance para o próximo lote só depois de um spawn bem-sucedido e preserve o excedente com -=.

💡 Ajuste sugerido
                 if (spawn.AccumulatedEnergy >= spawn.EnergyPerSpawn)
                 {
-                    // End current run.
-                    spawn.AccumulatedEnergy = 0;
-                    spawn.Processing = false;
-                    TrySpawnInContainer(spawn.Spawn, uid, spawn.SlotName, out _);
+                    if (!TrySpawnInContainer(spawn.Spawn, uid, spawn.SlotName, out _))
+                        continue;
+
+                    // End current run.
+                    spawn.AccumulatedEnergy -= spawn.EnergyPerSpawn;
+                    spawn.Processing = false;
 
                     // Try to start next run.
                     TryConsumeResources((uid, spawn));
                 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (spawn.AccumulatedEnergy >= spawn.EnergyPerSpawn)
{
// End current run.
spawn.AccumulatedEnergy = 0;
spawn.Processing = false;
TrySpawnInContainer(spawn.Spawn, uid, spawn.SlotName, out _);
// Try to start next run.
TryConsumeResources((uid, spawn));
if (spawn.AccumulatedEnergy >= spawn.EnergyPerSpawn)
{
if (!TrySpawnInContainer(spawn.Spawn, uid, spawn.SlotName, out _))
continue;
// End current run.
spawn.AccumulatedEnergy -= spawn.EnergyPerSpawn;
spawn.Processing = false;
// Try to start next run.
TryConsumeResources((uid, spawn));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs`
around lines 130 - 138, The spawn cycle in EntitySpawnPowerConsumerSystem should
not be finalized before confirming TrySpawnInContainer succeeds, and
AccumulatedEnergy should preserve any overflow instead of being reset. Update
the logic around TrySpawnInContainer, TryConsumeResources, and the
spawn.AccumulatedEnergy / spawn.Processing handling so the batch only advances
after a successful output-slot spawn. Keep the completed progress if the spawn
fails, and subtract EnergyPerSpawn rather than clearing all accumulated energy
to avoid losing excess energy.

Comment on lines +41 to +42
private TimeSpan _lastUiUpdate = TimeSpan.Zero;
private static readonly TimeSpan UiUpdateCooldown = TimeSpan.FromSeconds(0.5f);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

O throttle da UI está global para o sistema, não por máquina/BUI.

_lastUiUpdate é compartilhado por todas as instâncias. Se duas interfaces forem abertas ou ajustadas dentro de 0.5 s, a segunda cai no return de Line 233-234 e pode ficar sem estado inicial, porque não existe refresh periódico fora dessas ações.

Also applies to: 230-236

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Content.Server/_NF/Manufacturing/EntitySystems/GasSpawnPowerConsumerSystem.cs`
around lines 41 - 42, The UI throttle in GasSpawnPowerConsumerSystem is
currently shared across all instances because _lastUiUpdate is a single system
field, so one machine/BUI update can suppress another and leave it without an
initial refresh. Move the cooldown tracking to per-machine/per-UI state in the
relevant update path (for example in the methods that handle BUI refresh/state
sync around the current return guard), and ensure each opened interface can send
its initial state independently even if another update happened within
UiUpdateCooldown.

Comment on lines +137 to +142
var deltaP = Atmospherics.MaxOutputPressure - canister.Air.Pressure;
var maxMoles = deltaP * canister.Air.Volume / (_mixture.Temperature * Atmospherics.R);
molesToSpawn = MathF.Min(molesToSpawn, maxMoles);

_mixture.Multiply(molesToSpawn / _mixture.TotalMoles);
_atmos.Merge(canister.Air, _mixture);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Canister acima da pressão máxima pode gerar molesToSpawn negativo.

Em Line 137-139, se canister.Air.Pressure já estiver acima de MaxOutputPressure, deltaP fica negativo, maxMoles também, e Line 141 multiplica a mistura por um fator negativo antes do merge. Isso pode remover/corromper gás do canister em vez de só impedir produção.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Content.Server/_NF/Manufacturing/EntitySystems/GasSpawnPowerConsumerSystem.cs`
around lines 137 - 142, The GasSpawnPowerConsumerSystem spawn path can produce a
negative moles amount when the canister pressure is already above the maximum,
which then feeds a negative factor into the mixture scaling before merge. Update
the logic around the deltaP/maxMoles calculation to clamp the allowed spawn
amount at zero (or return early when the canister is over MaxOutputPressure)
before calling _mixture.Multiply and _atmos.Merge, using the
GasSpawnPowerConsumerSystem spawn flow and the molesToSpawn/maxMoles variables
as the key points to adjust.

Comment on lines +166 to +173
if (power <= ent.Comp.LinearMaxValue)
actualPower = power;
else
{
actualPower = ent.Comp.LogarithmCoefficient * MathF.Pow(
ent.Comp.LogarithmRateBase,
MathF.Log10(power / ent.Comp.LinearMaxValue) - ent.Comp.LogarithmSubtrahend
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

A curva logarítmica colapsa assim que passa de LinearMaxValue.

Em Line 170-172, com os valores default, power = 2_000_001 entra no ramo log e cai para ~2.5 W (800 * 2.5^(log10(1)-6.301)), enquanto 2_000_000 ainda rende 2 MW. Isso não suaviza a curva; ele praticamente desliga a máquina logo após o threshold.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Content.Server/_NF/Manufacturing/EntitySystems/GasSpawnPowerConsumerSystem.cs`
around lines 166 - 173, A curva de potência em
GasSpawnPowerConsumerSystem.GasPowerConsumer provavelmente está usando a fórmula
logarítmica de forma invertida, causando uma queda abrupta logo após
LinearMaxValue. Ajuste o cálculo no ramo else para que a transição a partir de
LinearMaxValue seja contínua e crescente, revisando os termos usados em
ent.Comp.LogarithmCoefficient, ent.Comp.LogarithmRateBase e
ent.Comp.LogarithmSubtrahend. Verifique o comportamento do método/trecho que
calcula actualPower para que valores logo acima do limite não colapsem para
poucos watts.

Comment on lines +101 to +114
if (_timing.CurTime >= xmit.NextDeposit)
{
xmit.NextDeposit += xmit.DepositPeriod;

if (!float.IsFinite(xmit.AccumulatedEnergy) || !float.IsPositive(xmit.AccumulatedEnergy))
{
xmit.AccumulatedEnergy = 0.0f;
continue;
}

float totalPeriodSeconds = (float)xmit.DepositPeriod.TotalSeconds;
float depositValue = GetPowerPayRate((uid, xmit), xmit.AccumulatedEnergy / totalPeriodSeconds) * totalPeriodSeconds;

xmit.AccumulatedEnergy = 0.0f;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Atrasos de frame supervalorizam o depósito.

NextDeposit avança só um período por Update, mas AccumulatedEnergy pode representar vários períodos quando o servidor atrasa. Nessa situação, toda a energia atrasada é convertida usando apenas um DepositPeriod, o que credita mais dinheiro do que deveria antes de zerar o acumulador. Calcule o pagamento pelo tempo real transcorrido desde o último depósito, ou processe todos os períodos vencidos sem reaproveitar a mesma energia.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Content.Server/_NF/Power/EntitySystems/PowerTransmissionSystem.cs` around
lines 101 - 114, The deposit calculation in PowerTransmissionSystem.Update is
using only one DepositPeriod even when the server has fallen behind and
AccumulatedEnergy spans multiple elapsed periods. Update the logic around
xmit.NextDeposit and xmit.AccumulatedEnergy so payment is based on the real time
since the last deposit, or iterate through all overdue deposit intervals and
consume energy per period instead of paying the same backlog once before zeroing
it.

@@ -0,0 +1,2 @@
entity-spawn-power-consumer-examine = The machine is consuming [color=lightblue]{POWERWATTS($actual)}[/color]/[color=lightblue]{POWERWATTS($requested)}[/color] of power.
entity-spawn-power-consumer-estimated-time = Estimated time to produce one unit: [color=yellow]{TOSTRING($time, "hh\\:mm\\:ss")}[/color]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the locale and system files mentioned in the review comment.
git ls-files 'Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl' \
             'Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs'

# Show the relevant portions with line numbers.
echo '--- locale file ---'
cat -n Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl

echo '--- server file excerpt ---'
sed -n '150,210p' Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs

Repository: Project-Dumont/Dumont-Station

Length of output: 3189


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect surrounding definitions for the time source and formatting path.
rg -n "GetGenerationTime|Estimated time to produce one unit|TOSTRING\\(|TimeSpan" Content.Server Content.Shared Resources/Locale -S

# Find the exact locale string usages if any.
rg -n "entity-spawn-power-consumer-estimated-time|entity-spawn-power-consumer-examine" -S .

Repository: Project-Dumont/Dumont-Station

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read only the specific lines around the locale string and time formatting logic.
echo '--- locale file (top) ---'
sed -n '1,20p' Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl

echo '--- system file (generation time and examine text) ---'
sed -n '160,190p' Content.Server/_NF/Manufacturing/EntitySystems/EntitySpawnPowerConsumerSystem.cs

Repository: Project-Dumont/Dumont-Station

Length of output: 1745


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the implementation of GetGenerationTime and any related fields/configuration.
rg -n "GetGenerationTime|GenerationTime|PowerConsumer|SpawnPowerConsumer|estimated time|adjustable draw|W/kW/MW/GW" Content.Server Content.Shared Resources -S

# If GetGenerationTime is present, print a wider window around it.
file=$(rg -l "GetGenerationTime" Content.Server Content.Shared Resources -S | head -n 1)
if [ -n "${file:-}" ]; then
  echo "--- $file ---"
  sed -n '1,260p' "$file"
fi

Repository: Project-Dumont/Dumont-Station

Length of output: 27396


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for the power-adjustment UI and any bounds/clamping that would limit the generation time.
rg -n "W/kW/MW/GW|draw|power.*slider|adjust.*power|clamp|minimum.*power|maximum.*power|GetGenerationTime" Content.Client Content.Shared Content.Server -S

# Find any documentation or comments about expected output duration formatting.
rg -n "days|hh\\\\:mm\\\\:ss|TimeSpan|estimated time to produce one unit" Resources Content.Server Content.Shared -S

Repository: Project-Dumont/Dumont-Station

Length of output: 50386


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the component values that determine the possible generation time range.
sed -n '1,220p' Content.Shared/_NF/Manufacturing/Components/EntitySpawnPowerConsumerComponent.cs

echo '---'
sed -n '1,220p' Content.Shared/_NF/Power/Components/AdjustablePowerDrawComponent.cs

echo '---'
sed -n '1,220p' Resources/Prototypes/_NF/Entities/Structures/Machines/ame_fab.yml

Repository: Project-Dumont/Dumont-Station

Length of output: 4738


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the adjustable power draw definitions and relevant prototype values.
git ls-files | rg '_NF/.*/AdjustablePowerDraw|AdjustablePowerDrawComponent|EntitySpawnPowerConsumerComponent|ame_fab.yml'

Repository: Project-Dumont/Dumont-Station

Length of output: 491


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the shared component that defines the minimum/maximum requestable power and energy per spawn.
cat -n Content.Shared/_NF/Manufacturing/Components/EntitySpawnPowerConsumerComponent.cs

echo '---'
# Read the UI component/prototype that may constrain the adjustable power range.
git ls-files | rg 'AdjustablePowerDraw'

Repository: Project-Dumont/Dumont-Station

Length of output: 5796


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the component defaults and ranges for the spawn power consumer.
cat -n Content.Shared/_NF/Manufacturing/Components/EntitySpawnPowerConsumerComponent.cs

echo '---'
# Show the prototype instance that uses this component.
sed -n '90,150p' Resources/Prototypes/_NF/Entities/Structures/Machines/ame_fab.yml

Repository: Project-Dumont/Dumont-Station

Length of output: 7002


A estimativa esconde dias acima de 24h.

Na linha 2, TOSTRING($time, "hh\\:mm\\:ss") faz wrap do TimeSpan a cada 24h. Com MinimumRequestablePower = 500 e EnergyPerSpawn = 1.2 GJ, a estimativa pode passar de um dia, então o texto omite os dias e mostra um valor incorreto.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Resources/Locale/en-US/_NF/manufacturing/entity-spawn-power-consumer-component.ftl`
at line 2, The estimated-time label in entity-spawn-power-consumer-component.ftl
is formatting the TimeSpan with TOSTRING($time, "hh\\:mm\\:ss"), which wraps
after 24 hours and hides days. Update the localization string used by
entity-spawn-power-consumer-estimated-time so it formats long durations with
days included, and keep the change localized to the estimated-time output path
in the relevant manufacturing entity-spawn power consumer text.

Comment on lines +35 to +45
- type: BatteryInterface
minChargeRate: 50000
maxChargeRate: 1500000
minSupply: 50000
maxSupply: 1500000
- type: Battery
maxCharge: 80000000
- type: PowerNetworkBattery
maxSupply: 1500000
maxChargeRate: 50000
supplyRampTolerance: 50000

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

O limite real de carga ficou preso em 50 kW.

BatteryInterface.maxChargeRate permite 1.5 MW, mas PowerNetworkBattery.maxChargeRate continua em 50 kW. Na prática, o BLES vai anunciar uma taxa muito maior do que a rede consegue aplicar, o que deixa a máquina bem mais lenta do que o protótipo sugere. Alinhe os dois valores para evitar esse descompasso.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Resources/Prototypes/_NF/Entities/Structures/Power/smes.yml` around lines 35
- 45, The SMES prototype has a charge-rate mismatch:
BatteryInterface.maxChargeRate is much higher than
PowerNetworkBattery.maxChargeRate, so the device advertises more charging
capacity than the network can actually apply. Update the PowerNetworkBattery
values in the smes prototype to match the intended BatteryInterface charging
limits, and keep the related charge/supply settings consistent so the runtime
behavior matches the prototype's advertised rate.

@cristalyssd

Copy link
Copy Markdown
Contributor Author

Poderia fazer com que cada máquina dessas precisasse pesquisar na sci, facilitaria não precisar ser mapeado em todo mapa

O de fabricar combustível de AME acho ok. Mas o PTL não acho que seria bacana, pois é praticamente um rework do nosso PTL atual que é bem sem graça e que não incentiva os engenheiros buscar mais formas de fazer energia.

@CRISOOOOO

Copy link
Copy Markdown
Contributor

Poderia fazer com que cada máquina dessas precisasse pesquisar na sci, facilitaria não precisar ser mapeado em todo mapa

O de fabricar combustível de AME acho ok. Mas o PTL não acho que seria bacana, pois é praticamente um rework do nosso PTL atual que é bem sem graça e que não incentiva os engenheiros buscar mais formas de fazer energia.

Esse PTL novo é mapeado onde? Eu troco o nosso antigo por esse novo?

@cristalyssd

Copy link
Copy Markdown
Contributor Author

Poderia fazer com que cada máquina dessas precisasse pesquisar na sci, facilitaria não precisar ser mapeado em todo mapa

O de fabricar combustível de AME acho ok. Mas o PTL não acho que seria bacana, pois é praticamente um rework do nosso PTL atual que é bem sem graça e que não incentiva os engenheiros buscar mais formas de fazer energia.

Esse PTL novo é mapeado onde? Eu troco o nosso antigo por esse novo?

Sim, você pode trocar o PTL antigo para o novo sem problemas. Mas faz o que tu achar melhor, vendo agora ele até parece que ocupa menos espaço do que PTL antigo.

@Unlimited-Pii

Copy link
Copy Markdown
Contributor

Deixar comentado aqui no Github, mas igual eu falei no Discord, tem diversas questões dessa PR que eu acharia que seria bom discutir sobre.

@cristalyssd

Copy link
Copy Markdown
Contributor Author

Deixar comentado aqui no Github, mas igual eu falei no Discord, tem diversas questões dessa PR que eu acharia que seria bom discutir sobre.

Mais 72 horas 🥺

@isTheSuperN0va

isTheSuperN0va commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

tá, algumas varias anotações que eu tivse sobre isso

essas são problemas que vale colocar em mente, mas n é necessario pra esse pr:

  1. as maquinas ptl e o fabricador não fazem barulho nenhum, pra umas maquinas enormes, isso é meio esquisito
  2. o fabricador anti-máteria não tem nenhum indicador de quando a proxima geração será (o ETA na ui n muda)
  3. o ^ não tem nenhum indicador na ui para se está sendo gerado atualmente ou n, além do indicador vermelho/amarelo no objeto em si
  4. esses sprites não são muito bom na minha opinião
  5. a bateria (BLES) não tem um sprite condizente com o nosso

agr esses problemas são problemas com esse pr que eu vi:

  1. a geração de dinheiro via excesso de energia é grande d+, fazendo calculos básicos, e tendo em mente o que é possivel nesse jogo, dá pra ver que teg com eletrolise + tesla/singulo... isso estoura muito a economia do jogo
  2. a geração de antimateria meio que é futil, sem necessidade ou sem sentido pro jogo, já que o trabalho de suprir os recursos da estação é da cargo, não da engi. por mais que a cargo tenha que suprir a engi com plastiaço, o custo é severamente reduzido, o equivalente de uma caixa que custa 25k é produzido com o material de um pacote comprado por 1k. isso n só deixa a cargo mais merda, mas como também machuca a economia do jogo.

do jeito que está atualmente, não acho que é uma boa dar merge. possivelmente seria bom colocar o PTL como pesquisa da sci, ou nerfar a geração de dinheiro de alguma maneira. sobre o fabricador anti materia, eu n sei sinceramente

voces podem me falar alguma coisa pra tentar me convencer, claro

@cristalyssd

Copy link
Copy Markdown
Contributor Author

tá, algumas varias anotações que eu tivse sobre isso

essas são problemas que vale colocar em mente, mas n é necessario pra esse pr:

  1. as maquinas ptl e o fabricador não fazem barulho nenhum, pra umas maquinas enormes, isso é meio esquisito
  2. o fabricador anti-máteria não tem nenhum indicador de quando a proxima geração será (o ETA na ui n muda)
  3. o ^ não tem nenhum indicador na ui para se está sendo gerado atualmente ou n, além do indicador vermelho/amarelo no objeto em si
  4. esses sprites não são muito bom na minha opinião
  5. a bateria (BLES) não tem um sprite condizente com o nosso

agr esses problemas são problemas com esse pr que eu vi:

  1. a geração de dinheiro via excesso de energia é grande d+, fazendo calculos básicos, e tendo em mente o que é possivel nesse jogo, dá pra ver que teg com eletrolise + tesla/singulo... isso estoura muito a economia do jogo
  2. a geração de antimateria meio que é futil, sem necessidade ou sem sentido pro jogo, já que o trabalho de suprir os recursos da estação é da cargo, não da engi. por mais que a cargo tenha que suprir a engi com plastiaço, o custo é severamente reduzido, o equivalente de uma caixa que custa 25k é produzido com o material de um pacote comprado por 1k. isso n só deixa a cargo mais merda, mas como também machuca a economia do jogo.

Respondendo algumas questões.

Não acredito que uma "outra" forma de ganhar dinheiro vá prejudicar ainda mais a cargo, pois ela é quebrada de qualquer forma não importa o que você faça para balancear. Quando você atinge a marca de cinquenta mil ou até mesmo abaixo disso, a quantidade de dinheiro torna obsoleta(Particularmente Departamento de Cargo só é importante para parte material, pois de resto ela é totalmente... inútil. Poucas pessoas vão para cargo sabendo que pode fazer tudo o que quiser com cinco mil de aço no silo). Particularmente PTL atual vs PTL novo não ia mudar o problema da cargo, pois ela está no fundo do poço de qualquer forma(Um rework completo da cargo seria mt bom, mas isso é outro tópico). :trollface:
Mas ao menos é mais dopamina para o pessoal que curte fazer mais outra formas de fazer energias e vê a porcentagem de dinheiro subindo. Uma coisa importante ressaltar é que você está analisando o melhor cenário de melhor geração de energia. Muitas das vezes os engenheiros sequer fazem os solares, pois sabem que a singularidade dá conta de manter a estação ou até mesmo fazer um TEG decente(Que desde o nerf pessoal tá sofrendo para fazer TEG acima de 200 KW ), sem falar que estaria alimentando estação também no meio do processo.

Eeh, eu acho legal fabricar AME. Acho mais um desafio do que um conteúdo propriamente legal mesmo, então particularmente nem ligo muito. Pode explodir.

Pequenos problema:

  1. PTL quando ligado faz barulho sim, é de uns raios bem doido. Que nem aquele coisinha que solta raios quando objeto se aproxima. Bem relaxante por sinal.

  2. Explode. Não teremos mais(!).

  3. Explode(!).

  4. Poh, PTL bingolão não é nada bonito também. O PTL novo é todo SCI estiloso.

  5. Complicado, é a parte mais complicada. Isso depois deveria receber um tópico adequado sobre padrão de sprite. Pois essa smes subframezada é a padrão, só que a nossa que é diferente pois a gente puxou do Funky.

Uns problemas:

Aparentemente tem um fabrica de gas ai no meio e sem prototype. Aparentemente... enfim, acredito devo apenas expurgar todo code que tenha haver com isso, certo? Dps fazer commit com as mudanças. Junto disso, essa smes subframezada nem tem como fazer dentro do jogo pelo que eu notei, então sei la. Poderia ser uma pesquisa da sci ou coisa parecida, mas padrao de sprite foge mt. Sobre fabricar AME nao acho necessario mesmo tambem, entao vou remover dps commit.

@isTheSuperN0va

Copy link
Copy Markdown
Collaborator

bem, a cargo estando na merda meio que n é desculpa pra deixar pior ainda.

sobre o audio, confesso que prestei mais atenção ao fabricador, que n tem audio mesmo.

o contador de dopamina se torna ainda melhor com um desafio invez de ser fácil que nem mamão, faz cada subida de numero ser mais satisfatorio.

n tenho certeza sobre esse nerf da teg? posso checar isso dps

@cristalyssd

Copy link
Copy Markdown
Contributor Author

bem, a cargo estando na merda meio que n é desculpa pra deixar pior ainda.

sobre o audio, confesso que prestei mais atenção ao fabricador, que n tem audio mesmo.

o contador de dopamina se torna ainda melhor com um desafio invez de ser fácil que nem mamão, faz cada subida de numero ser mais satisfatorio.

n tenho certeza sobre esse nerf da teg? posso checar isso dps

Mas cara, então proponha uma solução melhor para toda a cargo. Pois se a cargo quiser ela pode vender todo material start round minerado e não precisa fazer nenhuma bounty, e tu ainda está considerando uma estação com toda fonte de energia feita, sendo que isso tu dificilmente vê isso dentro do jogo. Se perguntar para qualquer um o que mais vê é a estação rodando só de AME.

Quero dizer, para tu ter uma quantidade igual PTL tu ia precisar gerar cerca de 1 MW constante. É mais desafio do que o atual, e ainda é mais legal do que o padrão.

Eu mesmo que fiz o nerf. TEG tá gerando uma seis vezes menos agora.

@Unlimited-Pii

Copy link
Copy Markdown
Contributor

O sprite do PTL atual ele combina com o restante, o novo é um estilo industrial e bruto mais diferente do nosso.

Questão de energia, SM e TEG são ápice, porém uma tesla consegue muito facilmente MWs, até a mais segura e básica das teslas.

Fora questão visual, em funcional eu acho que deveria remover muita coisa não usada daí.

  • Jarro AME grande
  • Conversor de gás
  • Bateria Bluespace

Acho que o PTP e Fab de anti matéria deveriam ser ambos pesquisas da Sci.

Fabricador deveria ser significativamente mais caro pra fazer um frasco, porque AME é seguro e quase invalida outros geradores de energia na maioria das estações.

O PTP eu achei o uso dele muito desinteressante. Não tem risco nenhum e nada de especial, é uma estrutura que aceita energia e sai dinheiro. PTL atual ele tem o risco de radiação e cria o laser que pode ser mal utilizado de forma ofensiva criando oportunidades antagonisticas. Dá mesma forma que não tem como roubar e se aproveitar da tentação de pegar o dinheiro, já que ele vai diretamente para a conta.

Em geral só achei legal da PR o fabricador de anti matéria, que é bem nicho mas existe. Mas é simples demais, acredito que fabricar anti matéria de forma mais interessante por meio de algo atmosférico como o cristalizador seria mais temático e divertido.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants