Appearance
Reference overview
The types here are generated from one source of truth, plot/schema/host-api.mjs; the tables on these pages are filled in from it by gen.mjs (node docs/developers/reference/gen.mjs, or --check to see if they're current). The generated TypeScript is plot/sdk/host.d.ts; plot/sdk/AGENTS.md has the same tables in compact form. When these pages and those files disagree, the generated files are current.
| Page | What |
|---|---|
| Hooks | the functions you export, and when the host calls them |
| Host API | every module and call: scene, input, network, assets, storage, lobbies, world, players, ui, content, mods, audio, time, log |
| Components | the scene's components |
| plot.json | the manifest |
| The Minecraft layer | @inventery/minecraft (registries, events, structures, world gen) and @inventery/lobby |
| Other languages | C, C++, Rust, C#, Zig and the raw ABI |
Imports
ts
import { scene, world, players, ui, storage, lobbies, time, isHostError } from "@inventery/host";
import type { PlayerId, Vec3, BlockEvent } from "@inventery/host";
import { blocks, items, recipes, entities, structures, worldgen, events } from "@inventery/minecraft"; // optional
import { defineLobbyGame } from "@inventery/lobby"; // optionalFor editor types, add plot/sdk/host.d.ts to your tsconfig's files and map the libraries in paths:
json
{
"compilerOptions": {
"strict": true, "noEmit": true, "target": "es2020", "module": "esnext", "moduleResolution": "bundler",
"paths": { "@inventery/minecraft": ["<sdk>/lib/minecraft.ts"], "@inventery/lobby": ["<sdk>/lib/lobby.ts"] }
},
"files": ["<sdk>/host.d.ts", "logic.ts"]
}build.mjs resolves these imports when it bundles.
Contexts
Every call and hook has a context:
| Context | Where | Calls allowed |
|---|---|---|
| lobby | lobby hooks (onPlayerEnter, tickLobby, onBlockBreak...), or inside lobbies.runWithin(id, fn) | lobby calls and any calls, acting on that lobby |
| plot | top-level code, init, chooseLobby, tickPlot, tickAllLobbies, onUpgrade | plot calls and any calls; registries; writes to the shared base |
| any | either | works in both; in a lobby it acts on the lobby, at plot level on the shared base |
onTimer and onModEvent run in the context they were set or sent in. In tickAllLobbies, lobbies.switchTo(id) carries on in a lobby's context.
Errors: refusals
A refused call throws a HostError with rule, call and a message that names the rule and the fix. Uncaught, it fails the hook and its writes are rolled back.
ts
import { isHostError } from "@inventery/host";
try { players.teleport(p, SPAWN); }
catch (e) {
if (isHostError(e, "playerProtected")) time.startTimer(players.get(p)!.protectionSecondsLeft, "teleport", { p });
else throw e;
}Better: act in onPlayerProtectionEnd (or onCountdownEnd), and don't use refusals as a check (a refused call costs far more than a successful one).
| Rule | Means |
|---|---|
wrongContext | A lobby call at plot level outside lobbies.runWithin, a plot-level call inside a lobby hook, or a write to something outside the current lobby (another lobby's player or entity, the shared base from a lobby) |
outsidePlot | A position, box or chunk outside the plot (reads may reach one chunk outside) |
playerProtected | The player is protected: their 10 s entry protection, or a start countdown with protectEveryone, is running, or they're away (check player.protectionSecondsLeft; act in onPlayerProtectionEnd or onCountdownEnd) |
itemsStashed | The player's real items are off limits here: the plot stashes items (so there's nothing to keep), or the player keeps what they win and the call would touch base economy items or their real max health. |
overBudget | Over a limit: channel messages, block edits per tick, timers, runtime assets, terrain chunk replacements, or the tick rate. |
storageFull | The package's storage is over its quota (its share of the plot's 1 MB; delete keys you don't need) |
lobbyNotEmpty | The lobby still has players (move them out or wait until it's empty) |
playerBody | The entity is a real player's body, owned by the room: use the players module instead. |
notSupported | The call isn't implemented by this host version (any call may raise it) |
runtimeOnly | A Mod package made a call reserved to the plot's Runtime package (lobbies, movement, camera, buttons, keeping items, tick rate) |
badArguments | A missing or mistyped argument, or a value out of range; the message says which (any call may raise it) |
The design docs number some of these rules: playerProtected is R4 (entry protection), itemsStashed is R6 and R7 (stashed items, kept items).