{"slug": "bloxd-mock-api-run-bloxd-world-code-outside-bloxd", "title": "Bloxd Mock API — run Bloxd world code outside Bloxd", "summary": "A developer known as Oreo_belt25, working with Claude, released Bloxd Mock API, an open-source Node.js tool that runs Bloxd world code outside the Bloxd engine to catch typos, bad arguments and engine quirks before deployment. The toolkit generates a JSON description of the editor's TypeScript declarations — covering 247 functions, 95 optional parameters and 80 callbacks from bloxd-types 0.1.2 — and includes a mock api object, a command-line runner that simulates players and ticks, a quirks file documenting where the real engine disagrees with the docs, and 45 self-test checks.", "body_md": "Run Bloxd world code on your own computer, without Bloxd. Catch typos, bad arguments and known engine traps before you paste anything into a world.\n\nMade by Oreo_belt25 with Claude. Free to use and change, just give a shoutout.\n\n| File | What it does | \n|---|---|\n| `mkmock.py` | Reads the editor's TypeScript declarations (or, as a fallback, the docs pages) and writes `bloxd_api.json` : every api function with its parameters, which ones are optional, and its return type, plus every callback | \n| `bloxd_api.json` | The generated description: 247 functions (95 optional parameters marked) and 80 callbacks, from `bloxd-types` 0.1.2, checked identical to the live editor's types on 25 Sep 2026 | \n| `mock_api.mjs` | Builds a fake `api` object from that JSON | \n| `quirks.mjs` | Places where the real engine disagrees with the docs, found by testing in-engine | \n| `run.mjs` | Command-line runner: loads your world code, simulates players and ticks, prints a report | \n| `selftest.mjs` | 45 checks that the mock still catches what it should. Run `node selftest.mjs` after any change | \n| `broken_world.js` | A deliberately broken file to see the report in action | \n| `quirk_probe_1.js` | World code that re-checks every rule in `quirks.mjs` in a real Bloxd world. Paste it into a test world and type`!help` | \n\n- Node.js 18 or newer\n- Python 3 (only to regenerate `bloxd_api.json` ). On Windows the command is\nusually`python` or`py` instead of`python3` . Without Python, the two`mkmock.py` self-test checks are skipped and everything else still runs\n\nNo packages to install.\n\n```\nnode run.mjs my_world.js\nnode run.mjs my_world.js --players 4 --ticks 400\nnode run.mjs my_world.js --chat \"!help\" --chat \"p2:!stats\" -v\n```\n\nThe runner joins the players, runs the tick loop (20 ticks = 1 second), sends any chat messages halfway through, then prints:\n\n- which callbacks your code defines\n- total api calls, the average per tick, and **the busiest tick** with what\nwas called on it (useful for spotting work that should be spread across ticks)\n- errors thrown inside callbacks (typos, calls that crash in-engine)\n- warnings (arguments the docs or the engine won't accept)\n\nOptions: `--players N`, `--ticks N`, `--chat MSG` (repeatable), `--null off|warn|throw`,\n`--null-returns` (every \"possibly null\" function returns null, to test your null guards),\n`--timeout-ms N` (how long one callback may run, default 10000),\n`--fire NAME` (fire any callback once halfway through, with placeholder arguments\nbuilt from its documented parameters; repeatable),\n`-v` to print everything shown to players (chat, middle and crosshair text,\nflying messages, popups, killfeed, and HUD text options like `RightInfoText`;\nHUD text re-set unchanged every tick is printed once), `--json` for machine-readable output.\nThe exit code is 2 if any callback threw, so it works in scripts.\n\n1. \n**The editor's types become data.**`mkmock.py` reads the same TypeScript\ndeclarations the Bloxd code editor uses for autocomplete, so it knows exact\ntypes and which arguments are optional. (It can also read the plain-text docs\npages, which don't mark optional arguments.) Each\nfunction's documented return type is mapped to a placeholder: a`number` returns 0, an inventory item returns`{name: \"Stone\", amount: 1, attributes: {}}` ,\nand so on. Ids are fresh on every call (`m_mock_1` ,`m_mock_2` ...), so two\nspawned mobs never share an id. \"Possibly null\" (`PNull<...>` ) functions\nreturn a real value by default, so spawns succeed and the happy path runs;`--null-returns` flips them all to null to check your guards.\n2. \n**Every call is checked.** Too many or too few arguments (a required one left\nout), null where the types don't allow it, explicit`undefined` in the middle of an argument list, and oversized\narguments all get flagged. Calling a function that isn't in the docs throws,\nwhich catches typos like`api.sendMesage` .\n3. \n**Some functions really work.** Player lists, player and lobby DB values,\npositions,`getBlock` /`setBlock` and`api.now()` keep real state, so most\nworld code runs normally instead of falling over on placeholder values.\n4. \n**The clock behaves like Bloxd's.**`Date.now()` is frozen for the whole tick\nand jumps 50 ms between ticks, as it does in-engine. A \"stop after 5 ms\" loop\nbudget never trips in Bloxd, so when one callback reads`Date.now()` hundreds of times in a single call, the report flags it with a`[clock]` warning before it lags a lobby.\nLike the engine, any callback that runs for about 10 s is stopped and\nreported as`InternalError: interrupted` , so an infinite loop shows up as\nan error instead of freezing your terminal. The mock then stops firing\nthat callback for the rest of the run.\n5. \n**Callback return values are checked.** The Callbacks page lists what each\ncallback may return. Returning something else, such as`\"preventchange\"` instead of`\"preventChange\"` , does nothing in-engine, so the mock warns and\nsuggests the right spelling. Callbacks whose documented return includes a\nnamed object type are skipped rather than risk a false warning.\n6. \n**Engine findings override the docs.**`quirks.mjs` holds behaviour confirmed\nby in-engine probes that contradicts or goes beyond the docs. Every rule was\nre-checked in-engine on 27 Sep 2026 by`quirk_probe_1.js` . Examples:\n  - returning `null` from a callback**prevents** the action: a block change, a\ndrop, or a hit on a mob or player, just like the documented`\"prevent...\"` strings. Return nothing to allow it. The typo`\"preventchange\"` is ignored\n  - `setItemSlot` and both chest functions reject amount`-1` , although the docs suggest it\n  - `setMobSetting(..., \"heldItemName\", null)` is the correct way to clear it;`\"\"` throws\n  - `setMobAiState` needs an explicit`null` for params\n  - `getCraftingRecipesForPlayer` throws an error`try/catch` can't catch\n  - an `{icon}` in a player's name tag is rejected, although the types allow it\n  - `setItemStat` 's`CrosshairText` and bow`secondaryDamage` are accepted but do nothing\n  - a `ParticleEmitter` attached to an entity node, and a mesh`Box` with only`emissiveColor` , are accepted but draw nothing\n  - `\"peacefulAdventure\"` is rejected; gamemode names are all lowercase\n  - `isNearInterrupt` does turn true late in a long callback; the mock\nsays true once a callback has used 80% of`--timeout-ms`\n The probe also caught four rules Bloxd had fixed, which the mock no longer flags: `animateEntity(id, null)` ,`giveItem` with an explicit`undefined` ,`getHeldItem` without`attributes` , and hand-built`tameInfo` .\n7. returning \n\n``` js\nimport { makeMockApi } from \"./mock_api.mjs\";\n\nconst mock = makeMockApi({\n  players: [\"p1\", \"p2\"],\n  overrides: { getBlock: () => \"Stone\" },   // replace any function\n});\nmock.api.setPlayerDbValue(\"p1\", \"coins\", 5);\nmock.api.getPlayerDbValue(\"p1\", \"coins\");   // -> 5\nmock.countCalls(\"setPlayerDbValue\");        // -> 1\nmock.warnings;                               // anything suspicious\n```\n\n**From the editor's types (recommended).** The npm package `bloxd-types`\nmirrors the declarations built into the Bloxd code editor (checked line by\nline against the live editor on 25 Sep 2026: identical apart from a few\n`//@ts-ignore` comments). With Node installed:\n\n```\nnpm pack bloxd-types            # downloads bloxd-types-<version>.tgz\ntar xzf bloxd-types-*.tgz       # unpacks to package/\npython3 mkmock.py --dts package/types/@bloxd/index.d.ts package/types/@bloxd/globals.d.ts\n```\n\nIf the package ever falls behind, you can pull the same files out of the\neditor: open World Code, press F12, go to **Sources**, press Ctrl+Shift+F and\nsearch for `interface GameApi`. The matching script holds the declarations as\na block of text.\n\n**From the docs text (fallback).** Copy the API Reference and Callbacks pages\nfrom bloxd.io/docs into text files (select all, paste into a `.txt`), then:\n\n```\npython3 mkmock.py API_Reference.txt Callbacks.txt\n```\n\nThis works, but the docs text doesn't say which arguments are optional, so the \"missing required argument\" check is switched off.\n\nEither way, if far fewer entries than expected turn up (under 200 functions or 70\ncallbacks), `mkmock.py` prints a warning and does **not** overwrite `bloxd_api.json`,\nsince that usually means a cut-off paste or a changed layout. Pass `--force` to write it anyway.\n\n- **Single-file world code only.** Files using`import` /`export` aren't supported yet.\n- **Most callbacks only run if you ask.** Join, tick, chat and leave fire\nautomatically; anything else needs`--fire NAME` , and gets placeholder\narguments (player`p1` , coordinates 0, block`\"Stone\"` , shop keys`\"mock_category\"` /`\"mock_item\"` , and a sensible value for other string or\nnumber types).\n- **Placeholders aren't real game state.** Functions without built-in behaviour\nreturn a placeholder, so code that depends on, say, real mob positions won't\nbehave as it would in a world. Use`overrides` to fake what you need.\n- **Only as good as the docs plus the quirks list.** Where the docs are wrong and\nnobody has probed it yet, the mock is wrong too. Test in-engine before shipping.\n\n- Use the full types for basic type checks (a number passed where an item name belongs, a string where coordinates belong).\n- Print where the docs and the editor's types disagree, as a doc-bug report.\n- Support multi-file world code.\n- Grow `quirks.mjs` as more engine behaviour gets confirmed, and re-run`quirk_probe_1.js` after each Bloxd update.", "url": "https://wpnews.pro/news/bloxd-mock-api-run-bloxd-world-code-outside-bloxd", "canonical_source": "https://gist.github.com/Oreo-belt25/f48cbe09cb9e4b45dd58282fcf433828", "published_at": "2026-09-26 01:45:35+00:00", "updated_at": "2026-09-29 20:19:22.437405+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Bloxd", "Oreo_belt25", "Claude", "Node.js", "Python", "bloxd-types"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/bloxd-mock-api-run-bloxd-world-code-outside-bloxd", "markdown": "https://wpnews.pro/news/bloxd-mock-api-run-bloxd-world-code-outside-bloxd.md", "text": "https://wpnews.pro/news/bloxd-mock-api-run-bloxd-world-code-outside-bloxd.txt", "jsonld": "https://wpnews.pro/news/bloxd-mock-api-run-bloxd-world-code-outside-bloxd.jsonld"}}