feat(core): world providers for game-owned simulations, and optional physics - #39
Open
cmaycumber wants to merge 3 commits into
Open
cmaycumber wants to merge 3 commits into
cmaycumber wants to merge 3 commits into
Conversation
Games whose state lives in their own simulation (run as a renderoni system)
were invisible to agents: describe/observe listed only entities, check only
resolved entities.* paths, and the state hash never changed.
engine.worlds.register({ name, describe?, observe?, resolve?, hash? }) now
feeds all of them:
- describe: worlds.<name> = describe() (key present only with providers)
- observe tier 0: "## <name>" sections after the entity section; entities
reserve up to half the 500-byte budget, providers split the rest evenly,
unused provider bytes flow back to entities
- check: world.<name>.<path...> via resolve(), with explicit failures for a
missing provider, missing resolve() or a throwing resolve()
- getStateHash: provider digests appended in name order; with no hashing
providers the digest bytes are unchanged (pinned against upstream main)
Diagnostics: RND_0410 invalid provider, RND_0411 duplicate name,
RND_0413 invalid hash value.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
createRenderoni({ physics: false }) / new RenderoniEngine({ physics: false })
never load Rapier. The default engine is unchanged.
- physics.ts imports Rapier through a cached dynamic import() (loadRapier),
so bundlers split the ~2 MB inlined WASM into its own chunk. Every other
module uses `import type` only.
- Presets build descriptors from ctx.native.rapier (the loaded module)
instead of a static import.
- With physics disabled, step() skips the physics step, contact/sensor
processing and the canonical re-sync; engine.native.world and
ctx.native.rapier throw RND_0412 (physics presets fail before creating
anything); getStateHash works with no contacts.
A physics-free consumer bundle (esbuild, esm + splitting, three external)
goes from one 2,206,271-byte chunk containing the WASM to a 116,789-byte
entry plus a 2,101,004-byte Rapier chunk that is never loaded.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`npm install github:<user>/renderoni#<branch>` now runs `prepare` (`npm run build`), producing dist/ from source. The build does not need the network or the optional @github/copilot-sdk: the editor imports it through a non-literal specifier, so tsc and the tsup DTS pass no longer try to resolve its types when it is not installed. prepare sends the build log to stderr because npm also runs it for `npm pack --json`, whose stdout the release contract gate parses as JSON. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Some games keep their state in their own simulation (run as a renderoni system) rather than as renderoni entities. For those games the MCP tools saw nothing:
describe/observelisted only entities,checkresolved onlyentities.*paths, and the state hash never changed.World providers
engine.worlds.register({ name, describe?, observe?, resolve?, hash? })feeds all of them:worlds.<name>. The key is present only when providers are registered.## <name>sections. Entities keep up to half the budget, and unused provider bytes flow back to them.world.<name>.<path>paths go throughresolve(), with explicit failures for a missing provider, a missingresolve, or a throwingresolve.Optional physics
createRenderoni({ physics: false })never loads Rapier. Rapier is now a cached dynamicimport(), so bundlers split the WASM into its own chunk. Presets take it fromctx.native.rapier. The default engine is unchanged. A physics-free consumer bundle drops from about 2.2 MB to about 117 KB.preparescriptGit installs (
npm install github:user/renderoni#branch) now builddist.Question for you: with
physics: false, Rapier could become an optional peer (peerDependenciesMeta). Our fork does this, but it conflicts with the package-contract test that requires it, so this PR leaves the contract alone. I'm happy to add it here if you want it.Verification: typecheck, build, and the full test suite pass. I'm using this in a real game (Sunder March, a Kenshi-like) whose whole simulation is exposed over MCP through a world provider.
🤖 Generated with Claude Code