feat: v2.0.0 -- confirmed working, scaffolding removed

Confirmed in game. The radiator's thermal-ammo and hold signals both
arrive, VentAllowed goes false, and the radiator idles with its manual
switch still on -- heat banked for the launchers instead of vented.

The self-test probes did their job: ThresholdToggle was fine, and a
mod-defined category carries a value perfectly well. The EMP probe was
simply a bad probe -- it read thermal_load_dissipation, which an idled
radiator broadcasts as zero, so it was correctly reporting a real zero.
Routing in v1.3.0 was the actual cure.

Remove the probes and the diagnostic indicators. The repointed power
indicator is the one cue a player needs: it now shows on a radiator the
mod has idled.

Add test_override_values_name_real_components, which catches an Overrides
value naming a component that does not exist -- a fourth way to produce a
mod that loads clean and does nothing, and one this very commit
introduced while stripping the scaffolding.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oLWY1G6S8U35bi2FxVWni
This commit is contained in:
2026-08-29 00:27:25 +02:00
co-authored by Claude Opus 5
parent 323ee90f3d
commit d82b7e43a4
5 changed files with 99 additions and 212 deletions
+47 -61
View File
@@ -115,84 +115,70 @@ removes it. If the script cannot find your Mods folder, set `COSMOTEER_MODS_DIR`
python3 tests/test_mod.py
```
Cosmoteer applies mod actions to vanilla data at load time, and a path that does
not resolve, a component reference pointing at nothing, or a misspelled
component `Type` all fail identically: the game crashes on startup and leaves a
log file. The suite parses the installed game's `.rules` tree and checks all
three offline. It also self-checks the parser against known vanilla facts first,
so a broken parser fails loudly instead of passing everything.
Cosmoteer applies mod actions to vanilla data at load time. Some mistakes crash
the game on startup — an unresolvable path, a misspelled component `Type` — and
the suite catches those by parsing the installed game's `.rules` tree offline.
Set `COSMOTEER_DATA` to point at a different install.
The more dangerous mistakes do not crash anything. They load perfectly and
silently do nothing; see **Status** below for the four this project hit and the
guard for each. The suite also self-checks its own parser against known vanilla
facts first, so a broken parser fails loudly instead of passing everything.
Set `COSMOTEER_DATA` to point at a different install, and `COSMOTEER_ASSEMBLY`
for the schema checks.
## How to tell it is working
There is no separate "auto" mode and nothing to reset. The radiator's on/off
switch is an AND gate:
- switch **off** → radiator is off, and stays off. The mod never turns it back on.
- switch **on** → the automation decides, moment to moment.
- switch **off** -> radiator is off, and stays off. The mod never turns it back on.
- switch **on** -> the automation decides, moment to moment.
An auto-idled radiator shows the same "powered off" indicator icon as a manually
switched-off one, and stops emitting its steam plume. That icon appearing on a
radiator you did *not* switch off is the mod working.
## Reading the diagnostic icons
The radiator reports its own internal state through indicator icons. An icon is
drawn while its toggle is **off**, so:
| Icon on a radiator | Meaning |
|---|---|
| 🔧 wrench (`MissingComponent`) | **Always expected.** Its absence means the mod's components never merged onto the part, and nothing else in the mod is running. |
| thermal missile | No thermal-ammo signal is reaching this radiator — no launcher on its heat network is set to Thermal Canister Missiles. |
| resource | No hold signal is reaching this radiator — no thermal battery on its network is asking it to hold. |
| power-off | The radiator is idle: either you switched it off, or the automation idled it. |
A correctly working setup, on a ship with a thermal launcher and a battery below
the vent ceiling, shows **the wrench alone**.
These make the failure legible rather than guessable: wrench missing points at
the patch mechanism, either other icon points at the specific signal that is
dead.
An auto-idled radiator shows the "powered off" indicator icon and stops emitting
its steam plume. That icon on a radiator you did *not* switch off is the mod
holding heat back for your launchers.
## Status
Validated against game data version 0.30.4c, and confirmed to load cleanly
(`Enabled mods: [User Folder] - ganter.auto_radiator`).
Working, confirmed in game on 2026-08-29 against game data version 0.30.4c.
**v1.0.0 loaded without error and did nothing in game.** It broadcast its
signals with `NetworkToggle` / `NetworkToggleReceiver`. All three vanilla uses of
those types set `IncludeInPhysical = false` — they are blueprint stat-display
plumbing and carry no signal on a real ship, so every receiver read off, the
vent gate was permanently open, and radiators behaved exactly as in vanilla.
Getting there took four builds that each loaded without a single error and did
nothing, for four different reasons. Cosmoteer reports none of them, so each one
now has a mutation-verified test:
**v1.1.0** carried the signals as `NetworkValue` / `NetworkValueReceiver`
instead, which is what vanilla's thermal amplification pump uses to drive actual
physical behaviour. That was necessary but not sufficient: it also loaded
cleanly and did nothing.
| Silent failure | Guard |
|---|---|
| `NetworkToggle` / `NetworkToggleReceiver` carry no signal on a physical ship (every vanilla use sets `IncludeInPhysical = false`) | `test_no_blueprint_only_signal_types`, plus `test_vanilla_marks_those_types_blueprint_only` so the premise cannot go stale |
| A field name that does not exist in the component's real schema is ignored rather than reported | `test_component_fields_exist_in_schema`, read from the assembly's own metadata |
| A network component no route reaches never attaches, and reads as absent forever | `test_network_components_are_routed` |
| An `Overrides` value naming a component that is not there reverts the gate to nothing | `test_override_values_name_real_components` |
**v1.2.0** added the diagnostic indicator icons, which is what finally located
the fault. The wrench icon was present — so `AddBase` and the `Overrides` had
been applying correctly the whole time — while both signal icons showed,
meaning both `NetworkValue`s read zero.
**v1.3.0** fixes the actual cause. A network component is only attached to the
network if a **route** reaches it: the part's `NetworkPort` anchors on one
component, and a `NetworkRouter` bridges that anchor to every other network
component on the part. That is how vanilla connects the radiator's own
The third was the actual cause. A network component is only attached if a
**route** reaches it: the part's `NetworkPort` anchors on one component, and a
`NetworkRouter` bridges that anchor to every other network component on the
part. That is how vanilla connects the radiator's own
`NetworkedThermalDissipationLoadValue`, and how the amplification pump reaches
the resonance beam turret. Unrouted components are not an error — they simply
never connect and read as absent forever.
the resonance beam turret. Routes now run from each part's anchor —
`NetworkedHeatBuffer` on the radiator through its existing `Router`, plus a new
`NetworkRouter` on the thermal battery, the missile launcher and
`base_part_overclock`, none of which ships one.
Routes were added from each part's anchor: `NetworkedHeatBuffer` on the radiator
through its existing `Router`, plus a new `NetworkRouter` on the thermal
battery, the missile launcher and `base_part_overclock`, none of which ships
one.
None of this is documented: the wiki's modding pages cover no network components
at all, so the game's own `.rules` files are the only reference.
Three separate mechanisms have now each produced a mod that loads without a
single error and silently does nothing. The test suite has a mutation-verified
guard for each: blueprint-only signal types, fields that do not exist in the
real schema, and unrouted network components.
`tools/dotnet_enum.py` reads component schemas and enum members straight out of
`Cosmoteer.dll`, which is how the field and type questions got settled. It is
useful on its own for any Cosmoteer modding:
```sh
python3 tools/dotnet_enum.py /path/to/Cosmoteer.dll PartThresholdToggleRules
python3 tools/dotnet_enum.py /path/to/Cosmoteer.dll MultiToggleMode
```
Version 1.4.0 in the git history carries a probe build that makes a radiator
report its own internal state through indicator icons, if this ever needs
debugging again.
## Possible additions