


Serves live game state from a running Dyson Sphere Program game over a small
localhost HTTP server, so the DSP Resource Tree Planner (dsp-ultimate-suite.html)
can show a live view. Three endpoints:
GET http://localhost:8765/state researched tech / upgrade levels
{ "version":1, "running":true,
"states":[ {"id":1131,"level":1,"max":1,"unlocked":true},
{"id":2101,"level":4,"max":6,"unlocked":true} ] }
GET http://localhost:8765/protos full item proto dump (static, built once)
{ "version":2, "items":[
{"id":1101,"name":"Iron Ingot","grid":1101},
{"id":2303,"name":"Assembling Machine Mk.I","grid":2404,"model":65,
"w":3,"h":3,"zstep":5.05,"slots":[3,3,3,3]}, ... ] }
GET http://localhost:8765/rates cumulative production/consumption counters
{ "version":1, "running":true, "gameTick":123456,
"items":[ {"id":1101,"p":12345,"c":678}, ... ] }
/state: id is the in-game TechProto id. Leveled upgrades report level
(curLevel); the planner expands consecutive ids per level using FactorioLab's id map./protos: every item gets id/name/grid (inventory grid index); buildings
additionally get model (modelIndex), w/h (blueprint footprint in cells from
prefabDesc.blueprintBoxSize), zstep (vertical offset per stacked level,
prefabDesc.lapJoint.y) and slots (per-side sorter slot counts [N,E,S,W] from
prefabDesc.slotPoses). The mapper's "Load protos (plugin)" button consumes this
for exact blueprint export./rates: counters accumulate across all factories since plugin load via a
Harmony prefix on FactoryProductionStat.GameTick, which reads
productRegister/consumeRegister just before the game folds and zeroes them
(the same approach the BetterStats mod uses). The planner polls twice and computes
items/min from deltas: rate = Δcount / Δtick × 3600 (60 ticks/s). The planner's
Plan vs actual card does this automatically.dotnet build), or open the .csproj in Visual Studio / Rider.BepInEx and HarmonyX are restored from the official BepInEx NuGet feed
(nuget.config points at https://nuget.bepinex.dev/v3/index.json) — they are
compile-time references only; the game's BepInEx install provides them at runtime.
The only machine-specific path is the game install (for Assembly-CSharp.dll and
the Unity 2022.3 engine assemblies, which have no NuGet package):
DSPManaged in DSPPlannerExport.csproj to match your install, or pass it
on the command line:dotnet build -c Release -p:DSPManaged="C:\...\Dyson Sphere Program\DSPGAME_Data\Managed"
bin\Release\DSPPlannerExport.dll into
…\Dyson Sphere Program\BepInEx\plugins\.DSP Planner Export: serving http://localhost:8765/state, /protos, /ratesThe plugin ships on Thunderstore as Suite/DSP_Planner_Export (community
dyson-sphere-program). Publishing is a local, one-command step — it can't run in CI
because the build needs the game's Assembly-CSharp.dll, which a runner doesn't have.
One-time setup:
.config/dotnet-tools.json): dotnet tool restore — invoked as
dotnet tcli. (publish.ps1 runs the restore for you.)Suite team → Service Accounts
→ Add service account → copy the token. (tcli is stateless — no login / credential store —
so the token is supplied per publish; the script sources it for you.)pwsh ./publish.ps1 -SaveToken # prompts for the token (hidden), stores it encrypted
It's kept under your Windows account (DPAPI-encrypted at rest, target
DSPPlannerExport:ThunderstoreToken — visible in Control Panel → Credential Manager →
Windows Credentials), outside the repo. publish.ps1 then reads it automatically — no
pasting. Resolution order: $env:TCLI_AUTH_TOKEN (for CI / op run) → Credential Manager →
a one-off secure prompt if neither is set. Treat the token like a release key; to rotate it,
re-run -SaveToken.Each release:
VERSION in Plugin.cs (single source of truth — flows to the csproj manifest and
the Thunderstore version_number). Thunderstore versions are immutable and must strictly
increase, so re-publishing the same number fails.pwsh ./publish.ps1 — builds the DLL, packages the Thunderstore zip
(thunderstore.toml + icon.png + README.md + the DLL under BepInEx/plugins/…), and
uploads it via tcli. Use pwsh ./publish.ps1 -DryRun to build + package only (inspect
./build/*.zip) without uploading.The package metadata lives in thunderstore.toml; icon.png (256×256) is the listing icon and
is committed so every publish reuses it. Keep this in step with the web release: when the app
ships a version that changes the live-link contract, bump + publish the plugin too.
dsp-ultimate-suite.html./state every ~3 s and repaints the trees as you
research in-game. (While Live is on, manual ticks are overwritten on each poll.)/rates every 3 s and compares
the plan's computed per-item rates with what your factories actually produce and
consume (needs two samples before the first numbers appear)./protos for exact model indices,
footprints, z-steps and sorter slots when exporting blueprints.The optional overlay (toggle with F8) draws live deficits and — when
[Advisor] Enabled — a "Upgrades available" section listing researched building
tiers worth switching to (e.g. Conveyor Belt MK.II researched). It mirrors the
planner's 💡 Advisor. Configure which kinds appear in the BepInEx config (live-reloaded):
[Advisor] Enabled — master toggle for the advisor section.[Advisor] Belts / Sorters / Machines / Proliferator — pick which recommendations show.[Advisor] DismissKey (default F9) — hide the current tips; each returns only when a
still-newer tier unlocks (dismissals are remembered in [Advisor] Acknowledged).The advisor flags the highest unlocked tier above the base in each family (belts, sorters, assemblers/smelters/chemical plants/miners, proliferator) — Dark-Fog-only tiers are excluded.
file://, fetching http://localhost — allowed because the plugin sends
Access-Control-Allow-Origin: *. No HTTPS issues since the page isn't HTTPS.Port in Plugin.cs, or run once as administrator.GameMain.history.{techStates,ItemUnlocked}, TechState.{unlocked,curLevel,maxLevel},
LDB.items/models, PrefabDesc.{blueprintBoxSize,lapJoint,slotPoses},
FactoryProductionStat.{GameTick,productRegister,consumeRegister}, GameMain.gameTick.
All verified to compile against the current build (Unity 2022.3.62, 2026-06). If a
future patch renames them, the compiler will point at the exact spot — the planner
side needs no change./rates counters reset when the plugin reloads; the planner detects the tick going
backwards and re-seeds automatically.