CMAPI 1.0.0 standalone release validation
This is the release-blocking pass for synchronized weather, world/environment APIs, command readability, discovery, diagnostics, native HUD notifications, public mutations, Steam integration, save safety, and console tools. Record the exact Planet Crafter version, gameinfo MVID, CMAPI console output, bootstrap log, and runtime log when any step fails.
1. Prepare the full game
- Close Planet Crafter and every CMAPI console.
- Launch the game normally once and close it.
- Use a clean game copy or an installation already owned by a CMAPI standalone receipt. Do not overwrite an unrelated root bootstrap.
- Remove old CMAPI runtime and test-mod copies from the disposable installation so the pass begins from a known state.
Do not reuse the Prologue directory.
2. Synchronize, build, and deploy
From the CMAPI repository:
.\scripts\Sync-GameReferences.ps1 `
-GamePath "C:\Program Files (x86)\Steam\steamapps\common\The Planet Crafter"Confirm it copies the full game's Assembly-CSharp, Unity, Netcode, input, and text-rendering references into CMAPI\Libs. Clean and rebuild the solution in Visual Studio, then deploy without rebuilding:
.\scripts\Deploy-Dev.ps1 `
-GamePath "C:\Program Files (x86)\Steam\steamapps\common\The Planet Crafter" `
-SkipBuild `
-SkipReferenceSyncThe deployment must include CMAPI.API.xml beside CMAPI.API.dll. Hover over ConsoleCommands, IPlayer, IPlayerPlacementManager, PlayerPlacementResult, IWeatherManager, IWorldStateManager, IEnvironmentManager, IPlanetManager, and their members in the test mod and confirm the XML summaries appear.
3. Launcher and compatibility startup
Start CMAPI.Console from Visual Studio. Later, also run the built CMAPI.exe with no path and confirm automatic Steam detection.
Expected startup:
- The CMAPI 1.0.0 banner appears.
- The complete game launches and the runtime connects.
- CMAPI reports the detected game version and
520dcd8f-2c13-4a99-b871-44c7ad40bcc1as the tested full-game MVID. Full-game player, environment, and trainer compatibility checks passedappears.CMAPI Test Mod 1.0.0loads once and reports gameplay, placement, environment, content, inventory, lifecycle, storage, scheduler, and game-loop services.- The console reaches
CMAPI is readywithout a red error.
Run:
version
gameinfo
health_check
config
mods
modinfo SourceNineLabs.CMAPITestMod
help
commands
commands gameplay
commands backup
commands tokens
commands testing
commands SourceNine
commands environment
help give_tokens
help test_say
help weather
help env
Confirm:
gameinfosays tested full-game build with compatible player, environment, and trainer surfaces;health_checkreportsPASS, the correct full-game Mods/backup paths, registered canonical-command/mod-command counts, and current session state;configmatches every active setting and prints the correctconfig.jsonpath;modinfoincludes the description,Public API 1.0.0+, commands, and update status;commandsshows every canonical command once in the expected category; category, description, alias, and provider searches return the right entries;help give_tokensresolves to canonicalgive_money, andhelp test_sayresolves totest_echo, showing aliases, category, provider, and usage;helpopens the same complete catalog ascommands, including all eleven test-mod commands. With default cheat settings, expect 49 canonical commands and 13 aliases in this test build;commands SourceNinefinds test-mod commands through provider Unique ID;- headings, command names, field labels, warnings, failures, and table separators are visually distinct without harming alignment;
- every runtime line has exactly one normal space between labels, such as
[INFO] [CMAPI]and[WARNING] [CMAPI], with no alignment padding.
4. Manifest and update behavior
On first launch, confirm <GameRoot>\CMAPI\config.json is created with CMAPI and mod update checks enabled, a six-hour interval, a ten-second timeout, and ModMenuToggleKey set to Insert.
Run:
updates
updates check
updates
The internal test mod intentionally has no public update key, so it should be reported as no update key. A fresh check must never freeze the game or console.
For fixture testing, make temporary manifest copies and verify CMAPI rejects:
- missing or blank
Description; - malformed
VersionorMinimumApiVersion; - a minimum API version newer than 1.0.0;
- a one-part, spaced, or symbol-containing
UniqueID; - duplicate or malformed
UpdateKeys; - more than ten update keys;
GitHub:keys not usingowner/repository;- an
EntryDllpath outside the mod directory.
Each failure should name the folder and list every independent metadata issue. Also test CheckForUpdates: false; updates should report checks disabled and the game should not make mod-provider requests.
Before public release, point a temporary mod at a real GitHub repository and test cached up-to-date, available, timeout/offline, invalid tag, and HTTP failure states. Nexus: should report unsupported without failing the mod.
5. Command behavior
Run:
help test_player
help test_echo
test_say alias path works
test_echo one two three
test_echo "hello planet crafter"
test_echo "say \"hello\""
test_echo
test_echo "missing end
test_playr
notify CMAPI notifications are working
test_notify Public notification API working
players unexpected
modinfo
modinfo one two
Confirm quoted text and escaped quotes parse correctly, missing arguments print standard usage, the test_say alias reaches test_echo with the full argument list, unmatched quotes produce a syntax error, test_playr suggests test_player, and no input disconnects the console. HELP TEST_ECHO must work case-insensitively.
Both notification commands must produce one native HUD information card while inside a world. At the main menu, they may remain queued for up to 20 seconds; they must never throw or create a permanent queue.
6. Steam launch and coupled lifetime
With the game closed, run:
.\CMAPI.exe --steam-launch-optionConfirm the printed value contains the absolute CMAPI.exe path followed by %command% and is copied to the clipboard. Paste it into Steam Launch Options, launch from Steam, and confirm Steam arguments reach Planet Crafter unchanged.
Test lifetime directions separately:
- Quit from the game's menu; CMAPI must report the exit code, create a post-exit backup, and close.
- Press Ctrl+C in CMAPI while in a world; the game should close normally within 15 seconds and CMAPI should close afterward.
- After saving, close the CMAPI window with X; the Windows Job Object must end the game too. This is a hard-shutdown test, so use a disposable copy of a save.
- Set each
Close*setting tofalsein turn and confirm only that lifetime direction is decoupled.
6A. Optional CMAPI Mod Menu 0.2.2
This separately versioned beta has two accepted navigation defects for the 1.0.0 core gate: L3+R3 may not open it on a physical controller, and the Browse/Search Item Catalog submenu may fail to activate. Record both results; use Insert and external items/give_item as the supported fallbacks. Input leakage, stuck cursor state, save mutation, or repeated trainer side effects are not accepted.
At the title screen, run:
version
cmapi_menu
CMAPI_Inject
cmapi_menu
cmapi_inject
Confirm version keeps CMAPI at 1.0.0, reports Public API 1.0.0, and separately reports CMAPI Mod Menu 0.2.2. Before injection, no CMAPI.ModMenu Unity object or overlay should exist. Injection at the title screen may create the module, but it must stay hidden with a clear input-capture explanation until a local player dispatcher exists. In a world, the first injection creates exactly one visible menu; the second is idempotent and only makes it visible. cmapi_menu must report Input: Captured by CMAPI while visible and Released after a normal hide.
Check every workspace at the title screen and again inside a disposable world:
- Player matches
players, exposes live vitals, and disables mutations before world load or for a joining client. - Inventory accepts exact item IDs, unquoted multi-word names, amounts, custom Terra Tokens, and quick grants. Record whether Browse/Search activates and populates; failure is the documented beta defect for this checkpoint.
- World matches
environment/weather_status, lists weather/meteor quick starts, rejects overlap, resets daylight, and shows Infinite Power readiness. - Teleport copies current coordinates, performs exact placement, and returns Back.
- Mods lists every loaded mod once and reports CMAPI 1.0.0 / Menu 0.2.2.
- Console runs built-in and test-mod commands and lists each canonical command once under its category with aliases.
Mouse/keyboard checks:
- Drag the window, resize the game, and switch windowed/borderless/fullscreen modes; it must shrink when needed and remain inside Unity's safe area.
- Click the target icon; the window must return to the current screen center.
- Open every drill-down page and scroll long content. At 1280x720 and the smallest supported window size, controls must remain readable and reachable.
- Click the window background, every row, field, and button. The entire menu must remain dark; no focused/active state may turn the window white or gray.
- The dedicated Insert key hides and restores the same injected menu at the same position. F8 must remain available to Planet Crafter's feedback/help screen and F9 must not open the store through CMAPI. If testing a keyboard where
Insis only a secondary numpad-0 label, document the required Num Lock/Fn state separately. - Set
ModMenuToggleKeyto another valid Input System key while CMAPI is closed, restart, and confirm the footer and toggle behavior match it. Bind it to a known game action and confirm CMAPI reports the conflict and chooses an unbound session fallback. Restore Insert. - Cursor lock/visibility returns to the prior game state after hide.
- Click
Uninject; the overlay disappears and the cursor restores. Open Pause immediately and confirm the mouse is visible and usable. Repeat while Pause was already open before injection. A new injection should begin centered. - With the menu visible over both gameplay and Pause, press movement, inventory, construction, Escape, Enter, controller UI buttons, and click directly over underlying Pause buttons. No Planet Crafter action, mouse click, controller submit, or background UI selection may fire. CMAPI's own mouse must remain visible/clickable. Hide the menu and confirm every prior game input works.
- Run commands that produce long output. Activity must remain inside the page scroll area with no text or footer clipped below the frame.
Controller checks with at least one Xbox-layout pad and, if available, a PlayStation-compatible pad:
- Inject from the console and confirm the footer switches to controller help.
- D-pad up/down moves the cyan action selection; A opens the selected page or activates its toggle, speed cycle, quick action, weather entry, or diagnostic.
- Try Inventory → Browse/Search Items and record whether it activates and populates. If it works, browse/select with D-pad and A; otherwise continue with external
items/give_itemand record the known beta defect. - LB/RB scroll long content and D-pad selection automatically scrolls into view.
- Analog sticks do not scroll or move the menu; X centers it.
- B returns to the main page, then hides. Try holding L3+R3 for roughly half a second and record whether it restores the menu. If it does not, use Insert; this is the documented beta controller-open defect. A short accidental press must never leave the game maps captured.
- Confirm View+Menu is not handled by CMAPI and does not open Steam through a CMAPI shortcut.
- One Y press arms but does not uninject. Let three seconds pass and confirm it cancels. Press Y twice within three seconds and confirm uninject.
- Confirm no controller step leaves the player moving, a game window stuck, or the cursor in the wrong state after hiding/uninjecting. Move/click the mouse while CMAPI is visible and confirm it immediately remains usable.
Trainer checks on a disposable host save:
god_mode status
god_mode on
infinite_oxygen toggle
infinite_water toggle
infinite_health toggle
no_toxicity toggle
no_fall_damage on
fly_mode on
move_speed 2
infinite_power on
Confirm toggles update in the menu within 0.25 seconds, native HUD feedback appears once per change, vitals stay full without per-frame RPC spam, flight and 2× movement work, fall damage is suppressed, and machines work without editing the displayed generator/consumer catalog. Leave Infinite Power on for at least ten seconds: no repeating energy-loss/restored HUD message or audio may occur. Construct or approach another requester and confirm it powers without starting an alert loop. Then switch every option off and confirm original flight, walk/run speed, fall damage, and real grid behavior return. Repeat with active effects, then cmapi_uninject; all effects must be disabled/restored while CMAPI and mods remain loaded.
Test god_mode against ordinary gauge drain and representative fall/meteor damage. Do not claim protection from scripted instant-death/story transitions until those cases pass separately. Confirm no stamina control is shown because the tested assembly has no independent stamina gauge.
Join another host as a client and confirm every trainer command and menu action is disabled or reports host-only. Leave/re-enter a save and return to title with effects active; CMAPI must restore/clear state without missing-reference errors.
Finally run:
cmapi_uninject
CMAPI_Uninject
cmapi_menu
health_check
Repeated uninject must be safe and report no injected menu. CMAPI, its console, all mods, environment APIs, and the game remain active. Also inject before planet travel, save switching, title return, and process shutdown; the menu must survive intended scene changes and be destroyed during runtime shutdown without MissingReferenceException, cursor, or IMGUI errors.
7. Player API before entering a world
At the main menu, run:
players
test_player
test_player nope
test_player 999
test_player 0 extra
Confirm clear no-player, invalid-ID, missing-player, and usage messages. There must be no repeated compatibility warning or synchronization exception while remaining at the menu.
8. Full-game world entry, gameplay commands, and live state
Enter a full-game save. The test mod should print exactly once:
Player started: <name> (client 0; local, host) | connected players: 1
Local player ready: <name> (client 0; local, host) at (...) | ... | manager match: True, lookup match: True
Run:
players
test_player
test_player 0
health_check
items uranium
give_item Iron 2
give_item Super Alloy 2
give_money 1000
teleport 414.61 8.3 585.28
teleport back
teleport bsck
test_api_item Iron 2
test_api_tokens 250
Confirm the same player/name/client ID appears everywhere. Move, consume oxygen and water, and rerun the commands. Position and gauges must update naturally. Exercise full-game areas unavailable in the Prologue—including travel or an alternate planet if the save permits—and confirm the player object remains valid or transitions cleanly.
For gameplay commands, confirm item searches show stable IDs and localized names; exact IDs and names grant the requested stack through the game's normal inventory handler; an ambiguous search lists candidates; invalid/zero/negative/ oversized amounts are rejected; and a backpack without enough space receives nothing. give_money and give_tokens must increase the shared Terra Token balance without an overflow. On a joining client, every mutation command must be rejected as host-only by default.
For teleporting, use known safe coordinates in a disposable save and exit any vehicle first. Confirm the player moves on the current planet, keeps their facing, receives native HUD feedback, takes no fall damage from the move, and teleport back returns to the exact origin. Reject missing values, non-numbers, NaN, infinity, and magnitudes over 1,000,000. A joining client must be rejected as host-only, and the command must never switch planets or move a vehicle. teleport bsck must suggest teleport back before printing usage.
Each successful item grant must show one native inventory notification with the item icon, localized name, inventory marker, and amount. Each Terra Token grant must show Planet Crafter's native Terra Token popup exactly once. Set ShowGameplayNotifications to false and confirm automatic grant notices stop without disabling commands or notify/test_notify.
In the test mod, confirm helper.Items.TryGetItem and FindItems return the same IDs shown by items, and helper.TerraTokens.Count tracks the live shared balance. test_api_item and test_api_tokens must log Success, requested and applied amounts, and show the same native notices. Test unknown IDs, invalid amounts, a full backpack, and execution from a joining client; the structured statuses must be ItemNotFound, InvalidArgument, InventoryFull, and HostRequired respectively. At the main menu, an empty item snapshot, unavailable token service, and WorldNotReady mutation results are valid.
Test the public placement surface separately from the built-in command:
test_api_teleport back
test_api_teleport 559 2 600
test_api_teleport back
test_api_teleport back
test_api_teleport clear
test_api_teleport back
The first call must log NoReturnPoint. Successful moves must log Success with exact origin/destination snapshots, show one native HUD notice, preserve facing, stay on the current planet, and alternate positions on repeated Back. Reject NaN, infinity, out-of-range coordinates, a joining client, player replacement, and planet travel with the documented structured status. Confirm clear must report HasReturnPoint: False; owner cleanup must do the same, and one mod cannot overwrite another mod's return point.
8A. Environment, world-state, and planet APIs
Enter a disposable host world and run:
environment
env
planets
world_state
world_state oxygen
world terraformation
weather_events
weather_list meteor
weather_status
weather
test_environment
test_world_state
test_weather
Confirm:
environmentandenvagree on planet, day/night value, local-player state, and active weather;planetsmarks exactly one current planet and correctly reports starting, natural-weather-count, and purification fields for installed/purchased worlds;world_statetotals and current/next stage match in-game screens, net rates change after building/removing a generator, and unit filtering is case-insensitive;weather_eventscontains each natural asset once even though Planet Crafter internally weights asteroid events twice, and shows exact IDs, readable names, duration, meteor/weather type, rain, wetness, and stage bounds;- every
test_*read matches its built-in command and logs no Unity/game type through the public contract.
Choose one ordinary weather event ID and one meteor/asteroid event ID from the catalog. Wait until no event is active, then run one at a time:
weather_start <exact ID>
weather_status
test_api_weather_start <exact ID>
For each successful start, confirm one native HUD notice, one CMAPI log, native environment/audio/rain/sky behavior, synchronized status progress, and normal event end. For a meteor event, confirm native shared seed/reference behavior and resource/asteroid spawning. Do not save over an important world during this test.
While an event is active, retry both start commands with the same and a different event. Every request must return AlreadyActive, leave current progress untouched, and produce no duplicate asteroid, audio, sky, wetness, or particle state. After natural end, confirm weather status becomes inactive and all effects clean up normally.
Find an event with stage bounds and test from saves outside and inside its range. Outside must return RequirementsNotMet; inside may start. If unit state has not initialized, the request must return WorldNotReady rather than bypass the stage check.
For a deliberate compatibility-gate test build, mark one required environment hook unavailable. gameinfo and health_check must identify it; mutations must return UnsupportedGameBuild; weather, world, environment, and planet reads must return unavailable or empty state without throwing.
Test daylight:
day_reset
test_api_day_reset
environment
Both mutation paths must reset the synchronized value to full day, notify once, leave terraformation values unchanged, and return HostRequired on a joining client. helper.Environment.IsUnderwater(localPlayer.Position) must agree with the local snapshot above and below active water; NaN/infinite programmatic queries must throw ArgumentOutOfRangeException without damaging the runtime.
Return to the title screen, switch saves, and travel to every accessible planet. Empty/unavailable snapshots during transitions are valid. After load, catalogs must refresh to the new planet with no stale IDs, current marker, weather state, stage, unit, or underwater result.
8B. Content, inventory, and lifecycle APIs
Run:
inventory
inventory backpack iron
inventory equipment
recipes iron
recipes CraftStationT2
recipe Super Alloy
unlocks available
unlocks locked
unlocks blueprint
unlock_info Iron
test_inventory backpack
test_inventory equipment
test_recipes uranium
test_unlocks chip
Compare at least three recipes against in-game screens, including one repeated ingredient and one non-default crafting station. Confirm output/ingredient ID and localized-name search, collapsed quantities, output kind, and station IDs. Check one base unlock, one progression lock, and one blueprint lock before and after its state changes; query results must be fresh and planet availability must match the current world.
Compare backpack/equipment capacity, occupied/free slots, and group counts. Add/remove and equip/unequip items through normal game actions. Test Mod must log exactly one native change callback per action, the right inventory/item/ direction, and a correct post-change snapshot. Exit/re-enter twice and confirm callbacks do not duplicate.
Verify Test Mod event order across world entry, a normal completed save, one available planet trip, a natural weather start/end, and world exit. Save events must not fire at request time. Old weather ends before planet/world teardown; WorldEntered, PlanetChanged, Saved, and WorldExited each fire exactly once at their documented boundary. A deliberately throwing test subscriber may be used in a private fixture: other subscribers must still run.
For a deliberate compatibility-gate test, mark one required content hook unavailable. gameinfo and health_check must list it, catalogs must be empty or snapshots unavailable, lifecycle callbacks must remain unbound, and CMAPI's loader/console/older APIs must continue without a runtime exception.
9. Save backups and restore
Before launch, confirm CMAPI creates a prelaunch ZIP under <GameRoot>\CMAPI\Backups. In a loaded disposable world, run:
backups
backup create
Confirm the game saves first, one manual ZIP appears only after the save finishes, and its cmapi-backup.json metadata plus Saves/*.json/.sav entries open cleanly. Quit normally and confirm one postexit ZIP. Set BackupRetentionCount to 3, create enough snapshots, and confirm only the three newest remain.
With the game closed, run:
.\CMAPI.exe --list-backups
.\CMAPI.exe --restore-backup "<one listed filename>"Confirm restore first creates a pre-restore backup, overwrites the archived save files, leaves unrelated saves untouched, and the restored world loads. Attempt restore while the game is open, from a path outside CMAPI\Backups, and with a ZIP containing traversal, nested, duplicate, or unsupported entries; every attempt must stop without changing saves.
10. World exit, re-entry, and save switching
Return to the title screen without closing the process. Expect exactly once:
Local player stopped: <name> ... | snapshot retained: True
Player stopped: <name> ... | connected players: 0
players, test_player, and health_check should report zero players. Re-enter the same save, then a different save, and confirm start/stop pairs remain balanced with no stale player, duplicate callback, destroyed-object error, or changed event ordering.
11. Multiplayer release gate
This section is required before an eventual official release:
- Host a world and join from a second complete-game client.
- Confirm one
PlayerStartedfor the remote player. - Verify two distinct client IDs and correct host/local roles with
players. - Run
test_player <clientId>for both players. - Travel/change planet if multiplayer permits and recheck the roster.
- Disconnect and reconnect the second player.
- Confirm one stop/start pair and no stale registry entry.
- Close the host session and verify both clients shut down cleanly.
- Verify
give_itemandgive_moneywork only from the host's console and propagate normally to the shared world/local host inventory. - Verify
test_api_itemandtest_api_tokensreturnHostRequiredon the joining client even ifRequireHostForCheatCommandsis set tofalse. - Start ordinary weather and a meteor event from the host. Confirm both clients show the same active event, progress, environment, and normal end.
- Confirm
weather_start,test_api_weather_start,day_reset, andtest_api_day_resetreturnHostRequiredfrom the joining client. - Attempt overlap from host and client while meteor weather is active; current weather and asteroid state must remain unchanged.
Repeat key checks from the joining client's CMAPI console. Client IDs remain a session identity, not a Steam/account identity.
12. Isolation and shutdown
Use temporary test mods to prove duplicate command collisions name the existing provider, throwing command/event handlers do not block later handlers, and a throwing Entry leaves neither events nor commands registered.
Close Planet Crafter normally. The console must report the exit code without an unhandled pipe, update-task, command, thread, reflection, or destroyed-Unity exception. Repeat once while offline so both CMAPI and mod update checks fail open without delaying shutdown.
13. Release-package smoke test
After all development checks pass:
.\scripts\Build-Release.ps1 `
-GamePath "C:\Program Files (x86)\Steam\steamapps\common\The Planet Crafter"Run the generated setup wizard against a second clean full-game installation. Confirm the launcher runs without a separately installed .NET runtime, detects the game from the game root, passes health_check, and does not ship the internal test mod, build output, source references, or Visual Studio files. Verify the archive against its generated .sha256 sidecar before extraction. Build-Release.ps1 runs Verify-Release.ps1 automatically; also run the verifier directly against the final files after copying them to the upload location.