S9SourceNine Labs / CMAPI Docs 1.0
CMAPI / Maintainers

Game hooks

Planet Crafter hooks currently owned by CMAPI.

View source ↗
CMAPI 1.0.0Standalone runtimeWindows x64Tested with Planet Crafter 2.008

Planet Crafter hook research

This note records hooks verified in both the supplied Prologue and complete-game decompiled assemblies. The 0.5.0 full-game comparison is detailed in FULL-GAME-COMPATIBILITY.md.

Strong native hooks

Game type Native hook CMAPI opportunity Important behavior
PlayersManager RegisterToLocalPlayerStarted(Action) Implemented LocalPlayerStarted Calls immediately if the local player already exists; otherwise calls when added. CMAPI publishes after initialization completes.
PlayersManager RegisterToPlayerStarted(Action<PlayerMainController>) Implemented PlayerStarted Replays every existing controller before subscribing to future players.
PlayersManager RegisterToPlayerStopped(Action<PlayerMainController>) Implemented PlayerStopped Fires before removal, so CMAPI reconciles on its next update and publishes the completed transition.
SavedDataHandler OnSaved Game.Saved or SaveCompleted Fires after JSON serialization completes and _saving becomes false. There is no matching public pre-save event.
PlayerStatus OnPlayerDied Player.Died Invoked inside DieAndRespawn; ownership/server behavior must be normalized by CMAPI.
Sector static OnSectorLoaded World/sector lifecycle Global static event; CMAPI must avoid stale subscriptions across scene/session changes.

Usable but less stable surfaces

  • PlanetLoader.planetIsLoaded is a public Action field, not a C# event. CMAPI can subscribe with +=, but it should treat the field as a game implementation detail and reattach if the manager changes.
  • Inventory.inventoryContentModified and inventoryContentGrowthFinished are public delegate fields. Modification notifications are propagated through the game's inventory-watch machinery, so CMAPI should verify watch lifetime and multiplayer authority before promising a universal inventory event.
  • WorldObjectsHandler.OnWorldObjectFromSceneDestroyed and InventoriesHandler.OnWorldObjectFromSceneRetrieved expose useful object lifecycle signals, but a public CMAPI item/world-object model should exist before these types are surfaced to mods.
  • ChatHandler.OnChatMessageReceived is a clean event, but chat APIs should be designed alongside player identity and multiplayer rules.

Player identity findings

PlayerMainController.id is not a safe universal public identity. Its meaning varies between platform/account and fallback client identity, and replication behavior does not establish it as a stable cross-platform contract. CMAPI therefore exposes the Netcode owner/client ID through an adapter and explicitly defines it as session-scoped.

The runtime reads that inherited value inside the Planet Crafter adapter. Neither IPlayer nor ordinary mods reference Unity Netcode. A persistent account model should wait until platform identity and host/client replication behavior are verified across Steam and other supported backends.

Full-game adapter boundary

Only the runtime's game adapter knows about PlayersManager, PlayerMainController, player gauges, transforms, and Netcode ownership. The public API uses CMAPI-owned types. The full-game comparison proved that this boundary allowed CMAPI to replace and validate its binding without changing an ordinary mod's references or public player code.

SavedDataHandler.OnSaved remains a small, high-confidence game lifecycle addition. Player death is also now viable because it can reference IPlayer instead of exposing PlayerStatus. Inventory APIs should wait until CMAPI defines stable item and inventory abstractions plus host/client mutation rules.