Separate map projects and add reusable island and operator camera tools

This commit is contained in:
Emil
2026-09-13 20:43:42 +03:00
parent 89c53d7058
commit 224b29f0e7
158 changed files with 633 additions and 34966 deletions
+12 -18
View File
@@ -2,9 +2,9 @@
A Minecraft building editor for collaboration between a human and an AI agent.
![Daylight screenshot of the Gothic hall built and inspected in Minecraft](docs/builds/gothic-hall-polished-day.png)
![Example building constructed and inspected in Minecraft](docs/images/build-demo.png)
An unedited in-game capture of our Gothic hall: 30,125 blocks and 53 lanterns. See the [build report](docs/builds/GOTHIC_HALL.md) for the reference, checked incremental edits, and dusk and interior photos.
An unedited in-game example created through checked incremental building and camera inspection. Map-specific designs, generators and progress reports belong in separate map projects.
Working prototype: a Paper plugin, an editing core, an MCP/ACP Bridge, and a Fabric camera mod. Building, conflicts, undo, crash recovery, and `.schem` have been tested against local Paper through HTTP and real MCP stdio. The camera has been tested in Prism with one client: a real 1280×720 PNG was delivered through MCP. Dedicated ChatGPT sign-in, in-game text replies, and a real one-block build → inspect → undo cycle through ACP have also been verified.
@@ -17,7 +17,7 @@ Working prototype: a Paper plugin, an editing core, an MCP/ACP Bridge, and a Fab
- Provides 19 MCP tools and `/ai` game chat through a pinned `codex-acp` adapter.
- Discovers the running server's complete vanilla block and item catalog on demand; ordinary recipes accept every registered block type and its valid states.
- Captures real images through a local worker on a spectator client. A single client with the owner temporarily in spectator has also been tested.
- Exports real north-up world surface maps without a player through the optional terrain plugin; applies reversible, terrain-following site layouts with checked snapshots.
- Previews deterministic terrain recipes and prepares relative terrain brushes through the same checked apply and undo workflow.
The current scope is one owner, one project, and one world, with at most 4096 blocks per plan and loaded chunks only. A complete delta history, automatic merging of manual edits, and the full design document are not implemented yet. [Detailed status and limitations](docs/IMPLEMENTATION.md).
@@ -25,14 +25,6 @@ Material discovery stays compact: `project_context` returns catalog counts and a
Block support does not replace placement design: doors, beds and tall plants need all their parts, attachments need support, and decorative leaves should normally use `persistent=true`. Terrain brushes still reject fluids and structures in their scan. The `.schem` codec accepts registered block states but rejects entity/block-entity payloads and refuses to export block entities. World checkpoints remain necessary for complete landscaped builds and their extra data.
## Shacraft lobby construction
The clock station in zone 02 now contains a furnished vestibule, a SMASH selection floor and a two-stop lift, with unfinished upper spaces closed. See the [station photographs and verification](docs/SHACRAFT-STATION.md). For future work, use the [decoration playbook](docs/DECORATION-PLAYBOOK.md), [14 practical recipes](docs/DECORATION-RECIPES.md) and [structured recipe catalog](docs/recipes/decorations.json).
The arrival square is finished with the real Shacraft emblem, hexagonal paving, evergreen flower beds, benches, copper-hood lanterns, stone urns and a welcome board. A cream-capped balustrade frames the square. An independently reversible invisible enclosure currently keeps normal players inside zone 01, including at its five road approaches and above the square; the configured lobby spawn remains inside. The station foundation, local roads and broad stairs are ready; other districts remain marked reservations. [Completed zone 01 and containment verification](docs/SHACRAFT-ZONE01-COMPLETE.md) · [Balustrade](docs/SHACRAFT-BALUSTRADE.md) · [Arrival garden](docs/SHACRAFT-ARRIVAL-GARDEN.md) · [Foundations and elevations](docs/SHACRAFT-FOUNDATIONS.md) · [Earlier site survey](docs/SHACRAFT-LOBBY-LAYOUT.md).
![Completed Shacraft arrival square, real Minecraft capture](docs/references/shacraft-zone01-overview.png)
## Build
Verified environment: Linux x64, Minecraft/Paper 26.2, Java 25, and Node.js 22.22.3+. From the repository root:
@@ -48,7 +40,6 @@ Build outputs:
- `paper-plugin/target/paper-plugin-0.1.0-SNAPSHOT.jar` — server plugin, including the editing core.
- `camera-mod/build/libs/minecraft-builder-camera-0.1.0-SNAPSHOT.jar` — client mod.
- `bridge/dist/` — executable MCP/ACP components.
- `terrain-world-plugin/target/terrain-world-plugin-0.1.0-SNAPSHOT.jar` — optional separate-world generator and read-only surface map exporter.
## Local setup
@@ -58,7 +49,7 @@ Build outputs:
python3 scripts/dev-server.py --accept-eula --run
```
For subsequent runs, use `python3 scripts/dev-server.py --run`. The server lives in `.runtime/server`, listens on `127.0.0.1:25575`, and keeps Minecraft authentication enabled. The user has accepted the EULA for the server already prepared in this workspace.
For subsequent runs, use `python3 scripts/dev-server.py --run`. The server lives in `.runtime/server`, listens on `127.0.0.1:25575`, and keeps Minecraft authentication enabled.
2. Connect a Minecraft Java 26.2 client to `127.0.0.1:25575`. In **that server's** console, grant your game account operator access with `op <name>`. In the game, run:
@@ -89,12 +80,16 @@ Build outputs:
Connect MCP to an external client using `python3 scripts/bridge.py mcp`. Owner scope comes from the Paper configuration. This command is intended for a client that launches MCP over stdio, rather than an interactive terminal.
For an external map project, set `MCB_RUNTIME_DIR=/path/to/map/.runtime` when launching the server, bridge, terrain, layout, survey and camera helpers. Their runtime defaults then use that directory; source code and build outputs stay in this checkout. Without the override, standalone setup still uses this repository's `.runtime`. Keep private runtime directories and any local compatibility symlinks out of Git.
## Camera
An ordinary player does not need the mod. For the observer, install the pinned Fabric Loader and API versions and add the camera JAR to a separate 26.2 profile. Before launching, pass `MCB_CAMERA_TOKEN` from the plugin's private `camera-token` setting to that process; set `camera-player-uuid` in Paper and restart the server. The observer must connect in spectator mode.
If the builder and observer play simultaneously, they need valid separate game sessions. With one client, set the camera UUID to the owner's UUID and temporarily enable spectator mode. This scenario has been verified in the Prism profile **26.2 MCP Building**; `scripts/camera-wrapper.py` passes the secret to Java without adding it to Prism's logged variables. See the [camera instructions](camera-mod/README.md) for the exact procedure and capture limitations. Once connected, `/ai camera save name` saves the owner's viewpoint. [Local single-client test results](docs/ONE_CLIENT_TEST.md).
For operator inspections of another world on the server, [camera-capture.py](scripts/camera-capture.py) captures an observer already positioned by the operator. It talks only to the authenticated loopback worker and does not teleport, edit blocks, or change the editor's authorized world. The ordinary MCP camera route retains its project checks.
## Tests and documentation
```bash
@@ -105,10 +100,12 @@ JAVA_HOME="$HOME/.cache/minecraft-builder-mcp/jdk-25.0.2" camera-mod/gradlew --p
`python3 scripts/live-server-test.py` starts and stops its own process in `.runtime/server`, checks conflicts and undo, deliberately terminates that process to test recovery, and then exercises MCP and `.schem`. First build the project, run the plugin once, and accept the EULA; any existing server must be stopped. This test targets the prepared test world and changes only bounded test regions. Results are saved in `.runtime/live-server-results.json` and `.runtime/live-mcp-results.log`.
This disposable-server test keeps its repository-local paths and does not follow `MCB_RUNTIME_DIR`. Run it only in a checkout whose `.runtime/server` is a disposable test server, not a compatibility symlink to a map's retained world.
- [Project design and future phases](docs/DESIGN.md).
- [Implementation status and verification](docs/IMPLEMENTATION.md).
- [Runtime materials and compact discovery](docs/MATERIALS.md).
- [Gothic hall from a reference: 30,125 blocks in the live world](docs/builds/GOTHIC_HALL.md).
- [Decoration workflow and placement checks](docs/DECORATION.md).
- [Protocol](docs/PROTOCOL.md), [editing core and journal](world-core/README.md).
- [Bridge, sign-in, and ACP limitations](bridge/README.md).
@@ -118,10 +115,7 @@ Git is initialized on branch `main`. Generated worlds, secrets, dependencies, an
Deterministic terrain recipes now support hills, ridges, plateaus, dry basins/channels and terraces. `terrain_preview` returns a native heightmap and cached recipe ID; `terrain_prepare` creates a checked tile plan for the existing apply/undo pipeline. Offline previews and bounded resumable batches are available through `scripts/terrain.py`. See [Terraforming tools](docs/TERRAFORMING.md) for examples, safety semantics and scale limits.
For a fresh map, the optional [initial terrain world plugin](terrain-world-plugin/README.md) generates a separate world directly from a recipe, with optional lakes and rivers at a configured water level. The [Shacraft lobby recipe](examples/terrain/shacraft-lobby-world.json) lays out a 768×768 mountain basin with building platforms. Initial generation has its own immutable manifest; subsequent construction uses the normal scoped editor.
`terrain_brush_prepare` additionally edits existing terrain relatively: raise/lower, flatten and snapshot-based smoothing, with soft edges, preserved columns, native before/after previews and checked read dependencies. See the relative-brush section of the terraforming guide.
The natural Shacraft v2 world replaces rectangular terrain platforms with a warped ridged mountain basin, soft hills and connected water courses. The live generation pass checked every column, including surface materials and water fill.
![Shacraft natural v2 terrain, real in-game capture](docs/references/shacraft-natural-v2-overview.png)
World-generation profiles, map geometry, custom gameplay plugins and construction archives are external project resources. They are not installed by the MCP build or exposed as implicit MCP tools.
+1 -1
View File
@@ -105,6 +105,6 @@ Deterministic terrain recipes now support hills, ridges, plateaus, dry basins/ch
## Shared building guidance
`src/building-guidance.ts` is the shared source for material discovery, terrain art direction and decoration used by MCP server instructions and the ACP agent. It prioritizes focused material searches and reuse of defaults, deliberate silhouettes, calm walking areas, localized mountain detail, organic foundations, slope-aware materials, preservation and real camera verification. Tool descriptions state the exact schema boundaries: the current MCP terrain recipe offers amplitude/scale value noise and a limited palette; the advanced `shacraft-natural-v1` profile and initial water generation are operator-configured features. Ordinary building plans can place registered fluid states; terrain brushes still cannot scan through water.
`src/building-guidance.ts` is the shared source for material discovery, terrain art direction and decoration used by MCP server instructions and the ACP agent. It prioritizes focused material searches and reuse of defaults, deliberate silhouettes, calm walking areas, localized mountain detail, organic foundations, slope-aware materials, preservation and real camera verification. Tool descriptions state the exact schema boundaries: the current MCP terrain recipe offers amplitude/scale value noise and a limited palette; advanced noise and initial-world generation require a separately supplied external generator and are not assumed to be installed or available as MCP tools. Ordinary building plans can place registered fluid states; terrain brushes still cannot scan through water.
ACP stores a fingerprint of successfully delivered instructions with its session state. An older or missing fingerprint causes the updated guidance to be sent on the next prompt in a resumed session, preserving history. Once delivered, unchanged guidance is not repeated on every turn or restart. Transport failures leave the old fingerprint so delivery can be retried.
+2 -2
View File
@@ -2,10 +2,10 @@
export const MATERIAL_GUIDANCE = `Material discovery: project_context contains only a catalog summary. All vanilla block states registered by the running server are available to ordinary build recipes, including water; item-only materials can be discovered but cannot be placed as blocks. Use material_search with a focused query, then material_describe for 1–3 chosen materials to obtain exact default states and allowed property values. Reuse those results while the catalog version is unchanged; do not enumerate the registry or repeatedly describe known materials. Omitted properties use server defaults. Block states do not accept raw NBT or configure inventories/sign text; same-material edits preserve existing block-entity data. Pass through region_inspect snapshot_id hashes in expected_blocks to detect changes to that data. Terrain recipes and brushes retain their separate limited palettes and fluid restrictions.`;
export const TERRAIN_GUIDANCE = `Terrain art direction: compose a readable skyline and calm playable valleys before adding detail. Prefer broad low-frequency relief, localized ridged mountain detail and modest coordinate warping when the available generator supports them. Independent seeded noise layers reduce repetition; more octaves alone do not fix bad composition. Keep fine detail weak along walking routes. Preserve sightlines, water courses and space for architecture. Avoid large rectangular plateaus unless explicitly requested: adapt buildings to the landscape and flatten only their actual foundations with wide, irregular transitions. Preserve existing terrain instead of repeatedly flattening whole districts. Use rock on steep slopes and soil/grass on gentle ground; avoid grass-and-dirt contour stripes across cliffs. Grade routes and entrances separately; natural-looking terrain is not automatically walkable.
Capability boundary: MCP terrain recipes currently expose three-octave value noise through amplitude/scale only. OpenSimplex2S, ridged noise and domain warping are available in the separately configured shacraft-natural-v1 initial-world profile, NOT as terrain_preview parameters or callable MCP tools. Do not invent noise, spline, erosion, biome or fluid APIs. MCP terrain tools do not place water; the initial-world generator can fill lakes/rivers at a configured level. Brushes reject water in their scan. Preserve waterways and their beds; request operator-side generation work if the task requires unsupported capabilities. There is no hydraulic erosion simulation or initial-generation block undo.
Capability boundary: MCP terrain recipes currently expose three-octave value noise through amplitude/scale only. Advanced noise families, domain warping and initial-world generation require a separately supplied external generator, NOT as terrain_preview parameters or callable MCP tools. Do not assume any map profile or external generator is installed. Do not invent noise, spline, erosion, biome or fluid APIs. MCP terrain tools do not place water; ordinary building plans can place registered fluid block states. External generators may have different capabilities that require separate verification. Brushes reject water in their scan. Preserve waterways and their beds; request operator-side generation work if the task requires unsupported capabilities. The MCP terrain tools provide no hydraulic erosion simulation or undo for external world generation.
Workflow: inspect a small relevant region, preserve structures and their foundations, preview composition, then apply bounded checked plans. A target heightmap is not a Minecraft screenshot. Inspect terrain from an overview and a player-height view when the camera is available; check silhouettes, chunk seams, shores, materials and route slopes. Poll pending captures by capture_id until completed or a reported error; report that error rather than claiming visual verification. On a shared camera client, ask the player to close menus and stay still. Distinguish proposed, prepared, server-applied and visually inspected work. Keep summaries compact; reuse terrain_id and operation IDs instead of dumping blocks or regenerating equivalent recipes.`;
export const DECORATION_GUIDANCE = `Decoration art direction: Establish purpose and silhouette before adding detail. Use a coherent palette, grouped texture variation and structural depth; avoid random high-contrast block noise. Preserve quiet surfaces, walking clearance, entrances and important sightlines. Build one small prototype, inspect it, then repeat its motifs with controlled variation. Discover selected materials and exact block states through material_search and material_describe. Verify orientation, attachment, support and stable leaves; decorative partial blocks do not guarantee containment. Keep unfinished rooms closed. Inspect actual captures from player height and an overview, in daylight and at night when available; state which views or lighting conditions remain unverified. Confirm server-applied changes before reporting completion. Documented decoration recipes are design specifications, not callable tools; translate selected details into supported bounded plans and preserve manual edits.`;
export const DECORATION_GUIDANCE = `Decoration art direction: Establish purpose and silhouette before adding detail. Use a coherent palette, grouped texture variation and structural depth; avoid random high-contrast block noise. Preserve quiet surfaces, walking clearance, entrances and important sightlines. Build one small prototype, inspect it, then repeat its motifs with controlled variation. Discover selected materials and exact block states through material_search and material_describe. Verify orientation, attachment, support and stable leaves; decorative partial blocks do not guarantee containment. For open trapdoors, derive facing from the physical edge touching the support: the panel occupies the edge opposite facing. Verify one side view before repeating it; do not invert horizontal lids or already correct facade panels. Keep unfinished rooms closed. Inspect actual captures from player height and an overview, in daylight and at night when available; state which views or lighting conditions remain unverified. Confirm server-applied changes before reporting completion. Documented decoration recipes are design specifications, not callable tools; translate selected details into supported bounded plans and preserve manual edits.`;
export const AGENT_BASE = `You are the Minecraft builder for the current authorized project. Respond in the player's language using short game-chat messages. Use only minecraft-builder-mcp to inspect and edit the world. Begin each new task with project_context; read relevant world data before designing. Only implemented server capabilities may be used. Prepare compact geometry, inspect statistics, apply using stable idempotency keys, and poll operation_status. Preserve manual edits: conflict requires localized redesign or the user's decision, never blindly overwrite fresh snapshots. A cancelled or failed operation may have partial writes. Camera requests are asynchronous; poll capture_id and inspect actual image. If unavailable, explicitly say visually unverified. Never use console commands, shell, files, or other MCP servers to modify Minecraft. Do not claim any action completed without server evidence.`;
+3 -1
View File
@@ -28,7 +28,9 @@ test('updated terrain and material guidance reaches resumed ACP sessions once wi
session=new CodexSession({projectId:'p',playerId:'u'},options);
await session.prompt('same guidance after restart',async()=>{});
const calls=await records();const prompts=calls.filter(v=>v.method==='session/prompt').map(v=>v.params.prompt[0].text);
assert.ok(prompts[1].includes('shacraft-natural-v1'));
assert.ok(prompts[1].includes('separately supplied external generator'));
assert.ok(!prompts[1].includes('shacraft'));
assert.ok(prompts[1].includes('panel occupies the edge opposite facing'));
assert.ok(prompts[1].includes('Avoid large rectangular plateaus'));
assert.ok(prompts[1].includes('NOT as terrain_preview parameters'));
for(const prompt of [prompts[0],prompts[1]]) {
+14
View File
@@ -47,6 +47,20 @@ python3 scripts/live-camera-test.py --camera-id test --delay 8
Before capture begins, return to Minecraft, close chat and menus, stop moving, and keep the mouse still. Rotation tolerance is only 0.1°, so even slight movement cancels the image. Switching windows may open the pause menu. In this mode, capture temporarily uses your game view; the server teleport changes your position. Your game mode and previous position are not restored automatically. Choose the desired mode and location manually when returning to building.
### Operator capture of an already positioned observer
[scripts/camera-capture.py](../scripts/camera-capture.py) can inspect a separate world after an authorized operator has placed the spectator there. This local CLI is not an additional MCP tool: it neither teleports nor edits the world, and does not change Paper's active editor project. Use the actual client dimension key and observer feet position:
```bash
MCB_RUNTIME_DIR=/path/to/map/.runtime python3 scripts/camera-capture.py \
--dimension minecraft:overworld --pose 16.5 90 16.5 45 25 --fov 80 \
--out /path/to/map/.runtime/captures/overview.png
```
The default private config is `MCB_RUNTIME_DIR/server/plugins/MinecraftBuilderMCP/config.yml`, falling back to this checkout's `.runtime/server`. `MCB_CAMERA_PAPER_CONFIG` overrides that default; `--config` overrides both. The helper disables proxies and redirects, authenticates to `127.0.0.1`, bounds responses, correlates the capture UUID/dimension/timestamp, and checks the PNG and its dimensions. It writes unchanged PNG bytes and an allowlisted `.capture.json` receipt with a SHA-256. It does not certify a server revision or restore the operator's previous viewpoint. Existing output files at the selected paths are replaced. The normal readiness and spectator requirements still apply.
When positioning through the vanilla console, write explicit decimal X/Z coordinates, such as `16.0`, when the capture requests exactly `16.0`. Integer X/Z arguments to `/teleport` select block centres and can become `16.5`. That half-block offset exceeds the camera's position tolerance and causes a timeout. Use the same feet position, dimension and rotation in the teleport and capture request. A completed real-world smoke capture verified this operator path on Paper 26.2; it remains separate from the MCP project's scoped camera route.
## Protocol
All requests, including health checks and image retrieval, require `Authorization: Bearer <MCB_CAMERA_TOKEN>`. JSON is not written to the log.
-115
View File
@@ -1,115 +0,0 @@
# Minecraft decoration playbook
Research reviewed **13 September 2026** for the Shacraft lobby. These notes combine primary Minecraft articles, interviews with builders and official Java release notes with our own measured-building workflow. They record reusable design knowledge; this research stage makes no changes to the world.
Start with this page, then open only the relevant entry in the [14-recipe cookbook](DECORATION-RECIPES.md). The [structured catalog](recipes/decorations.json) is the authoritative source for recipe dimensions, materials, assembly and acceptance checks. Recipes are original design proposals, not copied tutorial schematics, executable `build_prepare` payloads or claims of completed construction.
## Short working memory
1. Give the place a purpose and identify the main arrival, decision point and place to pause.
2. Resolve silhouette, structural rhythm and major material fields before surface details.
3. Assign each material a role. Keep a dominant family, supporting material and selective accent.
4. Make depth with real layers: a recessed window, a projecting sill, a supported eave. Keep the closure behind decorative partial blocks intact.
5. Cluster texture changes where wear, moisture, construction or planting explains them. Preserve calm surfaces between accents.
6. Arrange furniture as useful groups. Keep entrances, lift controls and destination signs visible.
7. Measure the actual ground, floor and route before placing a standard module. Preserve established widths and headroom.
8. Check material availability, exact states, rotation, attachment, substrate and stability after updates.
9. Build one sample, inspect it at player height and from the approach, then repeat with controlled variation.
10. Compare real day/night photographs and inspect concealed sides. A map, plan or successful placement receipt is not a lighting review.
11. Keep unfinished rooms closed. Decoration must not create a passage or a way around an existing enclosure.
12. Save recipe IDs, anchors, rotations, seeds, operation receipts and selected photographs; load only the local context needed for the next edit.
These are project working rules. Numeric dimensions below are starting proposals for this lobby, not universal Minecraft laws.
## What the research changes in our practice
### Shape and depth before micro-detail
Aegos and Shannooty describe working out roofs and the overall silhouette before detailing. Milosz explains using a consistent palette and comparatively simple textures at large scale. For Shacraft, the clock tower should remain the first readable feature; a dormer, finial or cornice is useful only if it strengthens that composition. Review a proposed feature from the main approach before copying it around the roof. [Tranquil Towers](https://www.minecraft.net/en-us/article/tranquil-towers), [The Sky is No Limit](https://www.minecraft.net/en-us/article/sky-no-limit).
The glass-pane article explicitly connects windows with variation in wall depth. Our adaptation uses a recessed **full-glass closure** and a projecting stone surround, since public containment is part of this project. Thin panes can be useful elsewhere, but their appearance does not prove a sealed boundary. Quartz also provides a consistent family for architecture and small furnishings. [Taking Inventory: Glass Pane](https://www.minecraft.net/en-us/article/taking-inventory--glass-pane), [Build With It: Quartz](https://www.minecraft.net/en-us/article/build-with-it--quartz).
### Material variation should explain the surface
Rough diorite and its polished form demonstrate that texture intensity changes the character of a surface; a brighter material is not automatically a quieter one. Mossy cobblestone can suggest age. Our design inference is to place texture by cause: moisture and earth contact at a retaining wall, wear near an approach, clean edges around a maintained station entrance. Use connected patches rather than an independent random material choice for every block. [Build with It: Diorite!](https://www.minecraft.net/en-us/article/build-it--diorite-), [Build With It: Cobblestone!](https://www.minecraft.net/en-us/article/build-with-it--cobblestone-).
A color gradient is optional. If used, it should reinforce a chosen mass or light direction and read at the intended distance. Do not impose an arbitrary weathering percentage or a fixed color-ratio formula on every building. We should compare a small clean sample and a restrained textured sample before committing a facade.
### Interior groups should tell players how to use the room
The builders in *Interior Motives* emphasize purpose and agreement between inside and outside. Jonathan “SnugSites” discusses livable furniture arrangements and the value of two-block partitions when rooms need different finishes on each face. We should build waiting groups, information points and viewing pockets, reserving a clear route between them; an empty section of floor can be necessary circulation. [Interior Motives](https://www.minecraft.net/en-us/article/interior-motives), [Fantastic Furniture](https://www.minecraft.net/en-us/article/fantastic-furniture).
Spruce, plants and lanterns are useful companions to copper and masonry in *Cozy Chambers*. For our station this means warmth at the scale of benches, counters and exhibits, with a limited number of focal groups. A Minecraft article also documents a flowerpot above a decorated pot as a large planter. The original cookbook used a small stone planter; the runtime catalog now makes registered pot block types discoverable, while custom pot decoration and stored-item data remain outside the ordinary state editor. [Cozy Chambers](https://www.minecraft.net/en-us/article/cozy-chambers), [Decorated Pot](https://www.minecraft.net/en-us/article/decorated-pot).
### Decorate the transition between architecture and landscape
The official presentation of BlueNerd's landscaping work connects paths, banks, soil and vegetation. Zaypixel's path examples show how material families and nearby objects communicate different settings. Our application is a clean, formal station axis that gradually gives way to local rock, soil and planted pockets farther out. Curve a route when its destination or terrain calls for it. Do not force a kink every seven blocks: that number belongs to one organic-building tutorial, not the engine or every architectural style. [Landscaping and Terraforming](https://www.minecraft.net/en-us/article/tutorial--tips-for-landscaping-and-terraforming), [Five simple path designs](https://www.minecraft.net/en-us/article/five-simple-path-designs).
Kelpie the Fox's outdoor groups provide useful roles for benches, small structures and hanging lights. The article identifies **Mizuno's 16 Craft** in its reference imagery. Borrow composition and purpose, then judge our result in the actual client textures; matching block names alone cannot reproduce a resource-pack image. [Cottagecore Decor](https://www.minecraft.net/en-us/article/tutorial--cottagecore-decor).
### Lighting requires its own review
Regular lanterns are a useful recurring fixture, but a fixture count does not establish room legibility. Look at the spaces between lights, stair landings, sign faces and exhibit fronts. We already used real station photographs to find dark interiors and refine concealed lighting; see the [completed station record](SHACRAFT-STATION.md). [Taking Inventory: Lantern](https://www.minecraft.net/en-us/article/taking-inventory--lantern).
**Tinted glass is not stained glass:** the Java release notes describe tinted glass as blocking light. Do not use it as a substitute for a transparent lighting lens. The same release notes document waxed copper as preventing oxidation. These facts explain material choices; exact accepted states still come from our current server. [Java Caves & Cliffs Part I](https://www.minecraft.net/en-us/article/caves---cliffs--part-i-out-today-java).
## Shacraft palette and composition
The following assignments are our design direction based on the existing arrival garden and station, rather than claims made by the sources:
- **Large cream masses:** `smooth_sandstone`, with `cut_sandstone` for purposeful masonry bands.
- **Clean prominent edges:** `smooth_quartz` and `quartz_pillar`; use supported sandstone stairs/slabs when a partial shape is needed.
- **Roofs and identity:** the `waxed_oxidized_cut_copper` family. Keep broad roof planes visible.
- **Human-scale warmth:** spruce for benches, counters, ceilings and small structural posts.
- **Selective emphasis:** gold at a major identity or control point, with green backing. Repeated small gold accents must not compete with the main sign.
- **Grounded base:** stone bricks, andesite and restrained moss near actual soil or damp recesses.
- **Planting:** a dominant evergreen mass and small pink/white flower groups, continuing zone 01's established vocabulary.
- **SMASH:** preserve the station frame; use a contained island exhibit and restrained warm accent to distinguish this floor.
Place more detail at an entrance, destination or stopping point. Leave broader quiet surfaces and uninterrupted paving between those locations. This is a distribution choice, not a ban on ornament.
## Recipe index
Each cookbook entry includes dimensions, palette, assembly order, clearance, controlled variants and failure checks:
- Facade: `arched-window-bay`, `cornice-bracket`.
- Roof: `closed-dormer`.
- Interior: `waiting-pocket`, `information-counter`, `smash-exhibit`.
- Routes: `avenue-edge`, `retaining-stair`.
- Lighting: `copper-lantern`, `concealed-light-lens`.
- Planting and landscape: `layered-planter`, `shore-pocket`.
- Small props and surfaces: `luggage-bench`, `masonry-weathering`.
## Current capability boundary
The saved Stage 07 `project_context` lists **100 material IDs**. All base recipe material lists were checked against that historical snapshot. The structured recipes retain that dated capability basis so earlier designs remain reproducible; it is no longer the building allowlist. The runtime implementation in [`BuildingWorld.java`](../paper-plugin/src/main/java/io/github/minecraftbuilder/paper/BuildingWorld.java) now accepts all registered vanilla block types and their valid states. Read the live catalog summary, then discover only the materials needed for the next detail through `material_search` and `material_describe`. [Material workflow](MATERIALS.md).
The original recipe catalog uses flush colored paving instead of carpet, masonry planters instead of pots, full stained glass instead of panes, and wooden block props instead of item entities. These remain deliberate design variants. Registered carpets, trapdoors, flowerpots, decorated pots, banners, candles, wildflowers, leaf litter and firefly bushes can now be selected through the runtime catalog. Block-type availability does not add arbitrary banner patterns, pot decorations, sign text, inventories or text-display creation; the station's existing labels use a separate project-specific plugin. Item-only materials are searchable but cannot be placed by a block recipe.
Java 1.21.5 introduced useful plant density/orientation options; its firefly bush emits only light level 2, so it should be treated as an atmospheric accent rather than primary street illumination. Java 26.2 also adds sulfur and cinnabar material families. Material IDs and exact properties come from the running server's registry, so search before using a version-specific feature. Additional behavior is not a new callable MCP API. [Java 1.21.5 release notes](https://feedback.minecraft.net/hc/en-us/articles/35298208390797-Minecraft-Java-Edition-1-21-5-Spring-to-Life), [Java 26.2 release notes](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-2).
For this runtime, discover the chain ID rather than assuming an older name; the saved station uses `minecraft:iron_chain`. Use `persistent=true` for decorative leaves unless deliberate natural decay is intended, and check distance state on read-back. Flowers need accepted substrates, logs need real support, and stairs/slabs/lanterns need the correct directional and attachment states. Place every half or part of doors, beds and tall plants explicitly. Ordinary building plans can place fluids and waterlogged states, but terrain brushes still reject water in their scan. The existing shore recipe remains a land-side design that preserves water. Fluid flow, random ticks and other later game behavior are not fully reversed by undoing only a plan's direct writes.
## Applying a recipe economically
The Markdown cookbook is for human review; the JSON makes one entry easy to retrieve without reading the entire document. For a local repository agent:
```bash
jq '.recipes[] | {id, category, size}' docs/recipes/decorations.json
jq '.recipes[] | select(.id == "copper-lantern")' docs/recipes/decorations.json
```
Save a placement record with recipe ID, recipe-catalog version and runtime material-catalog version, local origin, rotation, chosen variant, terrain/floor anchor, palette substitutions, variation seed and operation IDs. Use a focused `material_search` page (16 results by default, 32 maximum), then describe only 1–3 selected materials. Reuse their defaults and property domains while the runtime catalog version is unchanged. Inspect the target area and its support/clearance neighborhood, then compile a bounded expected-state patch. Copy each block-entity `snapshot_id` from `region_inspect` into `expected_blocks` to detect data edits without reading inventories or NBT into context. Keep the checked operation receipts and a small set of matching photographs. Large-scale repetition comes after a successful sample.
The shared [MCP/ACP guidance](../bridge/src/building-guidance.ts) includes short material-discovery and decoration summaries. Neither the full recipe catalog nor the material registry is injected into every model turn. The recipe JSON is not a new MCP resource or tool: the in-game ACP agent has no repository filesystem access, so its instructions must not pretend it can retrieve this file. New bridge processes receive the updated summary, and resumed ACP sessions receive changed guidance once through its stored fingerprint. Deployment and validation of the registry expansion are recorded in [MATERIALS.md](MATERIALS.md#validation).
## Acceptance before calling a decoration complete
1. **Fit:** same survey anchors, preserved structure, route width and four-block public headroom where that is the existing Shacraft contract. Four blocks is our design margin, not Minecraft's minimum player height.
2. **Stability:** supports, substrates, leaves, attached pieces and rotated states remain valid after block updates.
3. **Movement:** inspect approaches, corners, stairs and ceilings. A decorative fence or hedge does not replace the checked enclosure. Keep unfinished interiors inaccessible.
4. **Visuals:** matched overview, approach and player-height views; day/night where lighting matters. Check sign visibility, density, material contrast and dark exhibit faces in the actual client.
5. **Evidence:** distinguish proposed design, server-applied blocks, measured geometry and visually inspected results. Record an unavailable camera honestly.
6. **Preservation:** keep the before state, checked edits and useful photographs. A later manual edit is a conflict to resolve, not an invitation to overwrite it.
The 14 catalog entries have been reviewed as design specifications and checked for material-name availability. They have **not** been instantiated or visually approved as a new set of in-world samples.
-512
View File
@@ -1,512 +0,0 @@
# Shacraft decoration recipes
Generated from [decorations.json](recipes/decorations.json), the authoritative catalog. Read the [playbook](DECORATION-PLAYBOOK.md) for principles, current capabilities and the acceptance workflow.
**14 original design proposals, reviewed 13 September 2026.** Material IDs match the saved 100-material Stage 07 palette. These are design references, not executable Minecraft recipes or completed in-world samples. Recheck live capabilities before applying.
Dimensions below are **width × height × depth** in blocks. They exclude separately specified circulation and buried support. Local +X is right, +Y is up, +Z points into the object; the front faces -Z. Measurements and spacing are project proposals, not engine limits.
## arched-window-bay
**Recessed arched window bay** · facade · **7 × 10 × 3 blocks**
Give a large cream facade readable shadow and a consistent structural rhythm.
Materials: `smooth_sandstone`, `cut_sandstone`, `smooth_sandstone_stairs`, `smooth_sandstone_slab`, `smooth_quartz`, `brown_stained_glass`.
Assembly:
1. Reserve a seven-wide bay between the actual structural axes; keep adjacent columns and floor decks intact.
2. At the glazing plane, use five-wide glass rows for the straight portion, then three and one at the crown. Fill every surrounding cell with full masonry so the plane stays sealed.
3. Place glazing one block behind the front wall plane; use the remaining front depth for a sill and paired jamb brackets.
4. Use sandstone stairs only as outer trim. Maintain full masonry or full glass behind partial-block trim.
5. Repeat the approved bay on the established grid; redesign corners and the main doorway deliberately.
**Clearance:** Keep projections outside the existing public route and its four-block headroom; do not narrow the seven-block station entry.
Variants:
- Plain rectangular head on a secondary facade.
- One gold accent above the principal entrance only.
Acceptance:
- Closure plane has no unfilled cells, including arch shoulders.
- Recess reads from a diagonal player-height camera.
- No sill hides a sign or clips furniture.
- Stair rotation and corner shape checked after neighboring blocks update.
Avoid:
- Different window silhouettes in every bay.
- Assuming a pane or stair is a full containment wall.
Conceptual sources: [The Sky is No Limit](https://www.minecraft.net/en-us/article/sky-no-limit), [Taking Inventory: Glass Pane](https://www.minecraft.net/en-us/article/taking-inventory--glass-pane), [Build With It: Quartz](https://www.minecraft.net/en-us/article/build-with-it--quartz). Recipe geometry and sequence are our own proposal.
## cornice-bracket
**Cornice and paired bracket** · facade · **9 × 3 × 2 blocks**
Explain the floor/eave line without filling the wall with ornament.
Materials: `smooth_sandstone`, `smooth_sandstone_stairs`, `smooth_sandstone_slab`, `smooth_quartz`.
Assembly:
1. Place a continuous stone band on the existing floor or eave line.
2. Use an inverted-stair underside and a thin slab cap, with at most two blocks of total outward depth.
3. Put the two bracket groups over structural supports and leave the central field quiet.
4. Continue the band around corners with an explicitly resolved return; prototype the corner before repeating.
**Clearance:** Remain above route headroom and outside signs' viewing rays; preserve roof drainage shapes and window tops.
Variants:
- Single-block projection on small wings.
- A stronger cap at the tower base, using the same materials.
Acceptance:
- Horizontal band remains readable from the main approach.
- Brackets align with actual supports.
- Cap does not overwhelm the window opening.
Avoid:
- A thick shelf over every horizontal edge.
- Unrelated gold trim on every bracket.
Conceptual sources: [Tranquil Towers](https://www.minecraft.net/en-us/article/tranquil-towers), [The Sky is No Limit](https://www.minecraft.net/en-us/article/sky-no-limit), [Build With It: Quartz](https://www.minecraft.net/en-us/article/build-with-it--quartz). Recipe geometry and sequence are our own proposal.
## closed-dormer
**Closed green-copper dormer** · roof · **7 × 7 × 7 blocks**
Add a secondary roof feature while keeping the clock tower dominant.
Materials: `smooth_sandstone`, `brown_stained_glass`, `waxed_oxidized_cut_copper`, `waxed_oxidized_cut_copper_stairs`, `waxed_oxidized_cut_copper_slab`.
Assembly:
1. Fit a seven-wide sample to the actual roof pitch; use cream side cheeks and three-wide recessed glass.
2. Build the green pitched cap with a one-block overhang.
3. Keep a solid back and floor closure behind the apparent window; retain the existing public ceiling.
4. Test one dormer from the main approach before any repetition. Consider 14-18 blocks between centers only where the measured structural grid permits it.
**Clearance:** No opening into an unfinished attic, no overlap with tower faces or main roof ridge.
Variants:
- One larger central feature on a secondary wing.
- Omit the dormer if it competes with the clock silhouette.
Acceptance:
- Tower remains the primary skyline feature.
- Quiet copper roof planes remain visible between details.
- Full closure survives the added roof cutout.
Avoid:
- Treating proposed spacing as a universal rule.
- Adding attic access as part of a cosmetic edit.
Conceptual sources: [Tranquil Towers](https://www.minecraft.net/en-us/article/tranquil-towers), [The Sky is No Limit](https://www.minecraft.net/en-us/article/sky-no-limit). Recipe geometry and sequence are our own proposal.
## waiting-pocket
**Paired waiting benches** · interior · **9 × 4 × 7 blocks**
Create a believable place to wait beside the main hall.
Materials: `spruce_stairs`, `spruce_slab`, `spruce_planks`, `smooth_sandstone`, `green_concrete`, `lantern`, `oak_leaves`, `dirt`.
Assembly:
1. Place two three-seat spruce benches facing a shared open pocket, with cream end supports.
2. Keep a compact table at one side rather than on the main desire line.
3. Use a flush green paving inset to group the furniture; this substitutes for unsupported carpet.
4. Add one planter and one supported lantern near the back, leaving the front visually open.
**Clearance:** Reserve an additional three-block-wide clear passing strip and four blocks of route headroom. Existing wider routes retain their width.
Variants:
- Single bench and planter in a smaller side recess.
- Mirror the group around the room axis while varying the small prop.
Acceptance:
- Lift sign remains visible from the approach.
- Seat fronts and table can be approached without stepping onto furniture.
- Lamp and leaves remain stable after updates.
Avoid:
- Rows of isolated decorative chairs.
- Plants in front of navigation signs.
Conceptual sources: [Interior Motives](https://www.minecraft.net/en-us/article/interior-motives), [Fantastic Furniture](https://www.minecraft.net/en-us/article/fantastic-furniture), [Cozy Chambers](https://www.minecraft.net/en-us/article/cozy-chambers). Recipe geometry and sequence are our own proposal.
## information-counter
**Information counter** · interior · **9 × 5 × 4 blocks**
Provide a clear information point that belongs in a station.
Materials: `spruce_planks`, `spruce_slab`, `smooth_sandstone`, `smooth_sandstone_slab`, `green_concrete`, `glowstone`, `brown_stained_glass`.
Assembly:
1. Frame a seven-block counter between cream end piers; use spruce body and a thin cream slab top.
2. Align one green sign backing and one lit recess behind the counter.
3. Keep the back wall solid. Any future staff door remains a finished wall panel until the room exists.
4. Add actual text only through an existing authorized label mechanism; the block catalog does not create text entities.
**Clearance:** Reserve three clear queue blocks in front, separated from the entrance-to-lift route and its full width.
Variants:
- Short five-wide counter for a side room.
- A small gold emblem only above the principal information point.
Acceptance:
- Queue does not cross the main route.
- Counter is recognizable before reading the sign.
- No false usable door into unfinished space.
Avoid:
- Several equally bright competing headers.
- Claiming matchmaking or staff interaction exists merely because the counter is built.
Conceptual sources: [Interior Motives](https://www.minecraft.net/en-us/article/interior-motives), [Build With It: Quartz](https://www.minecraft.net/en-us/article/build-with-it--quartz), [Fantastic Furniture](https://www.minecraft.net/en-us/article/fantastic-furniture). Recipe geometry and sequence are our own proposal.
## smash-exhibit
**SMASH exhibit niche** · interior · **7 × 6 × 5 blocks**
Communicate floating islands and knockback through one readable display.
Materials: `deepslate`, `smooth_sandstone`, `green_concrete`, `gold_block`, `grass_block`, `dirt`, `glowstone`, `brown_stained_glass`.
Assembly:
1. Build a full dark base, full back and light stone frame around a five-wide exhibit.
2. Choose one miniature island or one abstract impact motif as the subject.
3. Put one small gold focal detail near the subject and keep the rest of the frame consistent with adjacent niches.
4. Light the subject from concealed side, base or overhead recesses; preserve full-block base and closure.
5. Use one shared frame for all six future arena places; vary the subject and real destination text only when available.
**Clearance:** Reserve a three-block viewing strip outside the main circulation aisle; preserve the existing selection aisle.
Variants:
- Closed trophy pedestal with a single object.
- Small landscape model for a future named arena.
Acceptance:
- Subject is legible from player eye level without entering the display.
- No dark face hides the model's silhouette.
- Placeholders clearly remain unassigned.
Avoid:
- Six unrelated palettes.
- A visual void that is also an accidental physical hole.
Conceptual sources: [Interior Motives](https://www.minecraft.net/en-us/article/interior-motives), [Fantastic Furniture](https://www.minecraft.net/en-us/article/fantastic-furniture), [Cozy Chambers](https://www.minecraft.net/en-us/article/cozy-chambers). Recipe geometry and sequence are our own proposal.
## avenue-edge
**Formal avenue edge** · path · **9 × 1 × 12 blocks**
Connect station stonework to the garden through a continuous legible route.
Materials: `stone_bricks`, `smooth_stone`, `smooth_sandstone`, `mossy_stone_bricks`.
Assembly:
1. Keep seven center columns as continuous clear paving and one flush border column on each side.
2. Survey elevations along the whole segment before decoration; grade transitions as separate geometry.
3. Place furniture in additional two-to-three-block shoulders or wider pockets, not inside the nine-block strip.
4. Keep the station approach clean. Introduce small connected worn patches at outer edges beside planting.
5. Widen at entrances and follow actual destinations rather than adding arbitrary bends.
**Clearance:** Seven-block clear walking width and four-block headroom; this example must not narrow a wider established route.
Variants:
- Use local gray stone farther from the station.
- Curve the outer border while keeping the tread continuous.
Acceptance:
- Entire route walkable at all grade changes.
- Flush borders do not introduce a lip.
- No lamp or planter creates a pinch point.
Avoid:
- Uniform random scatter of five paving materials.
- Applying an organic-path zigzag rule to a formal station axis.
Conceptual sources: [Tutorial: Tips For Landscaping and Terraforming](https://www.minecraft.net/en-us/article/tutorial--tips-for-landscaping-and-terraforming), [Five simple path designs](https://www.minecraft.net/en-us/article/five-simple-path-designs), [Build With It: Cobblestone!](https://www.minecraft.net/en-us/article/build-with-it--cobblestone-). Recipe geometry and sequence are our own proposal.
## copper-lantern
**Supported copper-arm lantern** · lighting · **3 × 7 × 1 blocks**
Establish one recognizable outdoor fixture family.
Materials: `stone_bricks`, `stripped_spruce_log`, `waxed_oxidized_cut_copper`, `iron_chain`, `lantern`.
Assembly:
1. With the sample's first above-ground cell at y=0, place a full stone foot at (0,0,0), rooted into surveyed ground below.
2. Raise a post at x=0,z=0 through y=1..5; place a full-block copper arm across x=0..2 at y=6.
3. Place a vertical iron chain at (2,5,0) attached beneath the full arm, then a hanging lantern at (2,4,0).
4. Place support before attached details and inspect resulting block states.
5. Keep the entire post outside the clear path; use a mirrored pair only at a major entry.
**Clearance:** Four empty cells below the hanging lantern if ground is level with the sample. Recalculate for actual terrain; do not assume the same clearance over a rising stair.
Variants:
- Shorter ground-mounted fixture in a planted pocket with no walk-under route.
- One gold marker at a major junction, outside this base recipe.
Acceptance:
- Full arm, chain axis and hanging lantern state remain valid after updates.
- Night view shows the next step, intersection and sign between lamps.
- Post cannot be used to bypass an existing containment boundary.
Avoid:
- Unsupported lanterns.
- Treating a fixed lamp spacing as guaranteed illumination coverage.
Conceptual sources: [Tutorial: Cottagecore Decor](https://www.minecraft.net/en-us/article/tutorial--cottagecore-decor), [Taking Inventory: Lantern](https://www.minecraft.net/en-us/article/taking-inventory--lantern), [Caves & Cliffs: Part I out today on Java](https://www.minecraft.net/en-us/article/caves---cliffs--part-i-out-today-java). Recipe geometry and sequence are our own proposal.
## layered-planter
**Layered planting pocket** · planting · **7 × 6 × 5 blocks**
Produce a planted mass with a readable front, middle and background.
Materials: `dirt`, `grass_block`, `spruce_log`, `spruce_leaves`, `oak_leaves`, `white_tulip`, `pink_tulip`, `oxeye_daisy`, `smooth_sandstone`.
Assembly:
1. Shape a low cream rim with solid soil behind it; support the entire pocket down to the existing terrain.
2. Put one small rooted tree toward the rear and two unequal shrub groups below it.
3. Use one dominant foliage species and two restrained flower colors near the front.
4. Leave patches of visible grass between groups; taper density toward the edge.
5. Save a seed and cluster anchors for repeatable variation; change group positions rather than every block independently.
**Clearance:** Keep the highest mass outside entrance and sign sightlines; no leaves overhang the protected walking clearance.
Variants:
- Formal clipped evergreen beside the station.
- Looser shrubs without a tree beside the mountain path.
Acceptance:
- Flowers have valid soil.
- Leaves use persistent=true and a stable read-back distance state.
- Trunk has stable soil under it.
- Foliage tint checked in the actual biome.
Avoid:
- A flower on every grass block.
- Using leaves as the only containment boundary.
Conceptual sources: [Cozy Chambers](https://www.minecraft.net/en-us/article/cozy-chambers), [Tutorial: Tips For Landscaping and Terraforming](https://www.minecraft.net/en-us/article/tutorial--tips-for-landscaping-and-terraforming), [Tutorial: Cottagecore Decor](https://www.minecraft.net/en-us/article/tutorial--cottagecore-decor). Recipe geometry and sequence are our own proposal.
## shore-pocket
**Quiet shore with a stony recess** · landscape · **12 × 4 × 8 blocks**
Connect existing water and terrain with a believable local bank.
Materials: `stone`, `andesite`, `cobblestone`, `mossy_cobblestone`, `dirt`, `grass_block`, `oak_leaves`.
Assembly:
1. Sample a short existing shoreline together with its water level and submerged bed.
2. Shape one quiet bank and one small stony recess; maintain continuous ground beneath the visible soil skin.
3. Put exposed rock at the outcrop and moss only in selected damp recesses.
4. Keep vegetation in sheltered land pockets and leave a clear view of the water.
5. This catalog specifies only land-side decor. Preserve water cells and the connected bed; stop if execution requires fluid placement or an unsupported brush through water.
**Clearance:** Preserve public route width, foundations, water level and any existing waterfront containment.
Variants:
- Grass bank with one isolated outcrop.
- Stone recess beside a retaining wall, without changing its footing.
Acceptance:
- Water network and visible level preserved.
- No new flow reaches a road or foundation after updates.
- A below-water view shows a continuous bed; top-down appearance alone is insufficient.
Avoid:
- Repeating identical coves as tiles.
- Assuming water exists in the MCP material palette.
Conceptual sources: [Tutorial: Tips For Landscaping and Terraforming](https://www.minecraft.net/en-us/article/tutorial--tips-for-landscaping-and-terraforming), [Build With It: Cobblestone!](https://www.minecraft.net/en-us/article/build-with-it--cobblestone-). Recipe geometry and sequence are our own proposal.
## retaining-stair
**Retaining wall and short stair** · path · **9 × 5 × 10 blocks**
Make a grade change feel supported and intentionally connected.
Materials: `stone_bricks`, `stone_brick_stairs`, `stone_brick_slab`, `smooth_sandstone`, `smooth_sandstone_slab`, `mossy_stone_bricks`, `dirt`.
Assembly:
1. Survey lower and upper approaches first; adapt the proposed envelope to the actual rise.
2. Reserve five clear stair columns and two shoulder columns per side.
3. Use three or four one-block rises followed by a three-block-deep landing; fill every tread and retaining wall down to solid ground.
4. Return the side walls into the upper terrace instead of ending them as disconnected pillars.
5. Keep the cream cap continuous; limit moss to local soil-contact or shaded recesses.
**Clearance:** Five clear stair blocks and four-block headroom along the full ascending path, including caps and any overhead fixture.
Variants:
- A shorter flight for a lower terrace.
- An additional landing and separate second flight when the actual rise requires it.
Acceptance:
- Stair facing matches direction of ascent.
- Approach and landing elevations agree with the survey.
- No hollow exposed underside or unsupported cap.
- Shoulders do not create a climb-over route around containment.
Avoid:
- Solving a height mismatch with a decorative slab at the doorway.
- Placing a standard stair module without measuring the destination.
Conceptual sources: [Tutorial: Tips For Landscaping and Terraforming](https://www.minecraft.net/en-us/article/tutorial--tips-for-landscaping-and-terraforming), [Five simple path designs](https://www.minecraft.net/en-us/article/five-simple-path-designs), [Build With It: Cobblestone!](https://www.minecraft.net/en-us/article/build-with-it--cobblestone-). Recipe geometry and sequence are our own proposal.
## luggage-bench
**Bench and luggage group** · props · **7 × 3 × 4 blocks**
Tell a station story with a small, useful-looking prop group.
Materials: `spruce_stairs`, `spruce_planks`, `stripped_spruce_log`, `smooth_sandstone`, `green_concrete`, `gold_block`.
Assembly:
1. Put a three-seat bench against the back of a widened pocket, facing the plaza.
2. Group two wood-toned luggage shapes at one end, leaving seat fronts clear.
3. Reserve a green backing for one real destination or station identity plaque.
4. Use at most one small metallic accent in the group; omit it if it attracts more attention than the navigation.
**Clearance:** Provide a separate three-block passing strip in front and preserve any wider existing route.
Variants:
- Bench alone.
- Bench with one planter instead of luggage.
Acceptance:
- Object reads as a resting place from the walking path.
- Luggage does not intrude into the bench approach.
- No label advertises an unfinished accessible destination.
Avoid:
- Crates in every empty corner.
- Unsupported decorative item entities or invented text APIs.
Conceptual sources: [Interior Motives](https://www.minecraft.net/en-us/article/interior-motives), [Fantastic Furniture](https://www.minecraft.net/en-us/article/fantastic-furniture), [Five simple path designs](https://www.minecraft.net/en-us/article/five-simple-path-designs). Recipe geometry and sequence are our own proposal.
## concealed-light-lens
**Full-block concealed light lens** · lighting · **3 × 2 × 3 blocks**
Illuminate a large room without adding a hanging fixture to every bay.
Materials: `glowstone`, `brown_stained_glass`, `smooth_sandstone`.
Assembly:
1. Reserve a three-by-three floor sample outside patterned paving, tree roots, landings and interactive controls.
2. Keep full paving in the eight perimeter columns; in the center put glowstone below a full brown stained-glass block flush with the walking surface.
3. Keep supporting construction below the sample intact and record expected states before replacement.
4. Prototype one lens; increase coverage only after matching night and interior photographs reveal dark areas.
5. A ceiling variant reverses the emitter and visible lens positions within an intact full-block ceiling.
**Clearance:** Top of the floor lens remains flush. Ceiling version preserves all existing route headroom and sealed upper rooms.
Variants:
- Use ordinary full glass if the brown lens makes the sample too dark.
- Concealed side lighting for an exhibit rather than more floor lights.
Acceptance:
- Full-block collision remains at the floor/ceiling surface.
- Actual captured room and exhibit faces become legible.
- No new bright fixture competes with the entrance or lift.
Avoid:
- Tinted glass: it blocks light and is not interchangeable with stained glass.
- Assuming more fixtures automatically produce a better interior.
Local precedent: Stage 07 used concealed brown-glass lighting and real camera review; this reusable sample has not itself been instantiated.
Conceptual sources: [Cozy Chambers](https://www.minecraft.net/en-us/article/cozy-chambers), [Caves & Cliffs: Part I out today on Java](https://www.minecraft.net/en-us/article/caves---cliffs--part-i-out-today-java). Recipe geometry and sequence are our own proposal.
## masonry-weathering
**Cause-based masonry weathering** · surface · **12 × 6 × 1 blocks**
Add age and material variation while retaining large calm wall fields.
Materials: `stone_bricks`, `cracked_stone_bricks`, `mossy_stone_bricks`, `andesite`, `smooth_sandstone`, `cut_sandstone`.
Assembly:
1. Choose either the gray retaining-wall family or the cream facade family; do not mix both randomly.
2. Save a mask for soil contact, sheltered joints and selected worn edges.
3. For gray masonry, use small connected mossy patches in the mask and a few connected cracked areas away from structural focal edges.
4. For cream masonry, keep the field mostly smooth and use cut sandstone to express masonry bands or quiet local variation; do not add green flecks everywhere.
5. Preserve trim, signs and dominant shapes, then inspect at near, approach and whole-building distances.
**Clearance:** Surface substitution only; preserve structural collision, public closure and existing manual edits.
Variants:
- Clean maintained station entrance with minimal weathering.
- More aged retaining wall near shaded soil contact.
Acceptance:
- Weathering locations have a visible cause.
- Large forms still read from the approach.
- Exact seed and patch anchors recorded for reproducibility.
Avoid:
- Independent random choice at every voxel.
- A universal percentage of damage on every material.
- Replacing load-bearing full cubes with stairs merely for texture.
Conceptual sources: [The Sky is No Limit](https://www.minecraft.net/en-us/article/sky-no-limit), [Build With It: Cobblestone!](https://www.minecraft.net/en-us/article/build-with-it--cobblestone-), [Build with It: Diorite!](https://www.minecraft.net/en-us/article/build-it--diorite-). Recipe geometry and sequence are our own proposal.
+13
View File
@@ -0,0 +1,13 @@
# Decoration workflow
Decoration uses the ordinary checked building tools. A design recipe is a specification to translate into geometry; it is not an additional MCP tool. Keep building-specific palettes, coordinates, references and construction records in the map project.
1. Read `project_context` and inspect the relevant part of the world. Establish the room's purpose, main silhouette and clear routes before adding detail.
2. Choose a coherent palette. Use `material_search` for focused discovery and `material_describe` for a few exact defaults and property domains; reuse them while the catalog version is unchanged. See [material discovery](MATERIALS.md).
3. Build one small prototype. Check proportions, supports, orientation and daylight appearance before repeating its motif. Leave calm surfaces between focal details and use texture variation in deliberate patches.
4. Preserve entrances, circulation, sightlines and unfinished-space closures. Thin decorative blocks do not prove containment. Doors, beds and tall plants need all their component blocks; leaves usually need `persistent=true`.
5. For an open trapdoor, choose the physical panel edge first: the panel occupies the edge **opposite `facing`**, with a thickness of 3/16 block. Check that it touches the intended support instead of leaving a 13/16-block gap. Horizontal lids use `half`; already correct panels must not be globally inverted.
6. Apply bounded plans with fresh expected states, including `snapshot_id` for existing block entities. Stop on conflicts and preserve manual changes. Use checked undo when a completed detail needs to be removed.
7. Inspect actual Minecraft captures from player height and an overview; check night lighting when relevant. State which views remain unverified. A matching block-state list does not establish good lighting or physical panel contact.
The short shared instructions live in [building-guidance.ts](../bridge/src/building-guidance.ts). They are supplied to MCP and ACP clients without loading an entire recipe library into every turn. External map documents are not implicitly accessible to the in-game ACP agent.
+95
View File
@@ -0,0 +1,95 @@
# Floating-island geometry
[`scripts/voxel-island.py`](../scripts/voxel-island.py) is a deterministic offline
Python helper. It returns solid vertical columns for a floating island. It does
not contact Minecraft, place blocks, or register an MCP tool. Surface grading,
materials, buildings and gameplay remain the caller's responsibility.
Run this example from the MCP checkout:
```python
import importlib.util
from pathlib import Path
spec = importlib.util.spec_from_file_location("islands", Path("scripts/voxel-island.py"))
islands = importlib.util.module_from_spec(spec)
spec.loader.exec_module(islands)
columns = islands.columns(
cx=120, cz=-80, radius_x=18, radius_z=13,
surface_y=144, depth=30, seed=27, contour=0.055,
)
for (x, z), column in columns.items():
for y in range(column["bottom"], column["top"] + 1):
pass # Add this coordinate to an offline blueprint, with a chosen material.
```
`bottom` and `top` are inclusive integer block coordinates. `radial` is normalized
distance from the shaped outline: zero at the centre, one at the rim. The top is
flat; modify it deliberately for circulation instead of adding surface noise by
default. Keep generated volumes bounded before expanding columns into voxels.
## Shape and noise
The outline starts with an ellipse. After dividing offsets by the two radii, the
angular boundary is `1 + contour * (sin(3θ + phase) + 0.45*sin(7θ - phase))`.
Low-frequency lobes establish a readable silhouette; the weaker seventh harmonic
adds smaller variations. Accepted contour strength is `0..0.2`. The boundary
therefore remains positive and at most `1.29` times the base ellipse; the helper's
`1.3`-radius sampling envelope contains it.
The underside uses a radial taper, `(1 - radial**1.55)**0.62`, multiplied by
correlated value noise sampled every 7.5 blocks. A smaller field sampled every
3.8 blocks adds hanging ribs. Smoothstep interpolation makes neighbouring samples
coherent. Thickness is rounded once and is at least three blocks. `depth` controls
the main taper, not an exact maximum thickness: the base and ribs add several
blocks. Read the returned bounds instead of predicting a fixed lowest Y.
Use broad noise fields for material bands as well. Independent random material
choices at every block create speckles and conceal the shape. Keep the seed and
generator version with the resulting blueprint. The underside noise is anchored
in world X/Z: moving the centre preserves the translated outline but can change
its thickness field.
This column model is a structural starting point. A flat top with many similarly
tall perimeter columns can look like a cut cylinder even when the outline and
tip are irregular. Inspect an actual oblique close view before adding more noise.
Use a few connected clefts, varied rock ribs and restrained edge vegetation to
break the sidewall silhouette. Keep a clear fighting or walking surface where
the design needs one; sculpting the underside does not require roughening every
usable floor. Preserve a versioned baseline and validate support again after
the decorative pass.
## Checks before placing a blueprint
- Flood-fill the intended top footprint using four-neighbour adjacency. The
continuous outline is radial, but discrete connectivity should still be checked
for the chosen radii and seed. Check separate islands remain separate.
- Require the entire base of each pier, stair approach and planter to have
support. Testing only the centre of a building misses unsupported outer piers.
Never skip unavailable foundation cells and then place the complete building
above them. Move the feature inward or author a connected plinth first.
- Check plant substrates and lantern attachment faces against the final combined
blueprint. Hanging lamps need a real beam/chain; slabs and stairs need their
actual state and collision height considered.
- Verify each spawn has its intended floor and four clear blocks above it. Check
routes through the final furnishings with their actual standing heights;
drawing a ring in the floor does not prove that the ring remains traversable.
- Measure all intended gaps and landing areas. A block count is geometric
evidence, not proof that sprinting, knockback or a configured double jump can
cross the gap. Confirm those interactions on the running server.
- For void arenas, inspect every exposed standing surface below the main deck.
Place the elimination threshold to prevent unintended recovery ledges or
sheltered camping pockets, while leaving the visible underside intact.
The supplied regression checks cover reproducibility, negative coordinates,
sampling bounds, solid column intervals and representative discrete connectivity:
```bash
python3 -m unittest discover -s scripts -p 'test_voxel_island.py'
```
Use the normal checked MCP editing path to modify an existing world. Loading an
offline blueprint as the initial generator of a new world is a separate operation;
it does not acquire block-by-block editor undo simply because this helper produced
the geometry.
+2 -2
View File
@@ -31,7 +31,7 @@ The following scenarios passed on real Paper in a separately created test world:
- A hollow cube through real MCP: 26 blocks; `.schem` export, the asset library, undo, import at the same anchor, and another undo restoring 27 blocks of air.
- A missing camera returns an error without substituting an image.
- After installing the mod in Prism, a 575-block tower was built and four real 1280×720 captures were obtained. The last completed the full Camera → Paper → Bridge → MCP ImageContent path. The first request failed when the viewpoint changed; a retry with the client stationary succeeded. [Test report](ONE_CLIENT_TEST.md).
- A reference-based Gothic hall was built, photographed, and polished through checked recipes: 30,125 final blocks and 53 lanterns. Final verification covered 30,843 positions, including 718 removals; grass growth on eight newly planted soil blocks was explicitly recorded. Day, dusk, and interior captures were inspected. At that stage, the narrower Paper policy rejected nonpersistent leaves and waterlogged lantern states; the runtime registry expansion removes that material restriction. [Build report](builds/GOTHIC_HALL.md).
- A reference-based hall was built, photographed, and polished through checked recipes: 30,125 final blocks and 53 lanterns. Final verification covered 30,843 positions, including 718 removals; grass growth on eight newly planted soil blocks was explicitly recorded. Day, dusk, and interior captures were inspected. At that stage, the narrower Paper policy rejected nonpersistent leaves and waterlogged lantern states; the runtime registry expansion removes that material restriction. [Example capture](images/build-demo.png).
Real `codex-acp` completed `initialize` in a separate profile without login: ACP v1 and session loading support are confirmed. That initial check did not invoke a model or consume model tokens. Dedicated ChatGPT sign-in and real authenticated ACP calls to `project_context` and `region_inspect` have since passed against Paper. A subsequent model turn placed and verified one oak-plank block at (24, -60, -45), then used checked undo and verified air. Place operation: `ae0166c8-6d03-45ab-a80a-48b644819a2b`; undo: `751017ba-8e07-433b-b38d-71dcc8cf2330`. A local proxy restricted writes to the fixture and its recorded undo.
@@ -59,7 +59,7 @@ Sponge v2 `.schem` is implemented without a WorldEdit dependency: up to 4096 blo
1. Extend the verified ACP one-block roundtrip to larger in-game `/ai` builds, real cancellation, and reconnect recovery.
2. Extend the verified single-client Prism scenario: test disconnection/freezing during capture and convenient switching between building and camera use.
3. Extend the demonstrated procedural Gothic-hall workflow to larger authenticated ACP builds, then reassess release readiness, limits, context deltas, and geometry extensions.
3. Extend the demonstrated procedural building workflow to larger authenticated ACP builds, then reassess release readiness, limits, context deltas, and geometry extensions.
## Terrain toolkit
-47
View File
@@ -1,47 +0,0 @@
# Shacraft arrival square — garden finish
Stage 03 finishes **zone 01** on the existing foundations. The clock station and other districts keep their previous construction state.
The main reference is sheet 03, *Clock station and arrival square*, supported by sheets 01, 02, 10 and 11. Its defining features are a pale open apron, the green Shacraft emblem, concentric hexagonal paving bands, evergreen planting islands, pink and white flowers, benches and warm garden lighting. The concept images guide the composition; they are not measured Minecraft drawings.
![Finished arrival garden in Minecraft](references/shacraft-arrival-garden-overview.png)
## Built composition
- The former square setting-out grid is replaced with a cream paved field and three flush hexagonal contour bands.
- The actual green artwork from the preserved `logo-180.png` is sampled into a 25 × 35 block footprint. The open hexagonal shield and S replace the earlier placeholder medallion.
- Six low stone-edged planting islands contain six custom conifers, six smaller topiary trees, low evergreen clusters and 258 flowers. The southern beds extend to the balustrade, eliminating isolated strips of paving behind them.
- Six spruce benches face the square. Each has a three-block level approach through the planter edge. The benches are decorative; no sitting interaction is added.
- Sixteen supported lantern fixtures use slender posts and green copper hoods. Eight former light piers are replaced, including a balanced pair beside the arrival stair.
- Obsolete zone 01 survey stakes, its block number and its floating survey label are retired. Other district markings remain.
Paving remains at block Y95, with the main walking plane at Y96. The central sightline toward the clock station and all existing road connections are preserved. No terrain platform, station construction or new fountain is introduced by this stage.
![Planting, a bench and copper lantern fixtures](references/shacraft-arrival-garden-detail.png)
![Evening lighting in the actual Minecraft world](references/shacraft-arrival-garden-evening.png)
## Checked construction
Before the work, the full server surface matched Stage 02 at all 589,824 columns. A fresh 359,964-voxel plaza survey included soil, foundations, fixtures and canopy air; 294,516 overlapping voxel states also matched the previous checkpoint. Unexpected manual edits stop the compiler, and the normal checked editor protects against changes between preparation and application.
The final candidate consists of 4,734 changed blocks. Its review checks persistent leaf distances, valid soil under flowers, grounded trunks, lantern support, bench approaches and 1.8 blocks of walking headroom. Grass beneath opaque tree trunks is replaced with dirt explicitly so random ticks do not change the recorded foundation state. The road audit starts with the previously verified usable surface, excludes actual planting and furniture, and checks the original eight route widths and their connectivity.
Final verification uses fresh observed blocks and a new full server map. These sequential surveys are not atomic world snapshots; construction remains idle during them. Perspective screenshots are real Fabric client captures, with heuristic render readiness. Geometry checks do not represent a human playtest or a full simulation of moving-player collisions.
The [final live report](references/shacraft-arrival-garden-verification.json) passed after **4,811 checked writes in 12 batches**, including a 77-block finishing pass that gives the conifers continuous green tips. All **4,734 final changed states** matched the latest observation. It checked 537 persistent leaf states, 258 supported flowers, 73 connected trunk blocks in 12 trees, 16 lantern supports and **4,955 clear walking samples**. All eight inherited road widths and 18 bench-front positions passed, with no isolated usable paving. The full **589,824-column map** matched the expected world, and all 41,467 visible water columns remained unchanged.
![Actual arrival garden surface map](references/shacraft-arrival-garden-map.png)
## Reusable tools
- `scripts/plaza-assets.py`: deterministic conifers, oriented benches and supported copper-hood lantern fixtures. Functions return local voxel states and never write to a world.
- `scripts/build-shacraft-plaza.py`: composes the approved garden geometry, real brand mask and static assets into a checked recipe. It preserves foundation elevations and existing road treads.
- `scripts/verify-plaza.py`: independent candidate/live validation of planting, fixtures, walking clearance and the inherited road network.
- `scripts/layout.py`: bounded checked placement, receipts and conflict-aware reverse undo.
The Paper policy now supports 99 materials. The added flowers are single-block decorative species; new copper forms are waxed. Existing restrictions on fluids, waterlogged states and nonpersistent leaves remain in force. The strict schematic codec retains its earlier material subset, so complete world checkpoints and voxel recipes are the preservation format for these gardens.
The final recipe, original observations and applied ledger are retained locally under `.runtime/plaza-stage03/`. The reference study and its earlier candidate are preserved separately from the finished state. Stage 02 remains available in the local Git archive and its full world backup.
The restorable final world checkpoint is `.runtime/projects/shacraft-arrival-garden-20260913/`, captured after an explicit save flush with automatic saving temporarily disabled and then re-enabled. It includes the full world container, matching plugin state, both stage ledgers and the earlier foundation receipts. Undo the apex polish ledger before the main garden ledger. The removed zone 01 text display is an independently recorded operator action rather than a block-journal change.
-46
View File
@@ -1,46 +0,0 @@
# Shacraft arrival square — perimeter balustrade
Stage 04 completes the edge of the finished zone 01 garden with a continuous pale handrail, regularly spaced sandstone piers and connected stone balusters. It follows the existing hexagonal terrace while keeping the road approaches open. The garden, logo apron, lighting and clock-station construction retain their previous state.
![Completed arrival-square balustrade in Minecraft](references/shacraft-balustrade-overview.png)
## Boundary and heights
The balustrade contains **302 perimeter columns** split into **five uninterrupted fence runs**, separated by the existing approach openings. The runs contain 46, 80, 74, 71 and 31 columns. Forty-six cut-sandstone piers mark endpoints, principal corners and intermediate bays.
Paving remains at block Y95, with its walking plane at Y96. Balusters and piers occupy Y96. A bottom smooth-sandstone slab at Y97 forms a continuous handrail with its upper surface at **Y97.5**, 1.5 blocks above the plaza walking plane. Wall connections are explicit, including tall side connections beneath the handrail and reciprocal connections to six adjoining road-rail columns.
The boundary forms a cardinal block chain. Elbows close the diagonal steps so adjacent railing pieces meet along block faces. Where planting occupies the inner choice, the connector moves to the outer side. Twenty-two small outer columns have stone-brick footings rising from observed full support to cut-sandstone coping at Y95. They support individual elbows without adding another terrace.
Four existing southern planter-rim slab columns are incorporated into the new boundary. Planting contents, existing lamps, road treads and the clear approach widths are preserved.
![Connected railing, pale coping and sandstone piers](references/shacraft-balustrade-detail.png)
![Grounded outer elbows and the terrace edge](references/shacraft-balustrade-exterior.png)
## Checked construction
`scripts/build-shacraft-balustrade.py` reads captured blocks and compiles a plan without changing the world. It refuses unexpected decoration at fence or handrail positions, protects inherited road cells, and finds observed footing support. `scripts/layout.py` checks expected states during preparation, journals bounded applications and verifies their results.
The editor made **692 checked writes in four batches**: 682 initial writes and ten finishing writes for the road-rail joints and buried soil. Twenty-one grass blocks beneath the new footings had already changed naturally to dirt; the remaining buried grass block was explicitly stabilized. The recorded final comparison covers **710 distinct expected states**, including those observed soil transitions. Their positions are preserved in `settled-soil.json` alongside the stage records.
The [final observed-world report](references/shacraft-balustrade-verification.json) passed. It checks the complete **556,308-voxel captured volume** against the baseline plus final plan, including **555,598 voxels outside the final changes**, with no mismatches. All 302 handrail columns, 46 piers, 22 grounded footings and six reciprocal rail joins passed. It also confirms all 1,172 preserved garden fixture states, **4,815 walking/headroom samples**, the original eight route widths and 32 bench-access columns.
The separate complete surface comparison matched all **589,824 map columns**, including 589,516 columns outside the edited area. All 41,467 previously visible water columns remained unchanged. The navigation graph reached all 57,352 surface samples across 14,338 usable columns.
These sequential voxel and surface captures are not atomic snapshots; construction was idle during final measurements. The volume check covers the supplied observed bounds. Route checks verify geometry, support and headroom, without simulating a moving player's complete collision body. Perspective images are actual Fabric client captures with heuristic render readiness.
![Actual server surface after the balustrade finish](references/shacraft-balustrade-map.png)
## Tools and preservation
- `scripts/build-shacraft-balustrade.py` compiles the continuous perimeter, grounded elbows and explicit connections.
- `scripts/verify-balustrade.py` independently checks the final rail, protected garden, approaches, navigation and complete observed volume.
- `scripts/verify-foundation-survey.py` checks the full before/after server surface against the final column states.
- `scripts/layout.py` provides checked placement, journal receipts and conflict-aware reverse undo.
Stage inputs, captured observations, final recipes and application receipts remain under `.runtime/balustrade-stage04/`. The archive separates initial computed previews and candidate checks from final Minecraft images and fresh observed-world reports.
The restorable checkpoint is `.runtime/projects/shacraft-plaza-balustrade-20260913/`. It contains the complete world container, matching plugin state and stage receipts. The world was explicitly flushed with saving temporarily disabled for the copy, and automatic saving was re-enabled afterward. All 137 recorded world-file hashes passed verification.
Previous references and stages remain in `/home/emil/Desktop/Shacraft-Lobby-Archive`. Raw observations, complete world saves, private plugin configuration, authentication data and journals stay outside its Git history. Undo the finishing ledger before the initial balustrade ledger, then process older stages only if requested. Natural soil transitions are recorded explicitly and must be considered during restoration; manual-edit conflicts stop checked undo.
-61
View File
@@ -1,61 +0,0 @@
# Shacraft — foundations for zones 01 and 02
This document preserves the Stage 02 foundation checkpoint. Zone 01 has since received its [Stage 03 arrival garden finish](SHACRAFT-ARRIVAL-GARDEN.md).
This construction stage develops the arrival square and clock station in the approved natural v2 world. It also builds their local approaches. The other district reservations and future bridge spans remain at the survey stage.
![Completed foundations and local approaches in Minecraft](references/shacraft-foundations-overview.png)
## Levels and circulation
The arrival square and oval station forecourt use paving blocks at **Y95**, with the walking surface at Y96. The station floor uses blocks at **Y98**, with the walking surface at Y99. The station follows its actual hall, tower and pavilion footprint. Its western retaining wall has shallow blind arches and stone pilasters; solid backing remains behind the recesses.
A nine-block clear avenue links the square to the forecourt. A **21-block clear stair** rises to the station in half-block tread increments, with full landings. The local southern approach is nine blocks wide, the district connections seven, and the lake approach five. Curved roads use full transverse rows of correctly facing stairs, with separate edge coping. Lamps and balustrades sit outside the reserved clear lanes.
Finished road endpoints, expressed as X/Z and the supporting block's Y:
- Southern approach: `(1, 110)`, Y79, joining native ground at the same level.
- Portal approach: `(-72, -46)`, Y89, joining native ground at the same level.
- Lake approach: `(-90, 32)`, an east-facing bottom stair at Y84, stepping down to native full blocks at Y83.
- Northwest station approach: `(-80, -77)`, Y85, joining native ground at the same level.
- Eastern bridge approach: `(82, 8)`, Y87.
- Northeast bridge approach: `(82, -78)`, Y86.
The two bridge approaches end at temporary balustrades beyond the completed walking deck. Those barriers must be removed when the corresponding bridge spans are constructed. Beyond the other local endpoints, the remaining route markings reserve later work; they are not finished roads.
![Actual server surface with the completed roads and foundations](references/shacraft-foundations-map.png)
## Materials and construction
The plaza has pale sandstone paving, restrained stone courses and a flush green Shacraft medallion. The station has a stone structural floor with setting-out bands for the future hall, clock tower and end pavilions. Exposed bases combine deepslate, stone brick and andesite coping. Twenty-seven lantern piers light the edges.
Every deck has structural courses and solid support down to the observed original terrain. The generator does not create a new rectangular terrain platform outside the building footprint. Small local cuts clear the paving and headroom; the original mountains and watercourses remain outside this construction scope.
![Western station base after arcade refinement](references/shacraft-foundations-west.png)
![Broad station entrance stair, captured in Minecraft](references/shacraft-foundations-stairs.png)
## Checked workflow
The design was compiled against a **1,981,407-voxel live before-survey**, including underground support and headroom. Unexpected differences from the original terrain plus known survey markers stop compilation. The placement driver also checks the caller's expected states atomically during preparation, journals bounded operations and verifies each applied batch.
The stage inputs and receipts are retained locally under `.runtime/foundations-stage02/`. A fresh post-build voxel survey checks standing heights and 1.8 blocks of vertical clearance on the actual full blocks and both stair treads. An independent half-block navigation graph checks route connectivity and full-width cross sections. These are geometric and block-state checks, not a simulated moving player or a manual playtest.
The full server-derived before/after surface maps are compared across the 768 × 768 world. The verifier applies air edits before finding the new top block, so lowered surfaces are checked correctly. Surface maps and sequential voxel surveys are not atomic; construction is kept idle while final measurements are taken. Perspective images use the real Fabric client, whose render readiness remains heuristic.
The [completed verification report](references/shacraft-foundations-verification.json) records **79,081 checked writes across 67 journalled batches**, including a 408-block refinement that moved the western pilasters clear of the arches and darkened their intact backing. All **78,673 final changed voxel states** matched the post-build survey; **15,708 standing-height and headroom samples** passed. All **589,824 surface columns** matched the expected result, including **572,923 columns outside the edited area**. All 41,467 previously visible water columns remained unchanged, and no observed water blocks were replaced.
## Tools and preservation
- `scripts/foundation-study/design.py` and `geometry.py` define the elevations, contours, stairs and road corridors.
- `scripts/build-shacraft-foundations.py` compiles observed terrain, approved geometry and materials into a checked block plan; it does not write to the world.
- `scripts/layout.py` applies bounded batches and supports checked reverse undo through the stage ledger.
- `scripts/foundation-survey.py` records actual voxel states and checks floor support and headroom.
- `scripts/foundation-study/verify_geometry.py` independently checks planned navigation.
- `scripts/verify-foundation-survey.py` compares actual surface maps with the complete edited column state, including excavation.
Original references and the marked-site checkpoint are preserved in the separate local Git repository `/home/emil/Desktop/Shacraft-Lobby-Archive`. Each completed stage has its own directory, source provenance and SHA-256 manifest. Restorable world backups remain outside Git, together with their matching private plugin state and operation journals.
The completed world checkpoint is `.runtime/projects/shacraft-foundations-01-02-20260913/`, captured with saving disabled after an explicit flush; normal saving was then re-enabled. It contains the full world container, including `world/dimensions/minecraft/shacraft_lobby_v2`, both relevant plugins and the construction ledgers. World-file checksums are recorded in `checkpoint.json`.
An undo must run newer stage ledgers before older ones and stop on manual-edit conflicts. Floating labels are separately managed entities; their operator commands are recorded with the stage artifacts rather than in the block journal.
-68
View File
@@ -1,68 +0,0 @@
# Shacraft lobby site marking
This document preserves the **Stage 01 survey checkpoint**. The current world has progressed to [Stage 02: foundations and local roads for zones 01 and 02](SHACRAFT-FOUNDATIONS.md).
The existing `shacraft_lobby_v2` alpine terrain is now marked for the future lobby. This is a site survey: building contours, entrances, courtyards, paths, bridge deck reservations, height stakes and wayfinding. Buildings, playable minigames and finished paths have not been constructed.
![Live world map and layout legend](references/shacraft-layout-final.png)
## Visit
Connect to the private local server at `127.0.0.1:25575` using the **26.2 MCP Building** Prism profile, then use `/lobby`. Spectator mode is useful for inspecting the complete arrangement. The configured camera client can reconnect autonomously after a local server restart.
The planning envelope is 768 × 768 blocks. Natural mountains frame the developed valley; the terrain was not flattened to fit district rectangles. Surface contours replace a single observed top block. Raised lines reserve future bridge, pier and airship elevations while leaving the river below intact.
## Legend and coordinates
Coordinates below identify the districts in X/Z. The same two-digit numbers are drawn with blocks; lit colored posts carry nearby floating names.
- **01 · lime · arrival square · (0, 8).** Open hexagonal plaza and Shacraft medallion, with a direct view toward the clock station.
- **02 · yellow · clock station · (-18, -119).** Hall, projecting tower, end pavilions and a smaller oval forecourt.
- **03 · purple · portal concourse · (-201, -156).** Chamfered hall, six separate portal bays and a garden approach.
- **04 · cyan · airship harbor · (179, -137).** Terminal, three west-facing piers at Y79 and a flagship reservation at Y92.
- **05 · red · sky gardens · (207, 88).** Palm glasshouse, winter garden and observatory. White paths follow their surrounding courts.
- **06 · orange · market quarter · (-195, 225).** Six small building plots, an open market square and individual entrance connections. These plots use the calmer southern shoulder.
- **07 · white · arrival avenue · (8, 284).** Long southern approach and a final viaduct at Y65.
- **08 · blue · lake waterworks · (-135, 43).** Pumping house, viewing terrace, Y51 boardwalk and two marked future stair approaches.
- **09 · pink · scenic overlooks.** Five small viewpoints with optional trails, preserving the mountain slopes.
White paired lines reserve path edges. Main avenues are designed for nine-block clear corridors, the district loop generally seven, and smaller access paths three to five. Colored building boundaries are reservations, not final material choices. White cross-ties and tall end stakes show bridge deck widths and elevations. Labels identify the larger level changes where stairs or staged access will be needed. The current block contours alone do not certify walking access.
## What was placed and checked
- 41 geometric reservations and 48 route segments, including six bridges, three airship piers, six portal bays and six market buildings.
- 16,967 distinct marker positions, applied with 17,040 checked writes across 36 journalled batches. The small second pass adds missing access links and extends bridge height stakes.
- Eight district labels and eleven access/elevation labels, verified again after the server restarted.
- Every batch was checked before planning, atomically against its caller snapshot during preparation, and after application. Stable operation keys and persisted receipts support resumption and checked undo.
- Full before/after world surface comparison and targeted reads beneath obscuring markers are recorded in the [verification report](references/shacraft-layout-verification.json). The map is read from actual Paper blocks, not reconstructed from the noise generator.
![In-game view of the arrival reservation and station axis](references/shacraft-layout-arrival.png)
## Autonomous map exporter
The optional terrain plugin implements this **server-console** command:
```text
lobby map survey-name
lobby status
```
It writes `plugins/ShacraftTerrain/maps/survey-name.png` and `.json`. The PNG has one pixel per world column, north up, with material colors and height shading. The JSON includes actual surface heights, material palette and coordinates. Existing names are never overwritten. The exporter loads only existing chunks, reads one chunk per tick, and renders/writes the detached result asynchronously. It requires no Minecraft client or account.
The exporter reads chunks sequentially, so a map is not an atomic world snapshot. Construction was idle during the verification captures. A top surface also hides the water beneath a bridge; separate bounded RPC reads verified that water. Text display entities appear in game but are not included in this block-surface map.
This is an orthographic world map. Perspective screenshots still use the Fabric spectator client and its heuristic render readiness.
## Reproduce and revise
The reusable [spatial plan](../examples/layout/shacraft-lobby-layout.json) and [access refinement](../examples/layout/shacraft-access.json) describe reservations, routes, heights and intent. Their geometry was studied against the natural terrain before live surface data was used for placement.
- `scripts/mark-shacraft-layout.py` compiles the primary survey from a current surface map and authorized world scope.
- `scripts/compile-layout-access.py` compiles the access refinements against the original survey and known primary marker states.
- `scripts/layout.py report` describes bounded batches without touching a server. `prepare` checks the input without allocating expiring plans. `apply --execute` writes and verifies; `undo --execute` uses reverse journalled undo.
- `scripts/render-layout-map.py` renders the labelled atlas from live surface data. Supplying `--blocks` explicitly produces a labelled **design preview** instead.
- `scripts/verify-layout-survey.py` compares every visible column and checks hidden water through bounded live reads.
The local applied ledgers are `.runtime/layout-study/placement-final.json` and `.runtime/layout-study/access-ledger.json`, with adjacent immutable input snapshots. Undo the access ledger before the primary ledger. Manual changes can block undo and must be preserved and reviewed. The 19 text displays are a separate operator-managed layer with tag `shacraft_layout_v1`; they are not part of the block journal. An explicit undo of the whole survey also requires removing that tagged display layer in the same world.
A complete stopped-world backup, including plugin state and layout ledgers, is stored locally in `.runtime/projects/shacraft-marked-lobby-20260913/`. The earlier unmarked natural world remains backed up separately. Private configuration and authentication material are excluded from the public examples and report.
-65
View File
@@ -1,65 +0,0 @@
# Shacraft clock station — vestibule and SMASH gallery
The clock station is built, furnished and verified in the local lobby world. Its two public floors contain the arrival vestibule and SMASH selection gallery, with enclosed personal lift cabins, warm architectural lighting and a closed island display. The complete world and matching plugin state are backed up.
![Completed clock station in Minecraft](references/station-stage07/station-overview.png)
The station occupies the existing irregular zone 02 foundation. Its 5,764 surveyed columns fit inside X **-74..40**, Z **-145..-83**. Pale stone arcades, green copper roofs, spruce ceilings, brass accents and warm lanterns continue the original clock-station reference. The roof silhouette rises from eaves at Y126 to a main ridge at Y140 and a clock-tower peak at Y158. Roof overhangs extend the complete building envelope to X **-76..42**, Z **-147..-81**.
The coordinate drawings and generated perspectives remain in `docs/references/zone02-interior-v1/`. Those images establish the visual direction; the saved layout and actual foundation geometry govern placement. They are not photographs of the completed building.
![South entrance and completed Shacraft nameplate](references/station-stage07/station-front.png)
## Two complete public floors
The vestibule floor occupies block Y98, with players standing at **Y99**. The SMASH floor occupies block Y112, with players standing at **Y113**. The intermediate deck at Y111..112 is continuous. Decorative coffer ceilings close each room; the upper structural ceiling at Y124..125 separates both public floors from the inaccessible roof and clock tower.
The south entrance follows the existing X=-6 approach axis. Its clear opening spans X=-9..-3, retaining seven blocks of width. Matching square columns align vertically on both floors. Shallow cream corbels and spruce ceiling panels remain above the circulation space, while inset green and brass-colored floor bands guide the central approach. Side galleries contain spruce benches, small planted stone boxes and restrained floor mosaics. There are no additional unfinished public rooms, stairs to the attic or open shafts.
The interior generator owns only the two-block setback inside the actual foundation, at block Y98..123. It leaves the exterior wall and window layers to the exterior compiler. Its 5,064 interior columns contain fifteen benches, ten small topiary planters and 48 hanging lanterns, with three additional miniature trees in the diorama. The complete recipe combines the exterior and interior before selecting only changed states against the captured baseline.
Real Minecraft photographs prompted a lighting refinement. Sparse brown-glass floor tiles reveal concealed glowstone below the paving; matching small lenses recess into the plain spruce ceiling panels. The regular nine-block layout adjusts locally around beams, mosaics, furniture, controls and landing points. All lens and emitter replacements retain full-block collision and solid floor/ceiling separation. The enclosed diorama receives its own concealed lighting.
![Furnished and illuminated ground-floor vestibule](references/station-stage07/station-vestibule.png)
## Enclosed lift cabins
The lift housing is **X=-10..-2, Z=-124..-116** on both floors. Each stationary cabin has a five-by-five clear interior at X=-8..-4, Z=-122..-118 and a five-block-wide south opening. Both cabin floors remain solid. The space above each cabin is closed, so the lift provides no passage to a shaft or unfinished upper rooms.
Gold selector blocks sit on the north interior wall at **(-6, 101, -123)** and **(-6, 115, -123)**. Right-clicking a selector from inside the matching cabin changes floors for that player alone, arriving at **(-5.5, 113, -119.5)** or **(-5.5, 99, -119.5)** facing south. The listener checks the destination support and two air blocks before teleporting. The independent geometry audit checks four blocks of headroom.
`/station` enters the ground-floor vestibule. `/station 1` and `/station 2` select the two completed cabin stops. The commands were exercised on the local server and both resulting player positions were read back; a third stop was rejected. The physical mouse-click path is covered by listener and cabin-selection tests but was not exercised through an automated client click.
Zone 01's previous invisible boundary remains in place. Use the station entry command while that earlier garden enclosure is retained; opening the physical route is a separate checked edit.
Twenty-four persistent text displays provide the exterior name, lift instructions, floor names, numbered arena placeholders and rules panels. A repeated installation replaced the previous set without increasing the count. These separately managed entities are recorded outside the block recipe. Arena placeholders do not perform world transfers or matchmaking.
## SMASH gallery
Six seven-by-five selection alcoves line the north gallery at Z=-140..-136, with centres at X **-42, -32, -22, -12, -2 and 8**. A seven-block-deep clear aisle at Z=-135..-129 connects them. Each alcove has a small decorative island relief, a framed display and a reachable selection surface. Slots **01–06 remain unassigned**; they do not advertise invented arena worlds, live queues or active minigames.
The western display occupies **X=-42..-24, Z=-124..-110**, a 19-by-15 rectangle. Miniature planted islands stand above a solid illuminated base, enclosed by continuous pale stone and glass. Twelve full brown-glass floor lenses admit concealed light inside the display while maintaining its intact base. It is a closed display on an intact floor, with no playable void below it. The nearby west gallery explains damage, knockback and double jumping. The eastern wing provides waiting benches and an orange terracotta floor accent. No SMASH arenas are included in this construction stage.
![Completed SMASH gallery and enclosed island display](references/station-stage07/station-smash.png)
## Verification and preservation
The completed stage required **84,446 checked writes across 98 batches** and has **83,924 final distinct changed states**. The final observed world matched every planned state. All **572,326 observed voxels outside the edits** also matched the baseline, completing the check of the full 656,250-voxel survey.
Independent observed-block checks pass for **4,796 vestibule walking columns** and **4,176 SMASH walking columns**, each with four blocks of clear headroom, and all **107 named furnishing and lift approaches**. Those counts include the exterior doorway columns; the interior generator alone reports 4,775 vestibule columns. Both cabins, both lift doorways, the main approach and the complete selection aisle were checked voxel by voxel. The fixture audit passed for 72 planned lantern supports, 78 persistent leaf states and thirteen rooted station/display trees.
The enclosure audit uses a temporary virtual cap at the intentional south entrance, then floods from both public floors and lift cabins. The cap is an analysis boundary, not a block placed across the doorway. Full glass and known full cubes stop the flood; partial and unknown shapes are treated as passable. The observed building has no connection from either furnished floor to the attic or clock tower. This static geometry audit does not prove lift behavior, spectator restrictions or administrative access control.
The complete visible-surface comparison passed for all **589,824 map columns**: 6,496 changed station columns and 583,328 unchanged outside columns. All **41,467 previously visible water columns** were preserved. The map was captured before the last lighting and nameplate polish. A separate final voxel comparison confirmed that all 602 subsequent polish differences lie below the exported roof surfaces, and that the actual final top blocks and surveyed blocks above them match the map for every station column.
The final plugin build passed 97 Maven tests; seven station-verifier tests and ten foundation tests also passed. World and surface captures are sequential rather than atomic. The four final photographs are actual Minecraft client captures with heuristic render readiness; their metadata does not claim a verified server revision. Observed block checks and runtime interaction receipts provide the separate measurement evidence.
`scripts/station-exterior.py` and `scripts/station-interior.py` generate the geometry. `scripts/build-shacraft-station.py` combines their owned regions, checks the observed baseline against the prior foundation checkpoint and compiles expected-state edits. `scripts/light-shacraft-station.py` generates the concealed lighting grid against the observed built station. `scripts/verify-station.py` independently checks the resulting circulation, enclosure and captured volume. Stage records are kept under `.runtime/station-stage07/`.
One interrupted batch verification exposed Minecraft's explicit `deepslate[axis=y]` state. The original receipt and manifest were retained. A fresh partial survey confirmed the applied prefix, and a separate remaining recipe continued from that observed state. This was a state-serialization correction at three miniature island tips; the retained recovery report records the exact positions and hashes.
The authoritative final recipe and metadata are `.runtime/station-stage07/final-v2/station.json` and `station.metadata.json`. The final observation is `after-complete.json.gz`, with `actual-complete-qa.json`, `complete-surface-verification.json`, `complete-surface-invariance.json` and `runtime-verification.json` recording the checks. The owner was returned to the vestibule at **(-5.5, 99, -92.5)** with spectator mode preserved.
The restorable backup is `.runtime/projects/shacraft-station-complete-20260913/`: **650 world and plugin files, 237,341,328 bytes**, with every recorded SHA-256 hash verified. Saving was flushed and temporarily disabled during copying, then automatic saving was re-enabled at 15:42:17 local time. `backup-receipt.json` records its location and verification.
The local Git archive preserves the final documents, generator and verifier snapshots, compact reports, reference plans, Minecraft photographs and surface maps. Complete world saves, raw voxel observations, private configuration, authentication, plugin binaries and placement journals remain in the separate local runtime backup. Earlier reference and construction checkpoints remain unchanged.
-53
View File
@@ -1,53 +0,0 @@
# Shacraft zone 01 — finishing details and invisible boundary
The arrival square is finished and its five approaches are closed with an invisible collision boundary. Players can explore the completed garden while the station and other districts remain outside the current playable area. The existing emblem, six planting islands, benches, lights and broad central sightline remain the focus.
![Completed arrival square in Minecraft](references/shacraft-zone01-overview.png)
## Visible finish
Two low pale-stone urns with white flowers stand at X/Z **(-10, 35)** and **(10, 35)**. A low green nameboard at **(-8, 43)** carries `SHACRAFT` and `Площадь прибытия`. Its text is a separately managed display entity attached visually to the board, with no directional arrows toward closed roads.
Five flush threshold bands use stone with small green-copper insets at the north, south, east, west and northwest approaches. Paving remains at block Y95, with the walking plane at Y96. Three full sandstone joint piers complete the road-to-plaza boundary, bringing the perimeter pier count to 49.
The visible recipe contains 106 changed block states, followed by a sixteen-write urn refinement. Together with the enclosure, the editor made **11,518 checked writes in twenty batches**. All **11,502 final distinct changed states** matched the final observed world.
![Welcome nameboard and planted stone urns](references/shacraft-zone01-welcome.png)
## Invisible enclosure
The boundary uses **11,396 barrier blocks**, recorded in a separate placement ledger so the enclosure can later be removed while keeping the garden finish. It includes side walls and a roof at block **Y116**, above the existing trees. The full-block floor at Y95 contributes to the enclosure.
The compiler bends the boundary inward around existing partial-block stairs and rails instead of replacing those details. The intended interior excludes 87 boundary-adjacent voxels for these local folds. The independently derived collision membrane contains **17,276 full-cube positions**: 11,396 barriers and 5,880 existing or finished structural blocks.
The [final observed containment report](references/shacraft-zone01-containment-verification.json) passed. The intended interior volume has one connected component containing 117,673 voxels. No interior voxel was reached from an exterior flood, and all **5,748 swept player-box boundary probes** were blocked. The probes use a 0.6 × 1.8 block player body; the complete static containment criterion is the full independently derived membrane. Unknown and partial blocks are conservatively treated as empty during the exterior flood.
This guarantee concerns normal continuous collision-based movement. Spectator mode, block removal, operator commands, plugin teleports and arbitrary discontinuous teleport or pearl behavior are outside its scope. The boundary is not an administrative access-control system.
![Arrival from the configured point inside the enclosure](references/shacraft-zone01-arrival.png)
## Arrival, respawn and maps
The configured `/lobby` destination is **(0.5, 96, 43.5)**, inside the southern welcome area. A scoped death-respawn handler returns players who died in the lobby world to that configured point, preventing Minecraft's highest-surface search from placing them on the invisible roof. It leaves other worlds and non-death transitions alone. The lobby spawn radius is zero. The scoped event behavior was unit tested; no player was killed for verification.
The owner was returned to creative mode at the verified arrival point after inspection. The nameboard entity, spawn settings and owner return are recorded separately from the block journals in `operator-actions.json`.
The server map exporter explicitly ignores `minecraft:barrier`, alongside air, when finding each visible surface. Exported metadata declares this policy, so maps show the garden beneath its invisible roof. Collision verification reads actual blocks separately and includes barriers.
![Actual visible-surface map, with invisible barriers excluded by policy](references/shacraft-zone01-map.png)
## Final verification and preservation
The complete **622,098-voxel captured volume** matched the baseline plus final plan, including **610,596 voxels outside the edits**. The finishing audit passed for 537 persistent leaves, 260 supported flowers, sixteen lanterns, twelve rooted trees, **4,794 walking/headroom samples** and 32 bench-access columns.
The complete visible-surface comparison matched all **589,824 map columns**. It covered 6,164 affected columns, with 87 visible surface changes; all 583,660 columns outside the affected area matched their baseline. All 41,467 previously visible water columns remained unchanged. The distinction between actual collision blocks and the declared visible-surface policy is preserved in the separate reports.
These sequential captures are not atomic snapshots. The full-volume statement applies to the supplied observed bounds, and static geometric checks are not a human playtest. Perspective images are actual Minecraft client captures with heuristic render readiness.
`scripts/finish-shacraft-zone01.py` compiles the visible finish, enclosure and boundary metadata. `scripts/verify-zone-containment.py` independently derives the collision membrane, checks containment and protects existing decoration. Stage records remain under `.runtime/zone01-stage05/`.
The barrier ledger is separate from the finishing and urn-polish ledgers. Remove barriers through their checked ledger when reopening the other districts; the visible garden finish can remain. Undo the urn polish before undoing the earlier visible finish. The nameboard text and scoped spawn settings are separately recorded operator/configuration actions.
The restorable backup is `.runtime/projects/shacraft-zone01-complete-20260913/`. The complete world container and matching plugin/receipt state were copied with saving temporarily disabled after an explicit flush, then automatic saving was re-enabled. All 137 recorded world-file hashes passed verification.
The local Git archive preserves compact design and final reports, source snapshots, maps, photographs and the world-backup location. Raw voxel observations, complete world saves, private configuration, authentication, plugin binaries and journals remain outside Git. All previous references and construction checkpoints remain unchanged.
+6 -8
View File
@@ -1,6 +1,6 @@
# Terraforming tools
The terrain toolkit turns one small JSON recipe into a repeatable height field, a raster preview, and bounded edit plans. It prepares the terrain foundation for the Shacraft lobby: mountain ridges, cliff-backed building platforms, a lake bed, garden terraces and ravines. Buildings and fluids are separate work.
The terrain toolkit turns one small JSON recipe into a repeatable height field, a raster preview, and bounded edit plans. It supports small hills, graded routes, ridges, dry channels and local terrain adjustments. Buildings and fluids are separate work.
## Design and boundaries
@@ -47,16 +47,14 @@ The terrain compiler and preview renderer run outside the server tick. Live read
Build once with `./mvnw package` and `npm --prefix bridge test`. Offline preview needs the Java runtime installed by the project's bootstrap script; `MCB_JAVA_HOME` can override its path.
Render the proposed Shacraft terrain without a running server:
Render the included eight-by-eight hill recipe without a running server:
```bash
python3 scripts/terrain.py preview examples/terrain/shacraft-massif.json \
--output docs/references/shacraft-terrain-heightmap.png
python3 scripts/terrain.py preview examples/terrain/small-hill.json \
--output .runtime/small-hill-preview.png
```
![Generated target heightmap](references/shacraft-terrain-heightmap.png)
The example proposes a 768×768×192 envelope and therefore 27,648 possible tiles at 4096 blocks each. This is a layout experiment, not an instruction to apply all tiles to the current world. It must be assigned a new, suitable project area before use. The current Gothic hall site is not a valid destination for it.
The example covers X/Z 0..7 and Y80..87, with a rounded hill over seeded low-amplitude noise. The output is a target heightmap, not an observed world image. Inspect a suitable site and select the correct area before applying the recipe. Larger map-specific recipes and their reference images should be stored in the map project, outside this reusable toolkit.
For an authorized small site, a local batch avoids sending every tile's polling traffic through model context. This Linux runner uses an exclusive manifest lock, saves requests before sending them, stops on conflicts and processes at most 64 explicitly selected tiles per invocation:
@@ -80,7 +78,7 @@ Automated tests cover ordered features, negative elevations/coordinates, determi
The opt-in `bridge/test/live-terrain.mjs` exercises the real MCP → Paper path in an isolated fixture: preview without writes, a 201-block hill, idempotent replay, checked undo, protected existing gold block, preserved cell, stale-plan conflict, empty mask, area rejection and unknown recipe ID. The local batch runner is also tested by apply → resume → undo with full air restoration.
A compact recipe and native PNG reduce context cost; they do not eliminate server work. Large sites still need many live reads and potentially large journals. No full 768×768 application, throughput target or crash/disk benchmark has been completed. This toolkit is ready for small terrain sections and progressive landscape work; a whole-map rollout should be benchmarked and staged separately.
A compact recipe and native PNG reduce context cost; they do not eliminate server work. Large sites still need many live reads and potentially large journals. No whole-map throughput target or crash/disk benchmark is claimed by these toolkit tests. This toolkit is ready for small terrain sections and progressive landscape work; a whole-map rollout should be benchmarked and staged separately.
## Relative brushes on existing terrain
-75
View File
@@ -1,75 +0,0 @@
# Gothic Hall
## Polished version
The current build contains **30,125 blocks**, including **53 lanterns** and **642 persistent leaf blocks**. The polishing pass changed 4,569 positions across 87 checked operations: 1,489 additions, 718 removals, and 2,362 replacements.
The main roof now has six small dormers instead of ten large ones. A thin iron ridge and window mullions, quieter gray stone bands, and a gold block bell bring the architecture closer to the reference. Portal lights, courtyard lamps, three nave chandeliers, wing and tower lights, low planted beds, and six narrow trees complete the scene. The existing entrance, stairs, timber structure, and connecting passage remain usable.
![Polished Gothic Hall in daylight](gothic-hall-polished-day.png)
![Polished Gothic Hall at dusk](gothic-hall-polished-evening.png)
![Lanterns and chandeliers inside the great hall](gothic-hall-polished-interior.png)
These are unprocessed Minecraft framebuffer captures without shaders: [day metadata](gothic-hall-polished-day.capture.json), [evening metadata](gothic-hall-polished-evening.capture.json), and [interior metadata](gothic-hall-polished-interior.capture.json). The exterior views use the same position and angles as the original capture below, with the server view distance increased to 12 chunks.
The new geometry lives in `polish_architecture.py` and `polish_scene.py` alongside the frozen original modules. After constructing the baseline and its 18-block finishing pass, run:
```bash
python3 scripts/polish-gothic-hall.py plan
python3 scripts/polish-gothic-hall.py apply
python3 scripts/polish-gothic-hall.py verify
```
The manifest, ledger, and verification report are in `.runtime/gothic-hall/polish/`. Preparation checks the canonical baseline and the current blocks; a saved plan must still expect the same states. Every operation receives a durable idempotency key before application. The original manifests and ledgers are preserved.
Final verification checked **30,843 positions**, including all 30,125 occupied positions and 718 removals to air, across 90 inspection tiles. It explicitly reported eight planted soil blocks observed as grass rather than dirt. This allowance is limited to the newly introduced planter soil during verification; preparation and application still require exact current states, and other mismatches stop the script without overwriting them. The final operation was `e7f0371d-e64c-48e0-86ae-13ac813dab98`.
The world and journal were backed up locally before polishing, and the finished world was saved with `save-all flush`. The camera remains honest about its heuristic readiness: `serverRevisionVerified` is `false`; block verification is a separate server read. The old baseline verification commands below describe their historical stages and will report expected differences after this polishing pass.
## Original baseline
A reproducible build based on the [visual reference](../references/gothic-hall-v1.png): a large hall with galleries, a smaller two-story wing, a connecting passage, and a bell tower. Modules in `scripts/builds/gothic_hall/` generate the geometry; `scripts/build-gothic-hall.py` applies it through the Paper plugin's checked operations.
This report records the original baseline before subsequent decorative polishing. It adapts the reference to the available palette: stone bricks, andesite, diorite, dark deepslate, wood, and tinted glass. No shaders were used. Detailed furnishing and landscaping were not part of this baseline; it includes a terrace, stairs, simple benches, and a raised platform. The bell is built from blocks, without a bell entity.
The baseline was applied in the live world: **29,354 blocks in 87 batches**, with verification saved in `.runtime/gothic-hall/verification.json`.
![Original Minecraft build without shaders](gothic-hall-built.png)
A real Fabric camera capture from September 12, 2026, after the initial finishing pass. The PNG is unprocessed; [capture metadata](gothic-hall-built.capture.json). Viewpoint: `(0, -20, -63)`, yaw `25°`, pitch `16°`, FOV `85°`. The test server's view distance was five chunks for this original capture, so distant edges disappear into fog. The current local server has since been updated to 12 chunks for the polishing pass. Frame readiness is checked on the client; agreement between the blocks and the blueprint was verified separately by reading the world.
The local coordinate origin is **origin = (-50, -60, -40)**. Add this origin to a local coordinate to obtain its world coordinate. All ranges below are inclusive; the main facades face north, toward `−Z`.
- Terrace: local `X=1..63, Z=1..62, Y=0`, size **63 × 62**. World coordinates: `X=-49..13, Z=-39..22, Y=-60`.
- Large hall: main body `X=7..31, Z=13..56`, size **25 × 44**; with decoration it occupies `X=3..35, Z=8..57, Y=0..48`. Main floor at `Y=6`, galleries at `Y=16`, roof ridge at `Y=43`. Main entrance near world position **(-31, -53, -31)**.
- Side wing: main footprint `X=38..57, Z=16..41`, size **20 × 26**; including projections, `X=36..59, Z=13..43, Y=0..28`. Floors at `Y=0/8`, roof ridge at `Y=28`. Entrance near **(-3, -59, -26)**.
- Bell tower: including projections, `X=34..46, Z=42..56, Y=0..60`, size **13 × 15**, with 61 block levels. Its top is at world `Y=0`; entrance near **(-10, -58, 2)**.
- Connecting passage: `X=31..40, Z=33..43, Y=0..16`; the walkway in `Z=36..39` rises from the hall floor at `Y=6` to the wing floor at `Y=8`.
Run commands from the repository root with Paper running, the project owner connected, and the building site's chunks loaded. The script reads project scope and the separate agent token from the private `.runtime/server/plugins/MinecraftBuilderMCP/config.yml`.
```bash
python3 scripts/build-gothic-hall.py plan
python3 scripts/build-gothic-hall.py apply
python3 scripts/build-gothic-hall.py verify
```
`plan` saves `.runtime/gothic-hall/manifest.json` and checks the palette, project bounds, and exactness of geometry compression into recipes. It does not change the world. Before each new batch, `apply` checks that the target region is empty, then calls `build_prepare` and `build_apply`. Original block states in the saved plan must also be air. `verify` compares recorded blocks with the live world and saves a report; it does not check empty spaces outside the recorded mask.
The resume ledger is `.runtime/gothic-hall/ledger.json`. It stores the blueprint hash, plans, idempotency keys, operation IDs, and their statuses. Rerunning `apply` resumes from this ledger using existing operations; completed batches are not rebuilt. The world ID and epoch are also checked.
An occupied region, a manual change to an expected block, or an unfinished/conflicting operation stops application. `verify` reports mismatches while preserving manual edits. If application stops, inspect the reported operation and its server journal; do not delete the ledger or automatically create a new plan over the existing structure. Server plans live in `plugins/MinecraftBuilderMCP/journal/plans/` and are required by this script for application and verification.
The initial finishing pass is stored separately from the original blueprint: `scripts/finish-gothic-hall.py` replaces 14 central pinnacle slabs with full stone blocks and four passage blocks with stairs. This removes gaps in the spires and makes the ascent between the buildings smooth. It uses a separate plan and `.runtime/gothic-hall/finish-ledger.json`.
```bash
python3 scripts/finish-gothic-hall.py plan
python3 scripts/finish-gothic-hall.py apply
python3 scripts/finish-gothic-hall.py verify
```
After that finishing pass, use the last command: it verifies the original building with the 18 replacements applied. The original `build-gothic-hall.py verify` expects those blocks' previous states and will report mismatches.
The finishing pass was applied as operation `682bb5bb-a1fe-4359-b687-06f7b1ce1005`. Reverification of all 29,354 blocks passed; the report is `.runtime/gothic-hall/finish-verification.json`. The world was saved with `save-all flush`.
@@ -1,29 +0,0 @@
{
"capturedAt": "2026-09-12T20:10:04.926155338Z",
"dimension": "minecraft:overworld",
"x": 0.0,
"y": -20.0,
"z": -63.0,
"eyeY": -18.380000114440918,
"yaw": 25.0,
"pitch": 16.0,
"fov": 85,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 21,
"stabilizationFrames": 3,
"afterOperationId": "682bb5bb-a1fe-4359-b687-06f7b1ce1005",
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "aa1dbef8-47f1-4985-b505-0bcc79e604b7",
"imageSha256": "b1dfd2fd671c20d7a0e4fd225843695a522f93a194cea18bfa313297e303774a",
"imageBytes": 670102,
"elapsedSeconds": 1.367,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 KiB

@@ -1,29 +0,0 @@
{
"capturedAt": "2026-09-12T20:42:08.334749638Z",
"dimension": "minecraft:overworld",
"x": 0.0,
"y": -20.0,
"z": -63.0,
"eyeY": -18.380000114440918,
"yaw": 25.0,
"pitch": 16.0,
"fov": 85,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 24,
"stabilizationFrames": 3,
"afterOperationId": "e7f0371d-e64c-48e0-86ae-13ac813dab98",
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "c219512d-ce8a-4e75-ba24-77e470abb061",
"imageSha256": "bbefeae9f00e33adbda3a98fa85c91fae43d2590339a6036b0a352ddd75f7a7a",
"imageBytes": 813940,
"elapsedSeconds": 2.063,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
@@ -1,29 +0,0 @@
{
"capturedAt": "2026-09-12T20:40:31.617476861Z",
"dimension": "minecraft:overworld",
"x": 0.0,
"y": -20.0,
"z": -63.0,
"eyeY": -18.380000114440918,
"yaw": 25.0,
"pitch": 16.0,
"fov": 85,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 24,
"stabilizationFrames": 3,
"afterOperationId": "e7f0371d-e64c-48e0-86ae-13ac813dab98",
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "c1ac75c3-f21e-484e-be35-d783790cdeae",
"imageSha256": "637bd82eb213ed609cbc1625e62fec96858218df000f18998e22c96294222dfa",
"imageBytes": 677364,
"elapsedSeconds": 2.019,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 662 KiB

@@ -1,29 +0,0 @@
{
"capturedAt": "2026-09-12T20:37:56.024582621Z",
"dimension": "minecraft:overworld",
"x": -31.0,
"y": -51.0,
"z": -29.0,
"eyeY": -49.38000011444092,
"yaw": 0.0,
"pitch": -8.0,
"fov": 70,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 21,
"stabilizationFrames": 3,
"afterOperationId": "e7f0371d-e64c-48e0-86ae-13ac813dab98",
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "8c11e828-4678-40ee-8037-91dd50f11ec9",
"imageSha256": "4587c6169b11f94044bb46daea310d8d02f4ff1980106c896fc82298c656e516",
"imageBytes": 875403,
"elapsedSeconds": 1.478,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 855 KiB

Before

Width:  |  Height:  |  Size: 795 KiB

After

Width:  |  Height:  |  Size: 795 KiB

-201
View File
@@ -1,201 +0,0 @@
{
"schema_version": 1,
"kind": "design_reference_catalog",
"reviewed_on": "2026-09-13",
"project": "Shacraft lobby",
"status": "Original design proposals; not executable build_prepare recipes and not newly built or playtested.",
"units": "Dimensions are width (X), height (Y), depth (Z) in blocks. Envelopes exclude separately specified circulation and buried support. Front is -Z; +Z points into the object. Adapt to surveyed world coordinates and rotate directional block states with the geometry.",
"capability_basis": "Material names checked against the saved Stage 07 project_context palette on 2026-09-13. Re-read live project_context before building. Material availability does not validate states, placement support or geometry.",
"source_notes": "source_ids identify conceptual inspiration. All dimensions, placement sequences and Shacraft adaptations below are original proposals, not source schematics.",
"sources": [
{"id":"S01","title":"Interior Motives","url":"https://www.minecraft.net/en-us/article/interior-motives","use":"Purposeful interiors and agreement between interior and exterior architecture."},
{"id":"S02","title":"Tranquil Towers","url":"https://www.minecraft.net/en-us/article/tranquil-towers","use":"Develop roof shape and silhouette before details."},
{"id":"S03","title":"The Sky is No Limit","url":"https://www.minecraft.net/en-us/article/sky-no-limit","use":"Consistent palette and simple textures for a large composition."},
{"id":"S04","title":"Taking Inventory: Glass Pane","url":"https://www.minecraft.net/en-us/article/taking-inventory--glass-pane","use":"Window depth; our sealed variant uses recessed full glass."},
{"id":"S05","title":"Build With It: Quartz","url":"https://www.minecraft.net/en-us/article/build-with-it--quartz","use":"A pale material family can connect architecture and furnishings."},
{"id":"S06","title":"Fantastic Furniture","url":"https://www.minecraft.net/en-us/article/fantastic-furniture","use":"Habitable furniture groups and independently finished partition faces."},
{"id":"S07","title":"Cozy Chambers","url":"https://www.minecraft.net/en-us/article/cozy-chambers","use":"Wood, plants and lighting soften stone and copper interiors."},
{"id":"S08","title":"Block of the Month: Decorated Pot","url":"https://www.minecraft.net/en-us/article/decorated-pot","use":"Flowerpot above decorated pot is a future material option, not supported by the current palette."},
{"id":"S09","title":"Tutorial: Tips For Landscaping and Terraforming","url":"https://www.minecraft.net/en-us/article/tutorial--tips-for-landscaping-and-terraforming","use":"BlueNerd: connect paths, banks, vegetation and shaped terrain."},
{"id":"S10","title":"Five simple path designs","url":"https://www.minecraft.net/en-us/article/five-simple-path-designs","use":"Zaypixel: route materials and nearby objects communicate place."},
{"id":"S11","title":"Tutorial: Cottagecore Decor","url":"https://www.minecraft.net/en-us/article/tutorial--cottagecore-decor","use":"Kelpie the Fox: outdoor places to rest; reference uses Mizuno's 16 Craft."},
{"id":"S12","title":"Taking Inventory: Lantern","url":"https://www.minecraft.net/en-us/article/taking-inventory--lantern","use":"Lanterns as recurring fixtures; historical spawning advice is not used."},
{"id":"S13","title":"Build With It: Cobblestone!","url":"https://www.minecraft.net/en-us/article/build-with-it--cobblestone-","use":"Moss and vegetation can suggest age in masonry."},
{"id":"S14","title":"Caves & Cliffs: Part I out today on Java","url":"https://www.minecraft.net/en-us/article/caves---cliffs--part-i-out-today-java","use":"Waxed copper, tinted glass light blocking, and introduced decorative blocks."},
{"id":"S15","title":"Minecraft Java Edition 1.21.5: Spring to Life","url":"https://feedback.minecraft.net/hc/en-us/articles/35298208390797-Minecraft-Java-Edition-1-21-5-Spring-to-Life","use":"New plant orientations/densities and low-emission firefly bushes; not current MCP capabilities."},
{"id":"S16","title":"Build with It: Diorite!","url":"https://www.minecraft.net/en-us/article/build-it--diorite-","use":"Texture intensity matters; polished variants can produce calmer surfaces."},
{"id":"S17","title":"Minecraft Java Edition 26.2","url":"https://www.minecraft.net/en-us/article/minecraft-java-edition-26-2","use":"Current game has additional material families; game availability is distinct from MCP support."}
],
"recipes": [
{
"id":"arched-window-bay","category":"facade","name":"Recessed arched window bay",
"size":{"width":7,"height":10,"depth":3},
"purpose":"Give a large cream facade readable shadow and a consistent structural rhythm.",
"materials":["minecraft:smooth_sandstone","minecraft:cut_sandstone","minecraft:smooth_sandstone_stairs","minecraft:smooth_sandstone_slab","minecraft:smooth_quartz","minecraft:brown_stained_glass"],
"steps":["Reserve a seven-wide bay between the actual structural axes; keep adjacent columns and floor decks intact.","At the glazing plane, use five-wide glass rows for the straight portion, then three and one at the crown. Fill every surrounding cell with full masonry so the plane stays sealed.","Place glazing one block behind the front wall plane; use the remaining front depth for a sill and paired jamb brackets.","Use sandstone stairs only as outer trim. Maintain full masonry or full glass behind partial-block trim.","Repeat the approved bay on the established grid; redesign corners and the main doorway deliberately."],
"clearance":"Keep projections outside the existing public route and its four-block headroom; do not narrow the seven-block station entry.",
"variants":["Plain rectangular head on a secondary facade.","One gold accent above the principal entrance only."],
"acceptance":["Closure plane has no unfilled cells, including arch shoulders.","Recess reads from a diagonal player-height camera.","No sill hides a sign or clips furniture.","Stair rotation and corner shape checked after neighboring blocks update."],
"avoid":["Different window silhouettes in every bay.","Assuming a pane or stair is a full containment wall."],
"source_ids":["S03","S04","S05"]
},
{
"id":"cornice-bracket","category":"facade","name":"Cornice and paired bracket",
"size":{"width":9,"height":3,"depth":2},
"purpose":"Explain the floor/eave line without filling the wall with ornament.",
"materials":["minecraft:smooth_sandstone","minecraft:smooth_sandstone_stairs","minecraft:smooth_sandstone_slab","minecraft:smooth_quartz"],
"steps":["Place a continuous stone band on the existing floor or eave line.","Use an inverted-stair underside and a thin slab cap, with at most two blocks of total outward depth.","Put the two bracket groups over structural supports and leave the central field quiet.","Continue the band around corners with an explicitly resolved return; prototype the corner before repeating."],
"clearance":"Remain above route headroom and outside signs' viewing rays; preserve roof drainage shapes and window tops.",
"variants":["Single-block projection on small wings.","A stronger cap at the tower base, using the same materials."],
"acceptance":["Horizontal band remains readable from the main approach.","Brackets align with actual supports.","Cap does not overwhelm the window opening."],
"avoid":["A thick shelf over every horizontal edge.","Unrelated gold trim on every bracket."],
"source_ids":["S02","S03","S05"]
},
{
"id":"closed-dormer","category":"roof","name":"Closed green-copper dormer",
"size":{"width":7,"height":7,"depth":7},
"purpose":"Add a secondary roof feature while keeping the clock tower dominant.",
"materials":["minecraft:smooth_sandstone","minecraft:brown_stained_glass","minecraft:waxed_oxidized_cut_copper","minecraft:waxed_oxidized_cut_copper_stairs","minecraft:waxed_oxidized_cut_copper_slab"],
"steps":["Fit a seven-wide sample to the actual roof pitch; use cream side cheeks and three-wide recessed glass.","Build the green pitched cap with a one-block overhang.","Keep a solid back and floor closure behind the apparent window; retain the existing public ceiling.","Test one dormer from the main approach before any repetition. Consider 14-18 blocks between centers only where the measured structural grid permits it."],
"clearance":"No opening into an unfinished attic, no overlap with tower faces or main roof ridge.",
"variants":["One larger central feature on a secondary wing.","Omit the dormer if it competes with the clock silhouette."],
"acceptance":["Tower remains the primary skyline feature.","Quiet copper roof planes remain visible between details.","Full closure survives the added roof cutout."],
"avoid":["Treating proposed spacing as a universal rule.","Adding attic access as part of a cosmetic edit."],
"source_ids":["S02","S03"]
},
{
"id":"waiting-pocket","category":"interior","name":"Paired waiting benches",
"size":{"width":9,"height":4,"depth":7},
"purpose":"Create a believable place to wait beside the main hall.",
"materials":["minecraft:spruce_stairs","minecraft:spruce_slab","minecraft:spruce_planks","minecraft:smooth_sandstone","minecraft:green_concrete","minecraft:lantern","minecraft:oak_leaves","minecraft:dirt"],
"steps":["Place two three-seat spruce benches facing a shared open pocket, with cream end supports.","Keep a compact table at one side rather than on the main desire line.","Use a flush green paving inset to group the furniture; this substitutes for unsupported carpet.","Add one planter and one supported lantern near the back, leaving the front visually open."],
"clearance":"Reserve an additional three-block-wide clear passing strip and four blocks of route headroom. Existing wider routes retain their width.",
"variants":["Single bench and planter in a smaller side recess.","Mirror the group around the room axis while varying the small prop."],
"acceptance":["Lift sign remains visible from the approach.","Seat fronts and table can be approached without stepping onto furniture.","Lamp and leaves remain stable after updates."],
"avoid":["Rows of isolated decorative chairs.","Plants in front of navigation signs."],
"source_ids":["S01","S06","S07"]
},
{
"id":"information-counter","category":"interior","name":"Information counter",
"size":{"width":9,"height":5,"depth":4},
"purpose":"Provide a clear information point that belongs in a station.",
"materials":["minecraft:spruce_planks","minecraft:spruce_slab","minecraft:smooth_sandstone","minecraft:smooth_sandstone_slab","minecraft:green_concrete","minecraft:glowstone","minecraft:brown_stained_glass"],
"steps":["Frame a seven-block counter between cream end piers; use spruce body and a thin cream slab top.","Align one green sign backing and one lit recess behind the counter.","Keep the back wall solid. Any future staff door remains a finished wall panel until the room exists.","Add actual text only through an existing authorized label mechanism; the block catalog does not create text entities."],
"clearance":"Reserve three clear queue blocks in front, separated from the entrance-to-lift route and its full width.",
"variants":["Short five-wide counter for a side room.","A small gold emblem only above the principal information point."],
"acceptance":["Queue does not cross the main route.","Counter is recognizable before reading the sign.","No false usable door into unfinished space."],
"avoid":["Several equally bright competing headers.","Claiming matchmaking or staff interaction exists merely because the counter is built."],
"source_ids":["S01","S05","S06"]
},
{
"id":"smash-exhibit","category":"interior","name":"SMASH exhibit niche",
"size":{"width":7,"height":6,"depth":5},
"purpose":"Communicate floating islands and knockback through one readable display.",
"materials":["minecraft:deepslate","minecraft:smooth_sandstone","minecraft:green_concrete","minecraft:gold_block","minecraft:grass_block","minecraft:dirt","minecraft:glowstone","minecraft:brown_stained_glass"],
"steps":["Build a full dark base, full back and light stone frame around a five-wide exhibit.","Choose one miniature island or one abstract impact motif as the subject.","Put one small gold focal detail near the subject and keep the rest of the frame consistent with adjacent niches.","Light the subject from concealed side, base or overhead recesses; preserve full-block base and closure.","Use one shared frame for all six future arena places; vary the subject and real destination text only when available."],
"clearance":"Reserve a three-block viewing strip outside the main circulation aisle; preserve the existing selection aisle.",
"variants":["Closed trophy pedestal with a single object.","Small landscape model for a future named arena."],
"acceptance":["Subject is legible from player eye level without entering the display.","No dark face hides the model's silhouette.","Placeholders clearly remain unassigned."],
"avoid":["Six unrelated palettes.","A visual void that is also an accidental physical hole."],
"source_ids":["S01","S06","S07"]
},
{
"id":"avenue-edge","category":"path","name":"Formal avenue edge",
"size":{"width":9,"height":1,"depth":12},
"purpose":"Connect station stonework to the garden through a continuous legible route.",
"materials":["minecraft:stone_bricks","minecraft:smooth_stone","minecraft:smooth_sandstone","minecraft:mossy_stone_bricks"],
"steps":["Keep seven center columns as continuous clear paving and one flush border column on each side.","Survey elevations along the whole segment before decoration; grade transitions as separate geometry.","Place furniture in additional two-to-three-block shoulders or wider pockets, not inside the nine-block strip.","Keep the station approach clean. Introduce small connected worn patches at outer edges beside planting.","Widen at entrances and follow actual destinations rather than adding arbitrary bends."],
"clearance":"Seven-block clear walking width and four-block headroom; this example must not narrow a wider established route.",
"variants":["Use local gray stone farther from the station.","Curve the outer border while keeping the tread continuous."],
"acceptance":["Entire route walkable at all grade changes.","Flush borders do not introduce a lip.","No lamp or planter creates a pinch point."],
"avoid":["Uniform random scatter of five paving materials.","Applying an organic-path zigzag rule to a formal station axis."],
"source_ids":["S09","S10","S13"]
},
{
"id":"copper-lantern","category":"lighting","name":"Supported copper-arm lantern",
"size":{"width":3,"height":7,"depth":1},
"purpose":"Establish one recognizable outdoor fixture family.",
"materials":["minecraft:stone_bricks","minecraft:stripped_spruce_log","minecraft:waxed_oxidized_cut_copper","minecraft:iron_chain","minecraft:lantern"],
"steps":["With the sample's first above-ground cell at y=0, place a full stone foot at (0,0,0), rooted into surveyed ground below.","Raise a post at x=0,z=0 through y=1..5; place a full-block copper arm across x=0..2 at y=6.","Place a vertical iron chain at (2,5,0) attached beneath the full arm, then a hanging lantern at (2,4,0).",
"Place support before attached details and inspect resulting block states.","Keep the entire post outside the clear path; use a mirrored pair only at a major entry."],
"clearance":"Four empty cells below the hanging lantern if ground is level with the sample. Recalculate for actual terrain; do not assume the same clearance over a rising stair.",
"variants":["Shorter ground-mounted fixture in a planted pocket with no walk-under route.","One gold marker at a major junction, outside this base recipe."],
"acceptance":["Full arm, chain axis and hanging lantern state remain valid after updates.","Night view shows the next step, intersection and sign between lamps.","Post cannot be used to bypass an existing containment boundary."],
"avoid":["Unsupported lanterns.","Treating a fixed lamp spacing as guaranteed illumination coverage."],
"source_ids":["S11","S12","S14"]
},
{
"id":"layered-planter","category":"planting","name":"Layered planting pocket",
"size":{"width":7,"height":6,"depth":5},
"purpose":"Produce a planted mass with a readable front, middle and background.",
"materials":["minecraft:dirt","minecraft:grass_block","minecraft:spruce_log","minecraft:spruce_leaves","minecraft:oak_leaves","minecraft:white_tulip","minecraft:pink_tulip","minecraft:oxeye_daisy","minecraft:smooth_sandstone"],
"steps":["Shape a low cream rim with solid soil behind it; support the entire pocket down to the existing terrain.","Put one small rooted tree toward the rear and two unequal shrub groups below it.","Use one dominant foliage species and two restrained flower colors near the front.","Leave patches of visible grass between groups; taper density toward the edge.","Save a seed and cluster anchors for repeatable variation; change group positions rather than every block independently."],
"clearance":"Keep the highest mass outside entrance and sign sightlines; no leaves overhang the protected walking clearance.",
"variants":["Formal clipped evergreen beside the station.","Looser shrubs without a tree beside the mountain path."],
"acceptance":["Flowers have valid soil.","Leaves use persistent=true and a stable read-back distance state.","Trunk has stable soil under it.","Foliage tint checked in the actual biome."],
"avoid":["A flower on every grass block.","Using leaves as the only containment boundary."],
"source_ids":["S07","S09","S11"]
},
{
"id":"shore-pocket","category":"landscape","name":"Quiet shore with a stony recess",
"size":{"width":12,"height":4,"depth":8},
"purpose":"Connect existing water and terrain with a believable local bank.",
"materials":["minecraft:stone","minecraft:andesite","minecraft:cobblestone","minecraft:mossy_cobblestone","minecraft:dirt","minecraft:grass_block","minecraft:oak_leaves"],
"steps":["Sample a short existing shoreline together with its water level and submerged bed.","Shape one quiet bank and one small stony recess; maintain continuous ground beneath the visible soil skin.","Put exposed rock at the outcrop and moss only in selected damp recesses.","Keep vegetation in sheltered land pockets and leave a clear view of the water.","This catalog specifies only land-side decor. Preserve water cells and the connected bed; stop if execution requires fluid placement or an unsupported brush through water."],
"clearance":"Preserve public route width, foundations, water level and any existing waterfront containment.",
"variants":["Grass bank with one isolated outcrop.","Stone recess beside a retaining wall, without changing its footing."],
"acceptance":["Water network and visible level preserved.","No new flow reaches a road or foundation after updates.","A below-water view shows a continuous bed; top-down appearance alone is insufficient."],
"avoid":["Repeating identical coves as tiles.","Assuming water exists in the MCP material palette."],
"source_ids":["S09","S13"]
},
{
"id":"retaining-stair","category":"path","name":"Retaining wall and short stair",
"size":{"width":9,"height":5,"depth":10},
"purpose":"Make a grade change feel supported and intentionally connected.",
"materials":["minecraft:stone_bricks","minecraft:stone_brick_stairs","minecraft:stone_brick_slab","minecraft:smooth_sandstone","minecraft:smooth_sandstone_slab","minecraft:mossy_stone_bricks","minecraft:dirt"],
"steps":["Survey lower and upper approaches first; adapt the proposed envelope to the actual rise.","Reserve five clear stair columns and two shoulder columns per side.","Use three or four one-block rises followed by a three-block-deep landing; fill every tread and retaining wall down to solid ground.","Return the side walls into the upper terrace instead of ending them as disconnected pillars.","Keep the cream cap continuous; limit moss to local soil-contact or shaded recesses."],
"clearance":"Five clear stair blocks and four-block headroom along the full ascending path, including caps and any overhead fixture.",
"variants":["A shorter flight for a lower terrace.","An additional landing and separate second flight when the actual rise requires it."],
"acceptance":["Stair facing matches direction of ascent.","Approach and landing elevations agree with the survey.","No hollow exposed underside or unsupported cap.","Shoulders do not create a climb-over route around containment."],
"avoid":["Solving a height mismatch with a decorative slab at the doorway.","Placing a standard stair module without measuring the destination."],
"source_ids":["S09","S10","S13"]
},
{
"id":"luggage-bench","category":"props","name":"Bench and luggage group",
"size":{"width":7,"height":3,"depth":4},
"purpose":"Tell a station story with a small, useful-looking prop group.",
"materials":["minecraft:spruce_stairs","minecraft:spruce_planks","minecraft:stripped_spruce_log","minecraft:smooth_sandstone","minecraft:green_concrete","minecraft:gold_block"],
"steps":["Put a three-seat bench against the back of a widened pocket, facing the plaza.","Group two wood-toned luggage shapes at one end, leaving seat fronts clear.","Reserve a green backing for one real destination or station identity plaque.","Use at most one small metallic accent in the group; omit it if it attracts more attention than the navigation."],
"clearance":"Provide a separate three-block passing strip in front and preserve any wider existing route.",
"variants":["Bench alone.","Bench with one planter instead of luggage."],
"acceptance":["Object reads as a resting place from the walking path.","Luggage does not intrude into the bench approach.","No label advertises an unfinished accessible destination."],
"avoid":["Crates in every empty corner.","Unsupported decorative item entities or invented text APIs."],
"source_ids":["S01","S06","S10"]
},
{
"id":"concealed-light-lens","category":"lighting","name":"Full-block concealed light lens",
"size":{"width":3,"height":2,"depth":3},
"purpose":"Illuminate a large room without adding a hanging fixture to every bay.",
"materials":["minecraft:glowstone","minecraft:brown_stained_glass","minecraft:smooth_sandstone"],
"steps":["Reserve a three-by-three floor sample outside patterned paving, tree roots, landings and interactive controls.","Keep full paving in the eight perimeter columns; in the center put glowstone below a full brown stained-glass block flush with the walking surface.","Keep supporting construction below the sample intact and record expected states before replacement.","Prototype one lens; increase coverage only after matching night and interior photographs reveal dark areas.","A ceiling variant reverses the emitter and visible lens positions within an intact full-block ceiling."],
"clearance":"Top of the floor lens remains flush. Ceiling version preserves all existing route headroom and sealed upper rooms.",
"variants":["Use ordinary full glass if the brown lens makes the sample too dark.","Concealed side lighting for an exhibit rather than more floor lights."],
"acceptance":["Full-block collision remains at the floor/ceiling surface.","Actual captured room and exhibit faces become legible.","No new bright fixture competes with the entrance or lift."],
"avoid":["Tinted glass: it blocks light and is not interchangeable with stained glass.","Assuming more fixtures automatically produce a better interior."],
"source_ids":["S07","S14"],
"local_precedent":"Stage 07 used concealed brown-glass lighting and real camera review; this reusable sample has not itself been instantiated."
},
{
"id":"masonry-weathering","category":"surface","name":"Cause-based masonry weathering",
"size":{"width":12,"height":6,"depth":1},
"purpose":"Add age and material variation while retaining large calm wall fields.",
"materials":["minecraft:stone_bricks","minecraft:cracked_stone_bricks","minecraft:mossy_stone_bricks","minecraft:andesite","minecraft:smooth_sandstone","minecraft:cut_sandstone"],
"steps":["Choose either the gray retaining-wall family or the cream facade family; do not mix both randomly.","Save a mask for soil contact, sheltered joints and selected worn edges.","For gray masonry, use small connected mossy patches in the mask and a few connected cracked areas away from structural focal edges.","For cream masonry, keep the field mostly smooth and use cut sandstone to express masonry bands or quiet local variation; do not add green flecks everywhere.","Preserve trim, signs and dominant shapes, then inspect at near, approach and whole-building distances."],
"clearance":"Surface substitution only; preserve structural collision, public closure and existing manual edits.",
"variants":["Clean maintained station entrance with minimal weathering.","More aged retaining wall near shaded soil contact."],
"acceptance":["Weathering locations have a visible cause.","Large forms still read from the approach.","Exact seed and patch anchors recorded for reproducibility."],
"avoid":["Independent random choice at every voxel.","A universal percentage of damage on every material.","Replacing load-bearing full cubes with stairs merely for texture."],
"source_ids":["S03","S13","S16"]
}
]
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

-16
View File
@@ -1,16 +0,0 @@
Generated using the built-in image_gen tool.
Concept reference for minecraft-builder-mcp; not an in-game screenshot or a dimensioned construction plan.
Use case: stylized-concept.
Asset type: architectural reference for a substantial building we will later construct in Minecraft Java.
Primary request: one impressive but realistically buildable Gothic civic guildhall / town hall, significantly larger and more sophisticated than a small watchtower.
Subject: a coherent single building with a long three-storey great hall, a steep dark gabled roof, a prominent square bell tower with a tall pointed roof, a lower connected side wing and an entrance stair. Approximately 65 by 45 Minecraft blocks in footprint, highest tower around 55 blocks; communicate substantial scale through believable block sizes. Strong readable silhouette and balanced architectural hierarchy. The front has a deep pointed-arch entrance and a restrained series of tall, narrow RECESSED windows with stone jambs and lintels. Glass sits inside thick masonry: absolutely no protruding glass boxes. A few recessed paired lancet windows on the great hall. Buttresses, structural masonry, layered cornices and roofs made of explicit block steps; purposeful details with some calm wall areas. The attached wing and tower must visibly connect to usable interior volumes.
Style/medium: beautiful high-quality Minecraft voxel architectural concept render, faithful cubic full-block, stair and slab construction at consistent voxel scale, crisp recognisable vanilla-like pixel textures. All edges obey the Minecraft grid. Not a smooth realistic European building with a token pixel filter.
Materials: predominantly grey stone bricks with restrained polished andesite and light stone trim, dark deepslate stair/slab roofs, dark oak and spruce for doors and inset timber features, dark glass deep in the walls. Restrained palette; strong depth and masonry shadows, no random patchwork.
Scene: the complete building stands on a small paved terrace at ground level, with minimal grass terrain and a quiet pale sky. Sparse setting keeps the architecture fully readable.
Composition: a single landscape image, elevated front three-quarter architectural view showing the entrance, long side facade, roof structure and tower; the full building and entire highest roof are inside the frame with breathing room. Moderate perspective, no fisheye. Building fills most of the composition.
Lighting: clear soft daylight with warm sunlight, readable shadow detail; avoid night, fog or overexposure.
Avoid: people, mobs, UI, HUD, captions, labels, text, watermarks, logos, floating islands, mountains obscuring the building, sprawling cities, enormous fantasy spires, excessive clutter or unbuildable smooth curves.
Generate a brand-new standalone reference, not an edit or screenshot of an existing build.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1010 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

@@ -1,589 +0,0 @@
{
"stage": "03-arrival-garden",
"writes": 4811,
"batches": 12,
"final_distinct_changed_blocks": 4734,
"actual_block_checks": {
"version": 1,
"mode": "actual_after_snapshot",
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"world_edits": 0,
"desired_blocks": 4734,
"baseline_expected_states_verified": 4734,
"actual_exact_state_mismatches": 0,
"actual_mismatch_examples": [],
"fixtures": {
"passed": true,
"checked": {
"leaves": 537,
"lanterns": 16,
"flowers": 258,
"rooted_trees": 12,
"root_connected_logs": 73
},
"failures": []
},
"walking": {
"checked_points": 4955,
"checked_route_edges": 0,
"failures": [],
"passed": true,
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"note": "Observed surface samples and vertical headroom; full cubes, slabs and explicit straight bottom-stair samples. Stair samples are a surface profile, not a full player-width collision simulation. Cached snapshot is not a live re-read."
},
"navigation": {
"version": 1,
"source": {
"x": 0,
"z": 9
},
"world_edits": 0,
"method": "Four quarter-center surface samples per clear cell; cardinal half-block BFS, rise/drop <= 0.5 block.",
"limitations": "Planned surface topology only. No headroom, body-width collision, material state or live-world verification. Width checks are cardinal cross-sections using the dominant local tangent; full declared masks are also checked.",
"geometry_sha256": "b58820302ac02852731c49ac482b0b6684b2aa7fe319d7e9dfc3d8374c972491",
"planned_columns": 16309,
"clear_columns": 14478,
"surface_samples": 57912,
"reachable_samples": 57912,
"unreachable_clear_columns": [],
"unreachable_by_group": {},
"station": {
"name": "clock-station",
"x": -6,
"z": -105,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 119.0
},
"routes": [
{
"id": "station-axis",
"passed": true,
"declared_clear_width": 9,
"corridor_columns": 593,
"missing_corridor_columns": [],
"declared_clear_columns": 486,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 47,
"minimum_structural_cross_section": 9,
"minimum_clear_cross_section": 9,
"minimum_reachable_cross_section": 9,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0,
"centerline_jumps": [],
"endpoints": [
{
"name": "station-axis:start",
"x": 0,
"z": -37,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "station-axis:end",
"x": -6,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 91.0
}
]
},
{
"id": "south-axis-local",
"passed": true,
"declared_clear_width": 9,
"corridor_columns": 685,
"missing_corridor_columns": [],
"declared_clear_columns": 565,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 59,
"minimum_structural_cross_section": 9,
"minimum_clear_cross_section": 9,
"minimum_reachable_cross_section": 9,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "south-axis-local:start",
"x": 0,
"z": 57,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 48.0
},
{
"name": "south-axis-local:end",
"x": 1,
"z": 110,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 102.0
}
]
},
{
"id": "portal-radial-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 531,
"missing_corridor_columns": [],
"declared_clear_columns": 376,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 70,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "portal-radial-local:start",
"x": -35,
"z": -14,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 57.0
},
{
"name": "portal-radial-local:end",
"x": -72,
"z": -46,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 126.0
}
]
},
{
"id": "lake-radial-local",
"passed": true,
"declared_clear_width": 5,
"corridor_columns": 403,
"missing_corridor_columns": [],
"declared_clear_columns": 297,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 63,
"minimum_structural_cross_section": 5,
"minimum_clear_cross_section": 5,
"minimum_reachable_cross_section": 5,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "lake-radial-local:start",
"x": -42,
"z": 18,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 50.5
},
{
"name": "lake-radial-local:end",
"x": -90,
"z": 32,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 112.5
}
]
},
{
"id": "east-radial-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 451,
"missing_corridor_columns": [],
"declared_clear_columns": 341,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 49,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "east-radial-local:start",
"x": 42,
"z": 16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 49.0
},
{
"name": "east-radial-local:end",
"x": 82,
"z": 8,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 90.5
}
]
},
{
"id": "ring-northwest-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 468,
"missing_corridor_columns": [],
"declared_clear_columns": 350,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 53,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "ring-northwest-local:start",
"x": -40,
"z": -65,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 113.0
},
{
"name": "ring-northwest-local:end",
"x": -80,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 165.0
}
]
},
{
"id": "ring-northeast-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 505,
"missing_corridor_columns": [],
"declared_clear_columns": 374,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 60,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "ring-northeast-local:start",
"x": 40,
"z": -95,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 151.0
},
{
"name": "ring-northeast-local:end",
"x": 82,
"z": -78,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 210.0
}
]
},
{
"id": "station-entrance-stair",
"passed": true,
"declared_clear_width": 21,
"corridor_columns": 161,
"missing_corridor_columns": [],
"declared_clear_columns": 147,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 7,
"minimum_structural_cross_section": 21,
"minimum_clear_cross_section": 21,
"minimum_reachable_cross_section": 21,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "station-entrance-stair:start",
"x": -6,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 91.0
},
{
"name": "station-entrance-stair:end",
"x": -6,
"z": -83,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 97.0
}
]
}
],
"passed": true,
"decorated_ground_columns_excluded": 662,
"bench_front_access": [
{
"name": "bench--17--17-front--1",
"x": -16,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.0
},
{
"name": "bench--17--17-front-0",
"x": -17,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 41.0
},
{
"name": "bench--17--17-front-1",
"x": -18,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 42.0
},
{
"name": "bench-17--17-front--1",
"x": 18,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 42.5
},
{
"name": "bench-17--17-front-0",
"x": 17,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 41.5
},
{
"name": "bench-17--17-front-1",
"x": 16,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.5
},
{
"name": "bench--32-2-front--1",
"x": -31,
"z": 1,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 38.0
},
{
"name": "bench--32-2-front-0",
"x": -31,
"z": 2,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 37.0
},
{
"name": "bench--32-2-front-1",
"x": -31,
"z": 3,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 36.0
},
{
"name": "bench-32-2-front--1",
"x": 31,
"z": 3,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 36.5
},
{
"name": "bench-32-2-front-0",
"x": 31,
"z": 2,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 37.5
},
{
"name": "bench-32-2-front-1",
"x": 31,
"z": 1,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 38.5
},
{
"name": "bench--22-35-front--1",
"x": -23,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 47.5
},
{
"name": "bench--22-35-front-0",
"x": -22,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.5
},
{
"name": "bench--22-35-front-1",
"x": -21,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "bench-22-35-front--1",
"x": 21,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.0
},
{
"name": "bench-22-35-front-0",
"x": 22,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 47.0
},
{
"name": "bench-22-35-front-1",
"x": 23,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 48.0
}
]
},
"passed": true,
"note": "Static support, leaf-distance and point-sampled navigation checks; not a complete moving-player collision simulation. Actual mode uses sequential observed snapshots.",
"input_sha256": {
"before": "770a08974e5bf9793c56be780576947dcceb2cd5b8400f479a5356e8509b3146",
"layout": "699060010db084dc05c47400572ac4440784d1a0c3dbd877122decd183048923",
"metadata": "400f672864117b62ed173600932ca04ab15a0c548587bb3d39f34eaa91484e89",
"walk": "453c5ee1e699a59be845db22abc5e481915768ab229a79c0cc6019d8b3e39d0d",
"navigation": "1baf3c4ef2c1ddfca22240395fcde97b5210d97c9afe5cb2b6c3275154cfe044",
"after": "5310988e559868a7e18a98d2e951d87e789798d6a1027df491ede65bb4bcdff8"
}
},
"actual_surface_checks": {
"version": 1,
"world": "shacraft_lobby_v2",
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"source": "Full live Paper surface maps plus observed baseline voxels and desired edit overlay",
"verified_surface_columns": 589824,
"affected_columns": 2823,
"outside_edit_columns_verified": 587001,
"changed_surface_columns": 2680,
"surface_mismatches": 0,
"outside_edit_surface_mismatches": 0,
"mismatch_examples": [],
"original_visible_water_columns": 41467,
"visible_water_surface_changes": 0,
"water_surface_change_examples": [],
"expected_states_checked_against_baseline": 4734,
"placed_or_replaced_voxels": 4702,
"removed_voxels": 32,
"lower_snapshot_voxels_consulted_after_cuts": 12,
"observed_water_voxels_replaced": [],
"water_preservation_passed": true,
"passed": true,
"capture_started_at": "2026-09-13T02:35:54.623721211Z",
"capture_finished_at": "2026-09-13T02:37:49.861979626Z",
"atomic_snapshot": false,
"note": "Sequential map captures; edits must be idle during each capture. This checks every visible surface and the observed water blocks in the edit. Hidden untouched blocks outside the voxel survey are not inferred. Live voxel and headroom checks are separate.",
"inputs_sha256": {
"before_map": "25b7eb12af89e0f9931a56f31cc8eca952b817a34218ffdc4fbf3636e1a3e917",
"after_map": "d0dde2583dfbb2f5b37b45a2d1cd5c239b8bfd2e72d4c1434ac280e99f8ed2af",
"baseline_voxels": "770a08974e5bf9793c56be780576947dcceb2cd5b8400f479a5356e8509b3146",
"desired_layout": "699060010db084dc05c47400572ac4440784d1a0c3dbd877122decd183048923"
}
},
"camera_readiness": "Real Fabric frames; heuristic render readiness, server block state verified separately."
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

@@ -1,695 +0,0 @@
{
"version": 1,
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"mode": "actual_after_snapshot",
"passed": true,
"world_edits": 0,
"desired_blocks": 710,
"guard": {
"passed": true,
"columns": 302,
"piers": 46,
"cardinal_components": [
31,
46,
71,
74,
80
],
"grounded_footings": 22,
"adjacent_road_rails": 6,
"failures": []
},
"protected_road_columns": 2927,
"protection_failures": [],
"preserved_fixture_states": 1172,
"lost_fixtures": [],
"fixtures": {
"passed": true,
"checked": {
"leaves": 537,
"lanterns": 16,
"flowers": 258,
"rooted_trees": 12,
"root_connected_logs": 73
},
"failures": []
},
"walking": {
"checked_points": 4815,
"checked_route_edges": 0,
"failures": [],
"passed": true,
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"note": "Observed surface samples and vertical headroom; full cubes, slabs and explicit straight bottom-stair samples. Stair samples are a surface profile, not a full player-width collision simulation. Cached snapshot is not a live re-read."
},
"navigation": {
"version": 1,
"source": {
"x": 0,
"z": 9
},
"world_edits": 0,
"method": "Four quarter-center surface samples per clear cell; cardinal half-block BFS, rise/drop <= 0.5 block.",
"limitations": "Planned surface topology only. No headroom, body-width collision, material state or live-world verification. Width checks are cardinal cross-sections using the dominant local tangent; full declared masks are also checked.",
"geometry_sha256": "4a2b951946c91a09dcef9606bfebd8eba51c34f21e827b019dc0a5f768cf4148",
"planned_columns": 16309,
"clear_columns": 14338,
"surface_samples": 57352,
"reachable_samples": 57352,
"unreachable_clear_columns": [],
"unreachable_by_group": {},
"station": {
"name": "clock-station",
"x": -6,
"z": -105,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 119.0
},
"routes": [
{
"id": "station-axis",
"passed": true,
"declared_clear_width": 9,
"corridor_columns": 593,
"missing_corridor_columns": [],
"declared_clear_columns": 486,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 47,
"minimum_structural_cross_section": 9,
"minimum_clear_cross_section": 9,
"minimum_reachable_cross_section": 9,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0,
"centerline_jumps": [],
"endpoints": [
{
"name": "station-axis:start",
"x": 0,
"z": -37,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "station-axis:end",
"x": -6,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 91.0
}
]
},
{
"id": "south-axis-local",
"passed": true,
"declared_clear_width": 9,
"corridor_columns": 685,
"missing_corridor_columns": [],
"declared_clear_columns": 565,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 59,
"minimum_structural_cross_section": 9,
"minimum_clear_cross_section": 9,
"minimum_reachable_cross_section": 9,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "south-axis-local:start",
"x": 0,
"z": 57,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 48.0
},
{
"name": "south-axis-local:end",
"x": 1,
"z": 110,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 102.0
}
]
},
{
"id": "portal-radial-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 531,
"missing_corridor_columns": [],
"declared_clear_columns": 376,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 70,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "portal-radial-local:start",
"x": -35,
"z": -14,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 57.0
},
{
"name": "portal-radial-local:end",
"x": -72,
"z": -46,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 126.0
}
]
},
{
"id": "lake-radial-local",
"passed": true,
"declared_clear_width": 5,
"corridor_columns": 403,
"missing_corridor_columns": [],
"declared_clear_columns": 297,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 63,
"minimum_structural_cross_section": 5,
"minimum_clear_cross_section": 5,
"minimum_reachable_cross_section": 5,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "lake-radial-local:start",
"x": -42,
"z": 18,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 50.5
},
{
"name": "lake-radial-local:end",
"x": -90,
"z": 32,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 112.5
}
]
},
{
"id": "east-radial-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 451,
"missing_corridor_columns": [],
"declared_clear_columns": 341,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 49,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "east-radial-local:start",
"x": 42,
"z": 16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 49.0
},
{
"name": "east-radial-local:end",
"x": 82,
"z": 8,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 90.5
}
]
},
{
"id": "ring-northwest-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 468,
"missing_corridor_columns": [],
"declared_clear_columns": 350,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 53,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "ring-northwest-local:start",
"x": -40,
"z": -65,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 113.0
},
{
"name": "ring-northwest-local:end",
"x": -80,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 165.0
}
]
},
{
"id": "ring-northeast-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 505,
"missing_corridor_columns": [],
"declared_clear_columns": 374,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 60,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "ring-northeast-local:start",
"x": 40,
"z": -95,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 151.0
},
{
"name": "ring-northeast-local:end",
"x": 82,
"z": -78,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 210.0
}
]
},
{
"id": "station-entrance-stair",
"passed": true,
"declared_clear_width": 21,
"corridor_columns": 161,
"missing_corridor_columns": [],
"declared_clear_columns": 147,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 7,
"minimum_structural_cross_section": 21,
"minimum_clear_cross_section": 21,
"minimum_reachable_cross_section": 21,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "station-entrance-stair:start",
"x": -6,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 91.0
},
{
"name": "station-entrance-stair:end",
"x": -6,
"z": -83,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 97.0
}
]
}
],
"passed": true,
"bench_access": [
{
"name": "bench-access--31-1",
"x": -31,
"z": 1,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 38.0
},
{
"name": "bench-access--31-2",
"x": -31,
"z": 2,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 37.0
},
{
"name": "bench-access--31-3",
"x": -31,
"z": 3,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 36.0
},
{
"name": "bench-access--23-32",
"x": -23,
"z": 32,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "bench-access--23-33",
"x": -23,
"z": 33,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.5
},
{
"name": "bench-access--23-34",
"x": -23,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 47.5
},
{
"name": "bench-access--22-33",
"x": -22,
"z": 33,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "bench-access--22-34",
"x": -22,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.5
},
{
"name": "bench-access--21-34",
"x": -21,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "bench-access--18--16",
"x": -18,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 42.0
},
{
"name": "bench-access--18--15",
"x": -18,
"z": -15,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 41.0
},
{
"name": "bench-access--18--14",
"x": -18,
"z": -14,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.0
},
{
"name": "bench-access--17--16",
"x": -17,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 41.0
},
{
"name": "bench-access--17--15",
"x": -17,
"z": -15,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.0
},
{
"name": "bench-access--16--16",
"x": -16,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.0
},
{
"name": "bench-access--16--15",
"x": -16,
"z": -15,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 39.0
},
{
"name": "bench-access-16--16",
"x": 16,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.5
},
{
"name": "bench-access-16--15",
"x": 16,
"z": -15,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 39.5
},
{
"name": "bench-access-17--16",
"x": 17,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 41.5
},
{
"name": "bench-access-17--15",
"x": 17,
"z": -15,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.5
},
{
"name": "bench-access-18--16",
"x": 18,
"z": -16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 42.5
},
{
"name": "bench-access-18--15",
"x": 18,
"z": -15,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 41.5
},
{
"name": "bench-access-18--14",
"x": 18,
"z": -14,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 40.5
},
{
"name": "bench-access-21-34",
"x": 21,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.0
},
{
"name": "bench-access-22-33",
"x": 22,
"z": 33,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.0
},
{
"name": "bench-access-22-34",
"x": 22,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 47.0
},
{
"name": "bench-access-23-32",
"x": 23,
"z": 32,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 46.0
},
{
"name": "bench-access-23-33",
"x": 23,
"z": 33,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 47.0
},
{
"name": "bench-access-23-34",
"x": 23,
"z": 34,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 48.0
},
{
"name": "bench-access-31-1",
"x": 31,
"z": 1,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 38.5
},
{
"name": "bench-access-31-2",
"x": 31,
"z": 2,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 37.5
},
{
"name": "bench-access-31-3",
"x": 31,
"z": 3,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 36.5
}
]
},
"volume": {
"passed": true,
"outside_desired_voxels": 555598,
"desired_voxels": 710,
"mismatch_examples": [],
"scope_note": "Every voxel inside the supplied before snapshot; no claim for unobserved exterior voxels."
},
"note": "Point-sampled body headroom and navigation; not a full moving-player collision simulation.",
"input_sha256": {
"layout": "6ec0e65027080207dc8e5f7b19afaa7b33f6ddb723de5c3632cc6097592da581",
"metadata": "242507f39a354f04281bdf4a32a2fe05d9c144af9d1b7c7e7e8ddecc17976114",
"garden_plan": "699060010db084dc05c47400572ac4440784d1a0c3dbd877122decd183048923",
"garden_metadata": "400f672864117b62ed173600932ca04ab15a0c548587bb3d39f34eaa91484e89",
"garden_walk": "453c5ee1e699a59be845db22abc5e481915768ab229a79c0cc6019d8b3e39d0d",
"navigation": "1baf3c4ef2c1ddfca22240395fcde97b5210d97c9afe5cb2b6c3275154cfe044",
"before": "3172d03627e625d759a3b9ce881282e26db2926c35dd68ac0036047ae33c3488",
"after": "c77e8f953f257822f6f6489d397ab39f40459c18183743dbdbea3e168a193c65"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 669 KiB

@@ -1,551 +0,0 @@
{
"stage": "02-foundations-zones-01-02",
"total_checked_writes": 79081,
"journalled_batches": 67,
"final_changed_voxels": 78673,
"checks": {
"surface-verification": {
"version": 1,
"world": "shacraft_lobby_v2",
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"source": "Full live Paper surface maps plus observed baseline voxels and desired edit overlay",
"verified_surface_columns": 589824,
"affected_columns": 16901,
"outside_edit_columns_verified": 572923,
"changed_surface_columns": 16901,
"surface_mismatches": 0,
"outside_edit_surface_mismatches": 0,
"mismatch_examples": [],
"original_visible_water_columns": 41467,
"visible_water_surface_changes": 0,
"water_surface_change_examples": [],
"expected_states_checked_against_baseline": 78673,
"placed_or_replaced_voxels": 77950,
"removed_voxels": 723,
"lower_snapshot_voxels_consulted_after_cuts": 12,
"observed_water_voxels_replaced": [],
"water_preservation_passed": true,
"passed": true,
"capture_started_at": "2026-09-13T01:47:40.367423160Z",
"capture_finished_at": "2026-09-13T01:49:35.666216379Z",
"atomic_snapshot": false,
"note": "Sequential map captures; edits must be idle during each capture. This checks every visible surface and the observed water blocks in the edit. Hidden untouched blocks outside the voxel survey are not inferred. Live voxel and headroom checks are separate.",
"inputs_sha256": {
"before_map": "45612085877b44b0fc58a67f3c140049452b3fc8e8798ff816bd368852a2eaa2",
"after_map": "b4bc17c20864543fab5b03dd1f6ccecba2b79c261fa45f3c8497f1824fb8ccfa",
"baseline_voxels": "d53662eac3c06ed79d86ba5da9ce0e95c32ade146f6eb9f4f30782ec51ae8677",
"desired_layout": "22da24b01fa5d14f278253e48d97721ffb5341543b46827c17617020c1b47374"
}
},
"walk-verification": {
"checked_points": 15708,
"checked_route_edges": 0,
"failures": [],
"passed": true,
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"note": "Observed surface samples and vertical headroom; full cubes, slabs and explicit straight bottom-stair samples. Stair samples are a surface profile, not a full player-width collision simulation. Cached snapshot is not a live re-read."
},
"block-verification": {
"version": 1,
"source": "Complete final observed block-state survey",
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"verified_desired_blocks": 78673,
"mismatches": 0,
"mismatch_examples": [],
"passed": true,
"verified_by_desired_material": {
"minecraft:deepslate_bricks": 2983,
"minecraft:polished_andesite": 2635,
"minecraft:stone_brick_stairs": 724,
"minecraft:stone": 53085,
"minecraft:stone_bricks": 4399,
"minecraft:smooth_sandstone": 5776,
"minecraft:smooth_stone": 6343,
"minecraft:stone_brick_wall": 670,
"minecraft:grass_block": 561,
"minecraft:air": 723,
"minecraft:chiseled_stone_bricks": 27,
"minecraft:smooth_stone_slab": 27,
"minecraft:lantern": 27,
"minecraft:smooth_quartz": 236,
"minecraft:green_concrete": 457
},
"verified_by_group": {
"lake-radial-local-foundation": 963,
"lake-radial-local-paving": 403,
"edge-balustrades": 651,
"remove-obsolete-survey": 572,
"ring-northwest-local-foundation": 1116,
"ring-northwest-local-paving": 468,
"ring-northwest-local-clearance": 30,
"station-west-pilasters": 184,
"clock-station-foundation": 31398,
"station-west-arch-stones": 20,
"clock-station-paving": 5508,
"lamp-piers": 81,
"lamps": 27,
"station-west-blind-arcade": 146,
"portal-radial-local-foundation": 1054,
"portal-radial-local-paving": 531,
"portal-radial-local-clearance": 219,
"station-structural-bands": 256,
"lake-radial-local-clearance": 4,
"arrival-hex-foundation": 14211,
"arrival-hex-paving": 4741,
"station-forecourt-foundation": 3113,
"station-forecourt-paving": 1298,
"clock-station-clearance": 44,
"station-entrance-stair-foundation": 418,
"station-entrance-stair-paving": 161,
"station-forecourt-clearance": 86,
"arrival-medallion": 693,
"arrival-hex-clearance": 203,
"station-axis-foundation": 1166,
"station-axis-paving": 582,
"station-axis-clearance": 83,
"south-axis-local-foundation": 1658,
"south-axis-local-paving": 685,
"south-axis-local-clearance": 27,
"ring-northeast-local-foundation": 2663,
"station-ne-connection-foundation": 143,
"station-ne-connection-paving": 27,
"ring-northeast-local-paving": 505,
"east-radial-local-foundation": 1963,
"east-radial-local-paving": 451,
"ring-northeast-local-clearance": 8,
"east-radial-local-clearance": 8,
"temporary-bridge-threshold": 86,
"temporary-bridge-gates": 19
},
"desired_layout_sha256": "22da24b01fa5d14f278253e48d97721ffb5341543b46827c17617020c1b47374",
"snapshot_started_at": "2026-09-13T01:47:42.024943+00:00",
"snapshot_finished_at": "2026-09-13T01:48:27.217492+00:00",
"atomic_snapshot": false,
"note": "Full block states include slab/stair orientation, waterlogging and other properties. Sequential read snapshot; edits were completed before capture."
},
"navigation-verification": {
"version": 1,
"source": {
"x": 0,
"z": 9
},
"world_edits": 0,
"method": "Four quarter-center surface samples per clear cell; cardinal half-block BFS, rise/drop <= 0.5 block.",
"limitations": "Planned surface topology only. No headroom, body-width collision, material state or live-world verification. Width checks are cardinal cross-sections using the dominant local tangent; full declared masks are also checked.",
"geometry_sha256": "e5c78e645100261d1720e50ea23eaa65650eb796341facb9a50bed0ab392e736",
"planned_columns": 16309,
"clear_columns": 15140,
"surface_samples": 60560,
"reachable_samples": 60560,
"unreachable_clear_columns": [],
"unreachable_by_group": {},
"station": {
"name": "clock-station",
"x": -6,
"z": -105,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 119.0
},
"routes": [
{
"id": "station-axis",
"passed": true,
"declared_clear_width": 9,
"corridor_columns": 593,
"missing_corridor_columns": [],
"declared_clear_columns": 486,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 47,
"minimum_structural_cross_section": 9,
"minimum_clear_cross_section": 9,
"minimum_reachable_cross_section": 9,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0,
"centerline_jumps": [],
"endpoints": [
{
"name": "station-axis:start",
"x": 0,
"z": -37,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 45.5
},
{
"name": "station-axis:end",
"x": -6,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 91.0
}
]
},
{
"id": "south-axis-local",
"passed": true,
"declared_clear_width": 9,
"corridor_columns": 685,
"missing_corridor_columns": [],
"declared_clear_columns": 565,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 59,
"minimum_structural_cross_section": 9,
"minimum_clear_cross_section": 9,
"minimum_reachable_cross_section": 9,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "south-axis-local:start",
"x": 0,
"z": 57,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 48.0
},
{
"name": "south-axis-local:end",
"x": 1,
"z": 110,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 102.0
}
]
},
{
"id": "portal-radial-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 531,
"missing_corridor_columns": [],
"declared_clear_columns": 376,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 70,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "portal-radial-local:start",
"x": -35,
"z": -14,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 57.0
},
{
"name": "portal-radial-local:end",
"x": -72,
"z": -46,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 126.0
}
]
},
{
"id": "lake-radial-local",
"passed": true,
"declared_clear_width": 5,
"corridor_columns": 403,
"missing_corridor_columns": [],
"declared_clear_columns": 297,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 63,
"minimum_structural_cross_section": 5,
"minimum_clear_cross_section": 5,
"minimum_reachable_cross_section": 5,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "lake-radial-local:start",
"x": -42,
"z": 18,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 50.5
},
{
"name": "lake-radial-local:end",
"x": -90,
"z": 32,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 112.5
}
]
},
{
"id": "east-radial-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 451,
"missing_corridor_columns": [],
"declared_clear_columns": 341,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 49,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "east-radial-local:start",
"x": 42,
"z": 16,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 49.0
},
{
"name": "east-radial-local:end",
"x": 82,
"z": 8,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 90.5
}
]
},
{
"id": "ring-northwest-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 468,
"missing_corridor_columns": [],
"declared_clear_columns": 350,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 53,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "ring-northwest-local:start",
"x": -40,
"z": -65,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 113.0
},
{
"name": "ring-northwest-local:end",
"x": -80,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 165.0
}
]
},
{
"id": "ring-northeast-local",
"passed": true,
"declared_clear_width": 7,
"corridor_columns": 505,
"missing_corridor_columns": [],
"declared_clear_columns": 374,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 60,
"minimum_structural_cross_section": 7,
"minimum_clear_cross_section": 7,
"minimum_reachable_cross_section": 7,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "ring-northeast-local:start",
"x": 40,
"z": -95,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 151.0
},
{
"name": "ring-northeast-local:end",
"x": 82,
"z": -78,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 210.0
}
]
},
{
"id": "station-entrance-stair",
"passed": true,
"declared_clear_width": 21,
"corridor_columns": 161,
"missing_corridor_columns": [],
"declared_clear_columns": 147,
"nonclear_declared_columns": [],
"unreachable_declared_columns": [],
"cross_sections": 7,
"minimum_structural_cross_section": 21,
"minimum_clear_cross_section": 21,
"minimum_reachable_cross_section": 21,
"narrow_cross_sections": [],
"centerline_invalid_steps": [],
"centerline_maximum_boundary_step": 0.5,
"centerline_jumps": [],
"endpoints": [
{
"name": "station-entrance-stair:start",
"x": -6,
"z": -77,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 91.0
},
{
"name": "station-entrance-stair:end",
"x": -6,
"z": -83,
"surface_samples": 4,
"reachable_samples": 4,
"passed": true,
"shortest_surface_route_blocks": 97.0
}
]
}
],
"passed": true,
"final_walkable_mask": "Only columns explicitly covered by the passed actual support/headroom verification",
"non_walkable_perimeter_floor_columns_excluded": 454,
"non_walkable_perimeter_floor_examples": [
[
-51,
-145
],
[
-50,
-145
],
[
-49,
-145
],
[
-48,
-145
],
[
-47,
-145
],
[
-46,
-145
],
[
-45,
-145
],
[
-24,
-145
],
[
-23,
-145
],
[
-22,
-145
]
]
},
"lake-native-toe-verification": {
"checked_points": 3,
"checked_route_edges": 0,
"failures": [],
"passed": true,
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"note": "Observed surface samples and vertical headroom; full cubes, slabs and explicit straight bottom-stair samples. Stair samples are a surface profile, not a full player-width collision simulation. Cached snapshot is not a live re-read.",
"observed_supports": [
{
"x": -91,
"z": 31,
"y": 83,
"state": "minecraft:white_concrete"
},
{
"x": -91,
"z": 32,
"y": 83,
"state": "minecraft:grass_block[snowy=false]"
},
{
"x": -91,
"z": 33,
"y": 83,
"state": "minecraft:grass_block[snowy=false]"
}
],
"source": "live targeted RPC scan of native shore immediately outside the edit boundary"
}
},
"archive": "/home/emil/Desktop/Shacraft-Lobby-Archive",
"world_backup": "/home/emil/Desktop/minecraft-builder-mcp/.runtime/projects/shacraft-foundations-01-02-20260913"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 KiB

@@ -1,16 +0,0 @@
{
"world": "shacraft_lobby_v2",
"source": "live Paper surface maps + bounded RPC water reads",
"verified_surface_columns": 589824,
"surface_mismatches": 0,
"unique_marker_blocks": 16967,
"planned_writes": 17040,
"original_water_columns": 42399,
"water_columns_obscured_by_markers": 932,
"water_obscured_by_markers_verified_intact": true,
"height_unchanged_columns": 587098,
"capture_started_at": "2026-09-13T01:03:10.136933937Z",
"capture_finished_at": "2026-09-13T01:05:10.066341053Z",
"atomic_snapshot": false,
"note": "World edits were idle during each capture. Terrain follows its original heights; raised markers represent future structures, not finished traversable paths."
}
@@ -1,11 +0,0 @@
{
"recipe_id": "b013cd330993b262ed0192659c9276af33e1c6fdb749a02ad332086a6d99e56a",
"chunks": 2304,
"mismatches": 0,
"water_columns": 59609,
"min_surface_y": 48,
"max_surface_y": 203,
"elapsed_ms": 144136,
"world": "shacraft_lobby",
"verified_columns": 589824
}
@@ -1,35 +0,0 @@
{
"note": "Target surface only; no live world reads. Bounds clip writes, not height calculations. Cache holds 32 recipes until restart; save the recipe to regenerate the same ID.",
"world_verified": false,
"tile_budget": 4096,
"sampled_height_min": 22,
"tile_count": 27648,
"mode": "sculpt",
"status": "completed",
"tile_order": "x_then_z_then_y",
"tile_edge": 16,
"bounds": {
"worldId": "terrain",
"min": {
"x": -384,
"y": 16,
"z": -384
},
"max": {
"x": 383,
"y": 207,
"z": 383
}
},
"sampled_height_max": 203,
"terrain_id": "b013cd330993b262ed0192659c9276af33e1c6fdb749a02ad332086a6d99e56a",
"sample_grid": {
"height": 256,
"width": 256
},
"legend": "Dark green \u003d low; pale stone \u003d high; pink \u003d preserved at sampled surface",
"kind": "terrain_heightmap_preview",
"clipped_samples": 0,
"mimeType": "image/png",
"orientation": "north (-Z) up; east (+X) right"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

@@ -1,11 +0,0 @@
{
"elapsed_ms": 274728,
"max_surface_y": 204,
"min_surface_y": 48,
"water_columns": 42399,
"mismatches": 0,
"chunks": 2304,
"recipe_id": "fed10bf28fa544e7dba08d10c76a1130c67292856999b06a9fd672feeed39296",
"verified_columns": 589824,
"world": "shacraft_lobby_v2"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 946 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 KiB

@@ -1,35 +0,0 @@
{
"note": "Target surface only; no live world reads. Bounds clip writes, not height calculations. Cache holds 32 recipes until restart; save the recipe to regenerate the same ID.",
"world_verified": false,
"tile_budget": 4096,
"sampled_height_min": -43,
"tile_count": 27648,
"mode": "sculpt",
"status": "completed",
"tile_order": "x_then_z_then_y",
"tile_edge": 16,
"bounds": {
"worldId": "terrain",
"min": {
"x": -384,
"y": -48,
"z": -384
},
"max": {
"x": 383,
"y": 143,
"z": 383
}
},
"sampled_height_max": 139,
"terrain_id": "5f0c33cd7152806995906c6b9ee51024ddbe90c5e7f6585e653552df2f4aabf8",
"sample_grid": {
"height": 256,
"width": 256
},
"legend": "Dark green \u003d low; pale stone \u003d high; pink \u003d preserved at sampled surface",
"kind": "terrain_heightmap_preview",
"clipped_samples": 0,
"mimeType": "image/png",
"orientation": "north (-Z) up; east (+X) right"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

@@ -1,20 +0,0 @@
{
"world_applied": false,
"water_level": 48,
"fields": [
{
"name": "V1 \u2014 rectangular platforms",
"min_ground_y": 22.0,
"max_ground_y": 203.0,
"water_columns": 59609,
"slope_p95": 3.0
},
{
"name": "Study \u2014 ridges, soft hills, winding water",
"min_ground_y": 31.35810089111328,
"max_ground_y": 204.61903381347656,
"water_columns": 42399,
"slope_p95": 3.5214755985851562
}
]
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 936 KiB

@@ -1,119 +0,0 @@
{
"version": 1,
"scope": {
"project_id": "shacraft-lobby-v2",
"world_id": "6679385a-b67f-4e88-b6be-33836ced6f2d",
"world_epoch": "b7626ccf-9c75-4b00-9cf3-b8a42231c754"
},
"world_edits": 0,
"mode": "actual_after_snapshot",
"desired_blocks": 11502,
"interior_columns": 5888,
"independently_derived_wall_columns": 276,
"interior_voxels": 117673,
"interior_excluded_voxels": 87,
"volume_components": {
"components": [
{
"voxels": 117673,
"nonfull_voxels": 117473,
"contains_source": true
}
],
"source_in_volume": true,
"note": "Disconnected sealed components are reported, not treated as escapes. The entire required membrane and exterior flood are checked."
},
"membrane": {
"passed": true,
"required_voxels": 17276,
"parts": {
"wall": 5457,
"floor": 5870,
"folded_boundary": 61,
"roof": 5888
},
"observed_materials": {
"barrier": 11396,
"smooth_sandstone": 4080,
"smooth_stone": 447,
"cut_sandstone": 425,
"polished_andesite": 137,
"stone_bricks": 16,
"waxed_oxidized_cut_copper": 12,
"chiseled_stone_bricks": 16,
"grass_block": 377,
"dirt": 12,
"green_concrete": 356,
"gold_block": 2
},
"nonfull_voxels": 0,
"examples": [],
"method": "Every voxel in N6(interior volume) minus interior volume must be an observed full collision cube."
},
"exterior_flood": {
"passed": true,
"observed_voxels": 220584,
"exterior_reached_voxels": 78339,
"interior_reached_from_exterior": 0,
"source_reached_from_exterior": false,
"unknown_or_partial_blocks_treated_as_empty": {
"stone_brick_wall": 293,
"stone_brick_stairs": 42,
"smooth_sandstone_slab": 505,
"iron_bars": 128,
"waxed_oxidized_cut_copper_stairs": 64,
"iron_chain": 16,
"spruce_leaves": 479,
"lantern": 16,
"oxeye_daisy": 60,
"azure_bluet": 39,
"white_tulip": 62,
"oak_leaves": 58,
"allium": 50,
"spruce_fence": 18,
"spruce_stairs": 18,
"pink_tulip": 49,
"smooth_sandstone_stairs": 8,
"waxed_oxidized_cut_copper_slab": 3
},
"leak_examples": [],
"method": "Six-neighbor free-voxel exterior flood; only known full collision cubes obstruct it."
},
"player_probes": {
"passed": true,
"player_width": 0.6,
"player_height": 1.8,
"source_headroom_observed_air": true,
"swept_crossing_probes": {
"diagonal": 3288,
"cardinal": 2280,
"folded_boundary": 178,
"floor": 1,
"roof": 1
},
"unblocked_probes": 0,
"examples": [],
"note": "Supplementary swept-AABB boundary probes; the independently derived full membrane is the complete static containment criterion."
},
"preserved_decor": {
"passed": true,
"protected_observed_states": 1016,
"changed_states": 0,
"examples": []
},
"volume": {
"passed": true,
"outside_desired_voxels": 610596,
"desired_voxels": 11502,
"mismatch_examples": [],
"scope_note": "Every voxel inside the supplied before snapshot; no claim for unobserved exterior voxels."
},
"passed": true,
"limitations": "Static continuous collision containment for normal nonspectator players only. No protection against spectator, breaking/removing blocks, operator commands, plugin teleports or arbitrary discontinuous teleport/pearl behavior. Actual snapshots are sequential, not atomic.",
"input_sha256": {
"before": "9332c546f50b174ec39b01430525eb903c926b43cbdfaa956a539759fbf0f7b2",
"after": "5fdbffc42df7a799e792bf5b31c1c45f5a7e02e09844860898bcdd2f79e199b3",
"layout": "95b430dd0815c8b0d1b87932e9ac1033413f3e82766dd1d4e67aefe4cbaecfa8",
"metadata": "12caa7f14f15128736a0525a765f67a9d9f6b343fc912b36cd41d2e76ab39904"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 698 KiB

@@ -1,28 +0,0 @@
{
"capturedAt": "2026-09-13T12:33:57.784380033Z",
"dimension": "minecraft:shacraft_lobby_v2",
"x": -6.0,
"y": 113.0,
"z": -24.0,
"eyeY": 114.61999988555908,
"yaw": 180.0,
"pitch": -8.0,
"fov": 95,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 40,
"stabilizationFrames": 3,
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "4a5e4d45-78f8-4f3b-9c2a-a0a665c29fe4",
"imageSha256": "b3f36b132e62a661e8269b405dcc6e3e48ab3c20eb58894e333d2bbf92cbf262",
"imageBytes": 856573,
"elapsedSeconds": 5.063,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 KiB

@@ -1,28 +0,0 @@
{
"capturedAt": "2026-09-13T12:37:51.019066137Z",
"dimension": "minecraft:shacraft_lobby_v2",
"x": 70.0,
"y": 151.0,
"z": -39.0,
"eyeY": 152.61999988555908,
"yaw": 133.0,
"pitch": 22.0,
"fov": 75,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 90,
"stabilizationFrames": 3,
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "c352f761-9dd9-409a-94f1-fc4fd364d7cc",
"imageSha256": "c06c1fbd498b0376f639e788f142c91bdb0e3509fa7ff3ce5846748311dd444e",
"imageBytes": 1302879,
"elapsedSeconds": 9.867,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

@@ -1,28 +0,0 @@
{
"capturedAt": "2026-09-13T12:37:05.830431206Z",
"dimension": "minecraft:shacraft_lobby_v2",
"x": -46.0,
"y": 119.0,
"z": -104.0,
"eyeY": 120.61999988555908,
"yaw": 225.0,
"pitch": 12.0,
"fov": 85,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 40,
"stabilizationFrames": 3,
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "74fc1c80-5328-4dd4-90c7-4ce53661d814",
"imageSha256": "b5d319d2f216b6d6c8f9496e612a2e0066718c660ccad09fc959fedd9ed14354",
"imageBytes": 1259152,
"elapsedSeconds": 5.135,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

@@ -1,28 +0,0 @@
{
"capturedAt": "2026-09-13T12:29:28.293904723Z",
"dimension": "minecraft:shacraft_lobby_v2",
"x": -5.5,
"y": 100.0,
"z": -91.5,
"eyeY": 101.61999988555908,
"yaw": 180.0,
"pitch": -6.0,
"fov": 85,
"readiness": "local_chunks_and_render_queue_stable",
"serverRevisionVerified": false,
"loadedChunkRadius": 1,
"stabilizationTicks": 150,
"stabilizationFrames": 3,
"status": "completed",
"mimeType": "image/png",
"width": 1280,
"height": 720,
"sourceWidth": 1280,
"sourceHeight": 720,
"captureId": "14496563-40e4-4c8b-a7cc-d111ad178b9d",
"imageSha256": "b420b4b71b22812a4f5bfc9464d1192856dd8d166e66526b579ff6c3e19ea905",
"imageBytes": 1024197,
"elapsedSeconds": 16.526,
"transport": "authenticated Paper HTTP camera_capture",
"testMode": "one owner/spectator client"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1000 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

@@ -1,40 +0,0 @@
# Shacraft clock station: vestibule and SMASH
Design v1, 13 September 2026. **Proposal only; no world edits were made.**
This design fits the saved, existing zone 02 foundation in `shacraft_lobby_v2`. The current station has a deck and setting-out bands, not a completed above-ground building. Its fixed overall envelope is 115 by 63 blocks; the occupied footprint is irregular. The final stage 02 geometry contains 5,764 station columns, including the east-edge recess. The earlier ideal outline contained 5,823 columns and is not the exact placement authority.
## Drawings
- [Coordinate plans and section](00-coordinate-plan.png) · [printable PDF](00-coordinate-plan.pdf)
- [First-floor vestibule](01-vestibule.png)
- [Second-floor SMASH hall](02-smash-floor.png)
- [Clock station cutaway](03-cutaway.png)
- [Exact coordinate specification and checks](layout.json)
- [Full image prompts](prompts.json)
The three perspective images were generated with the **built-in image_gen tool**. They establish architectural character and atmosphere. The coordinate plan and JSON govern dimensions and placement: generated ornament, block counts, lettering, map thumbnails and roof shapes are illustrative. In particular, the invented slogans in the SMASH image are not approved Shacraft copy. The technical plan was drawn deterministically with Pillow from the saved foundation cells.
## Spatial arrangement
The south entrance keeps the existing approach axis at X=-6. The exterior staircase is 21 blocks clear; the entrance and principal approach aisle are seven blocks clear. A green copper and warm brass-colored lift surround is visible from the doorway, with a small directory beside it. Benches and planting occupy the side galleries. Column positions align vertically; pale stone arches and spruce ceiling panels continue the original clock-station reference.
The first-floor paving remains at block Y98, with feet at Y99. The two-block intermediate deck occupies Y111 and Y112; SMASH is walked at Y113. This gives 12 blocks of structural clear height below the intermediate deck and 11 above it, before the next ceiling begins at Y124. Hanging lamps and decorative beams may reduce local headroom; keep at least four clear blocks over public circulation. The proposed main roof has eaves at Y126 and ridge at Y140; the clock-tower peak is Y158. These are proposed heights, not measurements of an existing shell.
The lift housing occupies X=-10..-2, Z=-124..-116 on both floors. Two-block walls leave a 5 by 5 clear cabin, with a five-block opening facing south. The suggested eventual behavior is a personal floor selection and transition between enclosed stationary cabins, preventing one player's selection from moving everyone else. Lift controls, animation and world transfers are not implemented by this design. Future floors can reuse the shaft alignment, but their height, roof integration and circulation need a further design pass.
## SMASH floor
The user confirmed the Shotbow-style mode: accumulating damage increases knockback, players double-jump and attempt to knock opponents off the arena. See [Shotbow's getting-started guide](https://wiki.shotbow.net/SMASH_Getting_Started).
Six seven-by-five selection alcoves line the north wall, with three blocks between adjacent alcoves and a seven-block clear aisle in front. Each contains an arena illustration and an ordinary sign at reachable height. Slots 01–06 are **unassigned placeholders**: arena names, destinations and live status are not invented here. Later, each sign can connect to its arena world or queue.
A 19 by 15 decorative island diorama occupies the western part of the main hall. Its small islands and static figures explain knockback visually. The display sits above a solid floor, behind a stone-and-glass enclosure. It is scenery, not a playable arena or a hole through the building. The west gallery explains damage, knockback and double jumping; the east gallery provides waiting space. Burnt-orange and dark-red accents distinguish SMASH while retaining Shacraft's green copper, cream stone, spruce and warm lighting.
## Evidence and limits
`draw-plan.py` checks all specified columns, benches, the lift housing, display and selection bays against a two-block setback inside the saved foundation. It checks for furnishing overlaps and keeps the seven-block entrance aisle and bay-front aisle clear. These are design checks, not a collision test of a constructed building.
Sources are `.runtime/foundations-stage02/foundations-final.geometry.json` and the saved `zone01-complete.json` surface export; its capture time is recorded in `layout.json`. That export is not an atomic or fresh live scan. It shows only deck, parapet and lamp heights in this footprint. Before building, inspect current voxels again, preserve manual changes, save a backup and implement with conflict-aware batches. Zone 01's existing containment remains in place until a separate, checked opening of the station route.
For a design rebuild in the main repository, run `python3 docs/references/zone02-interior-v1/draw-plan.py` with Pillow available and the source geometry/export retained. Roof overhangs, arches, window bays and decorative block palettes remain to be detailed during the building pass within the selected region. No additional minigame rooms or playable arenas are included in this stage.
@@ -1,10 +0,0 @@
0aa7b7be08876532e84c3567ab1c4ee1fc6a55f8232e6ad47398f7de43505653 00-coordinate-plan.pdf
9b549bd047b54521e6d2edaa3d09bd7c128cb1d31fd1e170b16d0a9b00d93dc3 00-coordinate-plan.png
5ba4142fa4e0cbcc21770e438ca963762c157e242598908c9326f0479b3c3d86 01-vestibule.png
c23c425ffefa5626e56ab83548e1b2c3f8ed38ab7f686d2d00da93e15d86d41b 02-smash-floor.png
cd8232d0c27ea25b60510128ebdca629b8872288e9ee95db6fa919c34ae0273f 03-cutaway.png
37702b2c8337cba6d301d37c7d88151ad930fb6c474954733cfe0771a820a75a README.md
1c90cf98558c079ba3ef3ebd3cd2d8dee17cecc01535875a9ab1f23a99577d03 draw-plan.py
6341286d9f66171788fc06dfa8368d0ce9cc195de398963465a87337dff5c091 generation-sources.json
135b16fcaaab87030cd78bed3129a0edfeb2aaa8de519245e1746879e45d6b83 layout.json
a361e3016e38e95d8dbc865c70d8d256f48f085ac8f1f37c866ec403b445d605 prompts.json
@@ -1,180 +0,0 @@
"""Render the proposed station layout against the saved, block-exact foundation.
Read-only design utility; it never connects to or writes the Minecraft world.
All X/Z boxes are inclusive block coordinates. Pillow is required.
"""
import json
from pathlib import Path
from collections import Counter
from PIL import Image, ImageDraw, ImageFont
OUT = Path(__file__).resolve().parent
ROOT = OUT.parents[2]
SOURCE = ROOT / '.runtime/foundations-stage02/foundations-final.geometry.json'
geometry = json.loads(SOURCE.read_text())
foot = {(c['x'], c['z']) for c in geometry['cells'] if c['group'] == 'clock-station'}
inner = {p for p in foot if all((p[0]+dx,p[1]+dz) in foot for dx in range(-2,3) for dz in range(-2,3))}
walls = foot-inner
def cells(box):
a,b,c,d = box
return {(x,z) for x in range(a,b+1) for z in range(c,d+1)}
core = [-10,-2,-124,-116]
cabin = [-8,-4,-122,-118]
bays = [[x-3,x+3,-140,-136] for x in [-42,-32,-22,-12,-2,8]]
display = [-42,-24,-124,-110]
pillars = [[x,x+1,z,z+1] for x in [-69,-49,-19,17,31] for z in [-127,-104]]
benches = [[x,x+7,z,z+1] for x in [-67,24] for z in [-132,-108]]
features = {'lift housing':core,'lift cabin':cabin,'display':display}
features.update({f'arena bay {i+1}':b for i,b in enumerate(bays)})
features.update({f'column {i+1}':b for i,b in enumerate(pillars)})
features.update({f'bench {i+1}':b for i,b in enumerate(benches)})
for name,box in features.items():
assert cells(box) <= inner, (name,'outside two-block perimeter setback')
solid_features = [core,display,*bays,*pillars,*benches]
for i,a in enumerate(solid_features):
for b in solid_features[i+1:]:
assert not cells(a)&cells(b), ('furniture overlap',a,b)
route = cells([-9,-3,-115,-85])
assert route <= foot
assert not route & set().union(*(cells(b) for b in solid_features))
bay_aisle = cells([-46,11,-135,-129])
assert bay_aisle <= inner
assert not bay_aisle & set().union(*(cells(b) for b in solid_features))
map_path = ROOT / '.runtime/server/plugins/ShacraftTerrain/maps/zone01-complete.json'
surface=json.loads(map_path.read_text())
hist=Counter(surface['surface_y'][(z-surface['min_z'])*surface['width']+x-surface['min_x']] for x,z in foot)
design = {
'status':'PROPOSAL ONLY. Foundation is surveyed; walls, interiors and upper levels are not built.',
'world':'shacraft_lobby_v2','coordinate_convention':'X/Z boxes include both endpoints. Floor Y is block Y; walk Y is top of that floor.',
'foundation_source':str(SOURCE.relative_to(ROOT)), 'surface_capture_finished_at':surface['capture_finished_at'],
'foundation_columns':len(foot),'foundation_bounds':[-74,40,-145,-83], 'foundation_surface_height_counts':dict(hist),
'floors':[{'name':'1 Vestibule','floor_block_y':98,'walk_y':99,'ceiling_underside_y':111,'clear_height':12},
{'name':'2 Smash','floor_block_y':112,'walk_y':113,'ceiling_underside_y':124,'clear_height':11}],
'intermediate_deck_block_y':[111,112], 'perimeter_wall_thickness':2,
'main_roof_eaves_y':126,'main_roof_ridge_y':140,'clocktower_peak_y':158,
'entrance_axis_x':-6,'entrance_opening_x':[-9,-3],'entrance_threshold_z':[-84,-83],
'lift':{'housing':core,'clear_cabin':cabin,'door_clear_x':[-8,-4],'door_z':[-117,-116],'opens':'south','same_location_on_both_floors':True},
'smash_display':display,'smash_selection_bays':bays,'aligned_columns':pillars,'wing_benches':benches,
'reserved_clear_aisles':{'entry':[-9,-3,-115,-85],'bay_front':[-46,11,-135,-129]},
'checks':{'features_inside_two_block_setback':True,'solid_features_do_not_overlap':True,'entry_route_clear_width':7,'bay_front_clear_depth':7},
'limitations':['Saved surface export is not a fresh live scan.', 'Containment and overlap checks cover the proposed plan, not constructed voxels.',
'Generated perspectives are artistic references; this coordinate specification governs placement.', 'Arena sign slots are unassigned, not working destinations.',
'Future floors need an explicit roof/height design before construction. Only the lift alignment is reserved.']}
(OUT/'layout.json').write_text(json.dumps(design,indent=2)+'\n')
W,H=2000,1530
im=Image.new('RGB',(W,H),'#f5f1e7'); d=ImageDraw.Draw(im)
REG='/usr/share/fonts/truetype/ibm-plex/IBMPlexSans-Regular.ttf'
BOLD='/usr/share/fonts/truetype/ibm-plex/IBMPlexSans-SemiBold.ttf'
SERIF='/usr/share/fonts/truetype/ibm-plex/IBMPlexSerif-Regular.ttf'
def text(x,y,s,size=22,color='#203e36',bold=False,anchor=None):
d.text((x,y),s,font=ImageFont.truetype(BOLD if bold else REG,size),fill=color,anchor=anchor)
text(65,35,'SHACRAFT / CLOCK STATION',44,bold=True)
text(65,93,'01 VESTIBULE + 02 SMASH / COORDINATE PLAN / DESIGN v1',22)
text(65,133,'Fixed foundation: 115 x 63 blocks overall. North is up. Both plans use the same 1-block grid.',21)
green='#376956';orange='#bd633b';wall='#58635c';floor='#e8dfcc';gold='#d0aa54'
def plan(ox,title,upper=False):
oy=255; sc=7
def xy(x,z): return ox+(x+74)*sc,oy+(z+145)*sc
def box(b,fill,outline=None):
a,c=xy(b[0],b[2]);bb,dd=xy(b[1]+1,b[3]+1)
d.rectangle((a,c,bb-1,dd-1),fill=fill,outline=outline)
def label(x,z,s,size=17,col='#203e36'):
a,b=xy(x,z);text(a,b,s,size,col,anchor='mm')
text(ox,196,title,28,bold=True)
for x,z in foot: box([x,x,z,z], wall if (x,z) in walls else floor)
# Discrete occupied columns avoid polygon boundary ambiguity.
for x,z in inner:
a,b=xy(x,z)
d.line((a,b,a+sc,b),fill='#ddd5c4')
d.line((a,b,a,b+sc),fill='#ddd5c4')
for b in pillars: box(b,'#7b8177')
for b in benches: box(b,'#957753')
box(core,green);box(cabin,'#cbdcd0')
box([-8,-4,-117,-116],'#cbdcd0')
label(-5.5,-120,'L',21)
if upper:
box(display,orange)
label(-32.5,-118,'DISPLAY',16,'#ffffff')
label(-32.5,-114,'19 x 15',16,'#ffffff')
for i,b in enumerate(bays):
box(b,gold);label((b[0]+b[1]+1)/2,-137.5,f'{i+1:02}',16)
label(-17,-132,'7-BLOCK CLEAR AISLE',17)
label(-60,-118,'RULES',17)
label(28,-118,'WAIT',17)
label(-5,-94,'SOUTH GALLERY',17)
else:
label(-58,-118,'WAITING',17)
label(28,-118,'WAITING',17)
label(-34,-117,'VESTIBULE',19)
box([1,7,-113,-111],gold)
label(4,-107,'DIRECTORY',15)
# South doorway through both perimeter wall blocks.
box([-9,-3,-84,-83],floor)
a,b=xy(-5.5,-88);c,e=xy(-5.5,-111)
d.line((a,b,c,e),fill=green,width=4)
d.polygon([(c,e),(c-8,e+14),(c+8,e+14)],fill=green)
label(-5.5,-97,'7 wide',15)
# Outside dimensions and orientation.
text(ox+402,oy-21,'115 blocks',19,anchor='mm')
d.line((ox,oy-8,ox+805,oy-8),fill=wall,width=2)
for x in [ox,ox+805]: d.line((x,oy-14,x,oy-2),fill=wall,width=2)
text(ox+842,oy+213,'63',21,anchor='mm');text(ox+842,oy+240,'blocks',16,anchor='mm')
d.line((ox+817,oy,ox+817,oy+441),fill=wall,width=2)
for z in [-145,-125,-105,-83]:
a,b=xy(-74,z);text(a-12,b,str(z),15,anchor='rm')
for x in [-74,-50,-25,0,40]:
a,b=xy(x,-82);text(a,b+18,str(x),16,anchor='mm')
text(ox+23,oy+398,'N',23,bold=True)
d.line((ox+31,oy+397,ox+31,oy+358),fill=green,width=3)
d.polygon([(ox+31,oy+352),(ox+23,oy+366),(ox+39,oy+366)],fill=green)
text(ox,oy+491,'X: east-west / Z: north-south / unit: one block',18)
plan(105,'01 / VESTIBULE • WALK Y99')
plan(1100,'02 / SMASH • WALK Y113',True)
d.line((65,792,1935,792),fill='#bdb8aa',width=2)
text(65,825,'SECTION / ENTRANCE AXIS X = -6',27,bold=True)
text(1060,825,'DESIGN RULES',27,bold=True)
# North at left, south at right; Y shown as world surface elevations.
sx,sy,scale=105,1200,11
def section_box(z0,z1,y0,y1,fill):
d.rectangle((sx+(z0+145)*scale,sy-(y1-98)*scale,sx+(z1+145)*scale-1,sy-(y0-98)*scale-1),fill=fill)
section_box(-145,-82,98,99,wall)
section_box(-145,-82,111,113,wall)
section_box(-145,-82,124,126,wall)
section_box(-145,-143,99,124,wall)
section_box(-84,-82,99,124,wall)
section_box(-84,-82,99,105,'#f5f1e7')
for y in [99,113]:
top=111 if y==99 else 124
section_box(-124,-122,y,top,green)
section_box(-118,-116,y+6,top,green)
section_box(-122,-118,y,y+0.25,gold)
for y,lab in [(99,'Y99 / level 1'),(111,'Y111 / ceiling'),(113,'Y113 / level 2'),(124,'Y124 / ceiling')]:
yy=sy-(y-98)*scale
d.line((sx-12,yy,sx+720,yy),fill='#b4afa2',width=1)
text(sx+735,yy,lab,18,anchor='lm')
text(455,1072,'12 clear',23,anchor='mm')
text(455,924,'11 clear',23,anchor='mm')
text(105,1234,'NORTH',18);text(735,1234,'SOUTH / ENTRY',18)
notes=[
'Fixed footprint; 2-block perimeter walls.',
'Lift: 9 x 9 housing; 5 x 5 clear cabin.',
'Same shaft and south-facing door on both floors.',
'Six 7 x 5 sign bays; destinations remain unassigned.',
'SMASH display is scenery on a solid, enclosed floor.',
'Gameplay takes place in separate arena worlds.',
'Future stories are not furnished or dimensioned here.',
'Concept images illustrate style; layout.json governs placement.'
]
for i,s in enumerate(notes): text(1060,878+i*43,s,21)
text(65,1320,'VERIFIED AGAINST THE SAVED FOUNDATION',22,bold=True)
text(65,1358,f'{len(foot):,} foundation columns • all specified furnishings inside the wall setback • no furnishing overlaps',21)
text(65,1394,'This is a design drawing, not a live scan or a completed building. Above-ground shell and floors are proposed.',21)
text(65,1452,'SOURCE: foundations-final.geometry.json + zone01-complete surface export / 13 SEP 2026',18)
im.save(OUT/'00-coordinate-plan.png')
im.save(OUT/'00-coordinate-plan.pdf',resolution=150)
print(json.dumps({'saved':str(OUT),'foundation_columns':len(foot),'height_counts':dict(hist),'checks':'passed'}))
@@ -1,5 +0,0 @@
{
"01-vestibule": "/home/emil/.codex/generated_images/01a096c0-89c4-73b3-b5c7-69c847aebebf/exec-20fd3d79-6c5c-47f8-b312-d0a557f7ca01.png",
"02-smash-floor": "/home/emil/.codex/generated_images/01a096c0-89c4-73b3-b5c7-69c847aebebf/exec-65601ecd-0dd8-46fd-bb8c-7a5a1793cc52.png",
"03-cutaway": "/home/emil/.codex/generated_images/01a096c0-89c4-73b3-b5c7-69c847aebebf/exec-875ff00a-540a-41e2-bf0c-b26fac132054.png"
}
@@ -1,235 +0,0 @@
{
"status": "PROPOSAL ONLY. Foundation is surveyed; walls, interiors and upper levels are not built.",
"world": "shacraft_lobby_v2",
"coordinate_convention": "X/Z boxes include both endpoints. Floor Y is block Y; walk Y is top of that floor.",
"foundation_source": ".runtime/foundations-stage02/foundations-final.geometry.json",
"surface_capture_finished_at": "2026-09-13T11:16:27.647422004Z",
"foundation_columns": 5764,
"foundation_bounds": [
-74,
40,
-145,
-83
],
"foundation_surface_height_counts": {
"98": 5500,
"99": 252,
"102": 12
},
"floors": [
{
"name": "1 Vestibule",
"floor_block_y": 98,
"walk_y": 99,
"ceiling_underside_y": 111,
"clear_height": 12
},
{
"name": "2 Smash",
"floor_block_y": 112,
"walk_y": 113,
"ceiling_underside_y": 124,
"clear_height": 11
}
],
"intermediate_deck_block_y": [
111,
112
],
"perimeter_wall_thickness": 2,
"main_roof_eaves_y": 126,
"main_roof_ridge_y": 140,
"clocktower_peak_y": 158,
"entrance_axis_x": -6,
"entrance_opening_x": [
-9,
-3
],
"entrance_threshold_z": [
-84,
-83
],
"lift": {
"housing": [
-10,
-2,
-124,
-116
],
"clear_cabin": [
-8,
-4,
-122,
-118
],
"door_clear_x": [
-8,
-4
],
"door_z": [
-117,
-116
],
"opens": "south",
"same_location_on_both_floors": true
},
"smash_display": [
-42,
-24,
-124,
-110
],
"smash_selection_bays": [
[
-45,
-39,
-140,
-136
],
[
-35,
-29,
-140,
-136
],
[
-25,
-19,
-140,
-136
],
[
-15,
-9,
-140,
-136
],
[
-5,
1,
-140,
-136
],
[
5,
11,
-140,
-136
]
],
"aligned_columns": [
[
-69,
-68,
-127,
-126
],
[
-69,
-68,
-104,
-103
],
[
-49,
-48,
-127,
-126
],
[
-49,
-48,
-104,
-103
],
[
-19,
-18,
-127,
-126
],
[
-19,
-18,
-104,
-103
],
[
17,
18,
-127,
-126
],
[
17,
18,
-104,
-103
],
[
31,
32,
-127,
-126
],
[
31,
32,
-104,
-103
]
],
"wing_benches": [
[
-67,
-60,
-132,
-131
],
[
-67,
-60,
-108,
-107
],
[
24,
31,
-132,
-131
],
[
24,
31,
-108,
-107
]
],
"reserved_clear_aisles": {
"entry": [
-9,
-3,
-115,
-85
],
"bay_front": [
-46,
11,
-135,
-129
]
},
"checks": {
"features_inside_two_block_setback": true,
"solid_features_do_not_overlap": true,
"entry_route_clear_width": 7,
"bay_front_clear_depth": 7
},
"limitations": [
"Saved surface export is not a fresh live scan.",
"Containment and overlap checks cover the proposed plan, not constructed voxels.",
"Generated perspectives are artistic references; this coordinate specification governs placement.",
"Arena sign slots are unassigned, not working destinations.",
"Future floors need an explicit roof/height design before construction. Only the lift alignment is reserved."
]
}
@@ -1,8 +0,0 @@
{
"mode": "built-in image_gen",
"prompts": {
"01-vestibule": "Use case: stylized-concept.\nAsset type: architectural Minecraft building reference for SHACRAFT, design proposal, not a game screenshot.\nProject: Alpine clock station / minigame selection hub on an already built irregular foundation. All geometry must look buildable using Minecraft blocks, stairs, slabs, fences and panes. Pale sandstone and cream masonry, dark stone plinths, spruce, oxidized green copper, muted brass, warm lanterns, forest-green SHACRAFT banners with a simple gold S. Restrained excellent craftsmanship, architectural clarity, no visual clutter. No sci-fi, no neon holograms, no modern shopping mall. Tiny Minecraft players only as 2-block height scale figures.\nHard spatial brief: foundation east-west 115 blocks overall and north-south 63 blocks maximum. Broad main hall 68 blocks wide by 48 deep, west pavilion 23 wide and east pavilion24 wide, both42 deep. A south entrance projection39 wide by16 deep is offset 11 blocks east of the whole building center. Entrance faces south and has a21-block-wide external staircase rising3 blocks. First floor feetY99, next floor feetY113; a two-block deck atY111..112 gives12 blocks of first-floor clear height. Second floor has11 blocks clear height, next ceiling beginsY124. Lift housing9x9 blocks with usable cabin5x5, on entrance axis x=-6, z=-120, opens south on BOTH floors. Interior rooms have2-block-thick perimeter walls and believable aligned masonry columns. Main ridgeY140; clocktower peakY158. Only two floors are furnished. Future floors remain a design reservation, no extra themed rooms.\n\nPrimary request: Draw ONE large, beautiful interior architectural perspective of the FIRST-FLOOR VESTIBULE, landscape16:9. Camera from south entrance facing north, eye height about3 blocks above floor, moderate wide-angle with straight credible verticals. In the center background, clearly visible forest-green/brass lift doorway9 blocks wide with5-block-wide opening, housed in a square structural core. A long7-block-clear cream stone aisle goes directly from entrance to lift. Immediately beside lift a small readable directory says only \"1 LOBBY\" and \"2 SMASH\". Show a substantial ceiling12 blocks above floor, ribbed masonry arches and deep spruce ceiling panels, no giant open roof or infinite atrium. Side aisles lead left and right into quieter waiting galleries with spruce benches, planters in stone urns and warm lamps. Floor has a restrained forest-green geometric compass mosaic OFF the straight route; do not block path with statue or fountain. Foreground side corners frame pale stone door jambs. Warm daylight through tall side windows. Keep actual usable scale of main hall, the view shows a section of its width rather than a falsely narrow corridor. Small centered title in a slim cream margin: \"SHACRAFT / 01 VESTIBULE\". Beautiful plausible Minecraft block design, not a real-world cathedral.",
"02-smash-floor": "Use case: stylized-concept.\nAsset type: architectural Minecraft building reference for SHACRAFT, design proposal, not a game screenshot.\nProject: Alpine clock station / minigame selection hub on an already built irregular foundation. All geometry must look buildable using Minecraft blocks, stairs, slabs, fences and panes. Pale sandstone and cream masonry, dark stone plinths, spruce, oxidized green copper, muted brass, warm lanterns, forest-green SHACRAFT banners with a simple gold S. Restrained excellent craftsmanship, architectural clarity, no visual clutter. No sci-fi, no neon holograms, no modern shopping mall. Tiny Minecraft players only as 2-block height scale figures.\nHard spatial brief: foundation east-west 115 blocks overall and north-south 63 blocks maximum. Broad main hall 68 blocks wide by 48 deep, west pavilion 23 wide and east pavilion24 wide, both42 deep. A south entrance projection39 wide by16 deep is offset 11 blocks east of the whole building center. Entrance faces south and has a21-block-wide external staircase rising3 blocks. First floor feetY99, next floor feetY113; a two-block deck atY111..112 gives12 blocks of first-floor clear height. Second floor has11 blocks clear height, next ceiling beginsY124. Lift housing9x9 blocks with usable cabin5x5, on entrance axis x=-6, z=-120, opens south on BOTH floors. Interior rooms have2-block-thick perimeter walls and believable aligned masonry columns. Main ridgeY140; clocktower peakY158. Only two floors are furnished. Future floors remain a design reservation, no extra themed rooms.\n\nPrimary request: Draw ONE large, beautiful interior architectural perspective of the SECOND-FLOOR SMASH SELECTION HALL, landscape16:9. Camera near south-east part of main hall looking north-west. Include the green/brass9x9 lift core on right, its opening on its south face visible obliquely, with clear sign \"1 LOBBY\". Left foreground is a19x15-block enclosed decorative display on an intact solid floor: three small voxel floating rock islands mounted over a dark inset plinth, two static small Minecraft figures, one knocked away on a restrained gold block motion arc. This is a MUSEUM DIORAMA with low glass-and-stone protective railing, not an actual combat arena, no lethal pit, no broken public floor. A seven-block-clear aisle passes around display.\nAlong north wall in background EXACTLY SIX recessed selection bays, each7 blocks wide, separated by3 blocks; they have spruce Minecraft signboards at player reach height with a small thumbnail map plaque above and numbered headings \"01\", \"02\", \"03\", \"04\", \"05\", \"06\". These are placeholders for future arenas, no invented live player counts or glowing portals. A large tasteful block-built \"SMASH\" header above back bays. West wall small visual plaques illustrate damage, knockback, double jump using voxel pictograms. SMASH accent colors burnt orange and dark red banners, balanced with Shacraft green. Keep the same cream stone columns, spruce, green copper and brass as vestibule. Ceiling is11 blocks above floor, visible solid ceiling and rafters, not infinitely tall. Daylight, warm readable practical space. Title in slim cream margin: \"SHACRAFT / 02 SMASH\".",
"03-cutaway": "Use case: stylized-concept.\nAsset type: architectural Minecraft building reference for SHACRAFT, design proposal, not a game screenshot.\nProject: Alpine clock station / minigame selection hub on an already built irregular foundation. All geometry must look buildable using Minecraft blocks, stairs, slabs, fences and panes. Pale sandstone and cream masonry, dark stone plinths, spruce, oxidized green copper, muted brass, warm lanterns, forest-green SHACRAFT banners with a simple gold S. Restrained excellent craftsmanship, architectural clarity, no visual clutter. No sci-fi, no neon holograms, no modern shopping mall. Tiny Minecraft players only as 2-block height scale figures.\nHard spatial brief: foundation east-west 115 blocks overall and north-south 63 blocks maximum. Broad main hall 68 blocks wide by 48 deep, west pavilion 23 wide and east pavilion24 wide, both42 deep. A south entrance projection39 wide by16 deep is offset 11 blocks east of the whole building center. Entrance faces south and has a21-block-wide external staircase rising3 blocks. First floor feetY99, next floor feetY113; a two-block deck atY111..112 gives12 blocks of first-floor clear height. Second floor has11 blocks clear height, next ceiling beginsY124. Lift housing9x9 blocks with usable cabin5x5, on entrance axis x=-6, z=-120, opens south on BOTH floors. Interior rooms have2-block-thick perimeter walls and believable aligned masonry columns. Main ridgeY140; clocktower peakY158. Only two floors are furnished. Future floors remain a design reservation, no extra themed rooms.\n\nPrimary request: Create ONE polished landscape architectural cutaway axonometric reference sheet, wide3:2 format, ivory background, thin dark green labels. A dominant three-quarter view looking from south-east shows the WHOLE clock station, broad horizontal wings, original grand green copper roofs, prominent slightly off-center front clock tower. Remove front and right portions of wall and selected roof to reveal EXACTLY TWO furnished stacked floors without concealing their connection. Ground floor is a cream stone vestibule with central arrival aisle, benches in wings, square green/brass lift core at rear of arrival aisle. Upper floor directly above has same aligned core, a small contained floating-island display in left half, six signboard alcoves along rear wall. Floor slab between them clearly shown, consistent14-block floor-to-floor spacing. Remaining roofs are translucent linework only where needed. Upper clock tower contains clockwork silhouette, not extra furnished game rooms. Foundation shape must remain broad main hall plus end pavilions, shallow rear mainhall projection and south projecting tower entrance, not a rectangular skyscraper. No extra buildings or landscape.\nAdd three neat callouts only: \"01 VESTIBULE / WALK Y99\", \"02 SMASH / WALK Y113\", \"LIFT / 5 x 5 CLEAR\". Add small title \"SHACRAFT / CLOCK STATION\" and subtitle \"Two-floor interior concept\". Add note at bottom \"Concept view - coordinate plan governs dimensions\". Strong visually legible separation of floors, genuine Minecraft voxel scale, warm copper and stone, refined presentation, no dense fake dimensions."
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-273
View File
@@ -1,273 +0,0 @@
{
"version": 1,
"min": {
"x": -384,
"y": 16,
"z": -384
},
"max": {
"x": 383,
"y": 207,
"z": 383
},
"base_height": 59,
"seed": 28092005,
"mode": "sculpt",
"noise": {
"amplitude": 26,
"scale": 90
},
"palette": {
"rock": "minecraft:stone",
"soil": "minecraft:dirt",
"surface": "minecraft:grass_block",
"soil_depth": 3
},
"features": [
{
"type": "ridge",
"points": [
{
"x": -350,
"z": -285
},
{
"x": -190,
"z": -335
},
{
"x": 0,
"z": -305
},
{
"x": 160,
"z": -330
},
{
"x": 330,
"z": -290
}
],
"width": 15,
"height": 100,
"falloff": 110
},
{
"type": "ridge",
"points": [
{
"x": -330,
"z": -220
},
{
"x": -350,
"z": -40
},
{
"x": -330,
"z": 180
},
{
"x": -290,
"z": 310
}
],
"width": 8,
"height": 60,
"falloff": 70
},
{
"type": "ridge",
"points": [
{
"x": 335,
"z": -210
},
{
"x": 340,
"z": 30
},
{
"x": 315,
"z": 210
}
],
"width": 10,
"height": 66,
"falloff": 80
},
{
"type": "hill",
"center": {
"x": 0,
"z": 0
},
"radius": 50,
"height": 45,
"falloff": 140
},
{
"type": "plateau",
"min": {
"x": -65,
"z": -55
},
"max": {
"x": 65,
"z": 60
},
"height": 106,
"falloff": 28
},
{
"type": "plateau",
"min": {
"x": -82,
"z": -165
},
"max": {
"x": 82,
"z": -80
},
"height": 118,
"falloff": 24
},
{
"type": "plateau",
"min": {
"x": -245,
"z": -185
},
"max": {
"x": -125,
"z": -105
},
"height": 110,
"falloff": 22
},
{
"type": "plateau",
"min": {
"x": 130,
"z": -200
},
"max": {
"x": 255,
"z": -100
},
"height": 124,
"falloff": 20
},
{
"type": "plateau",
"min": {
"x": 135,
"z": -60
},
"max": {
"x": 250,
"z": 5
},
"height": 110,
"falloff": 15
},
{
"type": "plateau",
"min": {
"x": 145,
"z": 40
},
"max": {
"x": 250,
"z": 95
},
"height": 97,
"falloff": 15
},
{
"type": "plateau",
"min": {
"x": 160,
"z": 130
},
"max": {
"x": 235,
"z": 180
},
"height": 84,
"falloff": 14
},
{
"type": "plateau",
"min": {
"x": -240,
"z": 90
},
"max": {
"x": -115,
"z": 215
},
"height": 92,
"falloff": 25
},
{
"type": "basin",
"center": {
"x": -220,
"z": -5
},
"radius": 47,
"height": 38,
"falloff": 30
},
{
"type": "channel",
"points": [
{
"x": -40,
"z": 125
},
{
"x": -25,
"z": 200
},
{
"x": 45,
"z": 260
},
{
"x": 15,
"z": 383
}
],
"width": 20,
"height": 22,
"falloff": 16
},
{
"type": "channel",
"points": [
{
"x": 100,
"z": -250
},
{
"x": 110,
"z": -100
},
{
"x": 100,
"z": 70
},
{
"x": 80,
"z": 190
}
],
"width": 10,
"height": 30,
"falloff": 12
}
],
"preserve": []
}
-273
View File
@@ -1,273 +0,0 @@
{
"version": 1,
"min": {
"x": -384,
"y": -48,
"z": -384
},
"max": {
"x": 383,
"y": 143,
"z": 383
},
"base_height": -5,
"seed": 28092005,
"mode": "sculpt",
"noise": {
"amplitude": 26,
"scale": 90
},
"palette": {
"rock": "minecraft:stone",
"soil": "minecraft:dirt",
"surface": "minecraft:grass_block",
"soil_depth": 3
},
"features": [
{
"type": "ridge",
"points": [
{
"x": -350,
"z": -285
},
{
"x": -190,
"z": -335
},
{
"x": 0,
"z": -305
},
{
"x": 160,
"z": -330
},
{
"x": 330,
"z": -290
}
],
"width": 15,
"height": 100,
"falloff": 110
},
{
"type": "ridge",
"points": [
{
"x": -330,
"z": -220
},
{
"x": -350,
"z": -40
},
{
"x": -330,
"z": 180
},
{
"x": -290,
"z": 310
}
],
"width": 8,
"height": 60,
"falloff": 70
},
{
"type": "ridge",
"points": [
{
"x": 335,
"z": -210
},
{
"x": 340,
"z": 30
},
{
"x": 315,
"z": 210
}
],
"width": 10,
"height": 66,
"falloff": 80
},
{
"type": "hill",
"center": {
"x": 0,
"z": 0
},
"radius": 50,
"height": 45,
"falloff": 140
},
{
"type": "plateau",
"min": {
"x": -65,
"z": -55
},
"max": {
"x": 65,
"z": 60
},
"height": 42,
"falloff": 28
},
{
"type": "plateau",
"min": {
"x": -82,
"z": -165
},
"max": {
"x": 82,
"z": -80
},
"height": 54,
"falloff": 24
},
{
"type": "plateau",
"min": {
"x": -245,
"z": -185
},
"max": {
"x": -125,
"z": -105
},
"height": 46,
"falloff": 22
},
{
"type": "plateau",
"min": {
"x": 130,
"z": -200
},
"max": {
"x": 255,
"z": -100
},
"height": 60,
"falloff": 20
},
{
"type": "plateau",
"min": {
"x": 135,
"z": -60
},
"max": {
"x": 250,
"z": 5
},
"height": 46,
"falloff": 15
},
{
"type": "plateau",
"min": {
"x": 145,
"z": 40
},
"max": {
"x": 250,
"z": 95
},
"height": 33,
"falloff": 15
},
{
"type": "plateau",
"min": {
"x": 160,
"z": 130
},
"max": {
"x": 235,
"z": 180
},
"height": 20,
"falloff": 14
},
{
"type": "plateau",
"min": {
"x": -240,
"z": 90
},
"max": {
"x": -115,
"z": 215
},
"height": 28,
"falloff": 25
},
{
"type": "basin",
"center": {
"x": -220,
"z": -5
},
"radius": 47,
"height": -26,
"falloff": 30
},
{
"type": "channel",
"points": [
{
"x": -40,
"z": 125
},
{
"x": -25,
"z": 200
},
{
"x": 45,
"z": 260
},
{
"x": 15,
"z": 383
}
],
"width": 20,
"height": -42,
"falloff": 16
},
{
"type": "channel",
"points": [
{
"x": 100,
"z": -250
},
{
"x": 110,
"z": -100
},
{
"x": 100,
"z": 70
},
{
"x": 80,
"z": 190
}
],
"width": 10,
"height": -34,
"falloff": 12
}
],
"preserve": []
}
@@ -1,28 +0,0 @@
{
"version": 1,
"min": {
"x": -384,
"y": 16,
"z": -384
},
"max": {
"x": 383,
"y": 239,
"z": 383
},
"base_height": 62,
"seed": 28092005,
"mode": "sculpt",
"noise": {
"amplitude": 0,
"scale": 220
},
"palette": {
"rock": "minecraft:stone",
"soil": "minecraft:dirt",
"surface": "minecraft:grass_block",
"soil_depth": 3
},
"features": [],
"preserve": []
}
+1 -1
View File
@@ -1,7 +1,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.minecraftbuilder</groupId><artifactId>minecraft-builder-mcp</artifactId><version>0.1.0-SNAPSHOT</version><packaging>pom</packaging>
<modules><module>world-core</module><module>paper-plugin</module><module>terrain-world-plugin</module></modules>
<modules><module>world-core</module><module>paper-plugin</module></modules>
<properties><maven.compiler.release>25</maven.compiler.release><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><paper.version>26.2.build.123-stable</paper.version></properties>
<build><pluginManagement><plugins>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.14.1</version></plugin>
+3 -2
View File
@@ -8,6 +8,7 @@ import re
import subprocess
ROOT = Path(__file__).resolve().parents[1]
RUNTIME = Path(os.environ.get('MCB_RUNTIME_DIR') or ROOT / '.runtime').expanduser().resolve()
def scalar(text, key):
@@ -37,7 +38,7 @@ def main():
parser.add_argument('mode', choices=['doctor', 'chat', 'mcp', 'login', 'status'])
parser.add_argument('action', nargs='?', choices=['status'], help='Only for login: check authentication without starting a login flow')
parser.add_argument('--status', action='store_true', help='With login: check authentication without starting login')
parser.add_argument('--config', type=Path, default=ROOT / '.runtime/server/plugins/MinecraftBuilderMCP/config.yml')
parser.add_argument('--config', type=Path, default=RUNTIME / 'server/plugins/MinecraftBuilderMCP/config.yml')
parser.add_argument('--console', action='store_true', help='Use console scope only with allow-local-automation in the disposable fixture')
args = parser.parse_args()
if (args.action or args.status) and args.mode != 'login':
@@ -46,7 +47,7 @@ def main():
# Login/authentication status needs no Paper config or Paper token. Always use the same
# default state directory as the chat daemon, including when called from another cwd.
env = dict(os.environ)
env.setdefault('MCB_STATE_DIR', str(ROOT / '.runtime/bridge-state'))
env.setdefault('MCB_STATE_DIR', str(RUNTIME / 'bridge-state'))
needs_backend = args.mode in ('chat', 'mcp')
if needs_backend and not args.config.is_file():
raise SystemExit('Start the Paper plugin once to generate its private config.')
-136
View File
@@ -1,136 +0,0 @@
#!/usr/bin/env python3
"""Plan/apply/verify the Gothic reference build through checked Paper editor operations."""
import argparse
from collections import Counter
import hashlib
import json
import os
from pathlib import Path
import re
import time
import urllib.error
import urllib.request
import uuid
from builds.gothic_hall.scene import build_scene, manifest
ROOT = Path(__file__).resolve().parents[1]
OUTPUT = ROOT / '.runtime/gothic-hall'
CONFIG = ROOT / '.runtime/server/plugins/MinecraftBuilderMCP/config.yml'
def save(path, data):
temp = path.with_suffix('.tmp')
with temp.open('w') as stream:
json.dump(data, stream, indent=2)
stream.write('\n'); stream.flush(); os.fsync(stream.fileno())
temp.replace(path)
def digest(data):
return hashlib.sha256(json.dumps(data, sort_keys=True, separators=(',', ':')).encode()).hexdigest()
def point_key(value):
return value['x'], value['y'], value['z']
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('action', choices=['plan', 'apply', 'verify'])
args = parser.parse_args()
OUTPUT.mkdir(exist_ok=True)
config = CONFIG.read_text()
def scalar(key):
return re.search(r'^' + re.escape(key) + r':[ \t]*(.*?)$', config, re.M).group(1).strip().strip("'\"")
scope = {'player_id': scalar('owner-uuid'), 'project_id': scalar('project-id')}
assert scope['player_id'], 'An online project owner is required'
token = scalar('agent-token')
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
def rpc(method, params):
for attempt in range(100):
data = {'method': method, 'params': {**params, **scope}, 'requestId': str(uuid.uuid4())}
req = urllib.request.Request('http://127.0.0.1:' + scalar('http-port') + '/v1/rpc',
data=json.dumps(data).encode(), headers={'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json'})
try:
with opener.open(req, timeout=30) as response: body = json.load(response)
except urllib.error.HTTPError as error:
body = json.load(error)
if body.get('ok'): return body['result']
code = body.get('error', {}).get('code', 'unknown')
if code == 'busy': time.sleep(.1); continue
raise RuntimeError(f'{method}: {code}; no blind overwrite or replay performed')
raise RuntimeError('Paper remained busy')
context = rpc('project_context', {})
if args.action == 'plan':
voxels = build_scene(); model = manifest(voxels)
allowed = set(context['supported_materials'])
assert all(block.split('[')[0] in allowed for block in model['palette']), 'Unsupported material in blueprint'
for batch in model['batches']:
assert batch['blocks'] <= 4096
expanded = {}
for operation in batch['recipe']['operations']:
a, b = operation['min'], operation['max']
for y in range(a['y'], b['y'] + 1):
for z in range(a['z'], b['z'] + 1):
for x in range(a['x'], b['x'] + 1):
assert (x, y, z) not in expanded, 'Compression overlapped a voxel'
local = tuple(n - o for n, o in zip((x, y, z), model['origin']))
assert voxels.blocks[local] == operation['block'], 'Compression changed the blueprint'
expanded[(x, y, z)] = operation['block']
assert len(expanded) == batch['blocks']
for axis in ('x', 'y', 'z'):
assert context['region']['min'][axis] <= batch['min'][axis] <= batch['max'][axis] <= context['region']['max'][axis]
model['world_id'] = context['world_id']; model['world_epoch'] = context['world_epoch']
path = OUTPUT / 'manifest.json'
if (OUTPUT / 'ledger.json').exists() and path.exists():
assert digest(json.loads(path.read_text())) == digest(model), 'Existing live build has a different blueprint; preserve it'
save(path, model)
print(json.dumps({'blocks': model['blocks'], 'batches': len(model['batches']), 'stages': model['stages'],
'max_recipe_operations': max(len(b['recipe']['operations']) for b in model['batches'])}), flush=True)
return
model = json.loads((OUTPUT / 'manifest.json').read_text())
assert model['world_id'] == context['world_id'] and model['world_epoch'] == context['world_epoch'], 'World identity changed'
ledger_path = OUTPUT / 'ledger.json'
ledger = json.loads(ledger_path.read_text()) if ledger_path.exists() else {'manifest_sha256': digest(model), 'batches': {}}
assert ledger['manifest_sha256'] == digest(model), 'Blueprint changed after writing began'
for index, batch in enumerate(model['batches'], 1):
record = ledger['batches'].get(batch['key'])
if args.action == 'apply':
if record is None:
before = rpc('region_inspect', {'min': batch['min'], 'max': batch['max'], 'detail': 'summary'})
assert set(before['palette']) == {'minecraft:air'}, f"Occupied site in batch {batch['key']}; preserve and review"
plan = rpc('build_prepare', {'recipe': batch['recipe']})
# The immutable persisted plan must still agree with the reviewed empty site.
envelope = json.loads((CONFIG.parent / 'journal/plans' / (plan['plan_id'] + '.json')).read_text())
persisted = json.loads(envelope['payload'])
assert all(change['expected'] == 'minecraft:air' for change in persisted['changes']), 'Concurrent edit before prepare; stop'
record = {'plan': plan, 'idempotency_key': 'gothic-hall-' + plan['plan_id']}
ledger['batches'][batch['key']] = record; save(ledger_path, ledger)
if not record.get('operation_id'):
operation = rpc('build_apply', {**record['plan'], 'idempotency_key': record['idempotency_key']})
record['operation_id'] = operation['operation_id']; save(ledger_path, ledger)
for _ in range(600):
status = rpc('operation_status', {'operation_id': record['operation_id']})
if status['status'] not in ('queued', 'applying'): break
time.sleep(.1)
record['status'] = status; save(ledger_path, ledger)
assert status['status'] == 'applied', f"Batch {batch['key']} stopped: {status['status']}; inspect the operation"
print(json.dumps({'batch': index, 'of': len(model['batches']), 'key': batch['key'], 'written': status['written'],
'stages': batch['stages'], 'operation_id': record['operation_id']}), flush=True)
else:
assert record and record.get('status', {}).get('status') == 'applied', 'Build is not fully applied'
envelope = json.loads((CONFIG.parent / 'journal/plans' / (record['plan']['plan_id'] + '.json')).read_text())
planned = json.loads(envelope['payload'])
current = rpc('region_inspect', {'min': batch['min'], 'max': batch['max'], 'detail': 'blocks'})
states = {point_key(block['pos']): block['state'] for block in current['blocks']}
mismatches = [change['pos'] for change in planned['changes'] if states[point_key(change['pos'])] != change['desired']]
assert not mismatches, f"Live geometry differs in batch {batch['key']} at {mismatches[:5]}; preserve edits"
if args.action == 'verify':
report = {'status': 'verified', 'blocks': model['blocks'], 'batches': len(model['batches']), 'verified_at': time.time(),
'manifest_sha256': digest(model), 'scope': scope}
save(OUTPUT / 'verification.json', report)
print(json.dumps(report), flush=True)
else:
print('GOTHIC HALL BUILD APPLIED', flush=True)
if __name__ == '__main__':
main()
-171
View File
@@ -1,171 +0,0 @@
#!/usr/bin/env python3
"""Compile a continuous, checked arrival-square balustrade; never edit the world.
The existing polygon is followed exactly. Cardinal elbows close diagonal gaps;
garden-side elbows move outward and receive observed, grounded stone footings.
Every road clear cell, planted block and existing light remains protected.
"""
import argparse
from collections import Counter
import importlib.util
import json
import math
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
STAGE = ROOT / '.runtime/balustrade-stage04'
AIR = 'minecraft:air'
N = {'east': (1, 0), 'north': (0, -1), 'south': (0, 1), 'west': (-1, 0)}
def module(name, path):
spec = importlib.util.spec_from_file_location(name, path)
value = importlib.util.module_from_spec(spec)
spec.loader.exec_module(value)
return value
survey = module('balustrade_survey', ROOT / 'scripts/foundation-survey.py')
geometry = module('balustrade_geometry', ROOT / 'scripts/foundation-study/geometry.py')
def compile_plan(before):
design = json.loads((ROOT / '.runtime/plaza-stage03/design-final.json').read_text())
geo = json.loads((ROOT / '.runtime/foundations-stage02/foundations-final.geometry.json').read_text())
cells = {(c['x'], c['z']): c for c in geo['cells']}
roads = {tuple(p) for r in geo['routes'] for p in r['clear_cells']}
outer = geometry.polygon_cells(design['outer_hex'])
edge = {p for p in outer if any((p[0]+dx, p[1]+dz) not in outer for dx, dz in N.values())}
gardens = set()
for bed in design['beds']:
gardens |= geometry.polygon_cells(bed['outline'])
gardens |= {tuple(p) for p in bed.get('additional_planting_columns', [])}
ordered = sorted(edge, key=lambda p: math.atan2(p[1]-9, p[0]))
chain, elbows = [], []
for a, b in zip(ordered, ordered[1:]+ordered[:1]):
chain.append(a)
dx, dz = b[0]-a[0], b[1]-a[1]
if max(abs(dx), abs(dz)) > 1:
raise ValueError('Boundary order contains a nonadjacent jump')
if dx and dz:
candidates = [(a[0], b[1]), (b[0], a[1])]
def score(p):
state = before.state(p[0], 96, p[1])
return (p in edge or p in chain, p in gardens or state != AIR, p not in outer, p)
# An opening remains open even when its diagonal connector lies in it.
p = min(candidates, key=score)
chain.append(p)
elbows.append(p)
if len(set(chain)) != len(chain):
raise ValueError('Cardinal perimeter is not a simple cycle')
selected = {p for p in chain if p not in roads}
for p in selected:
state = before.state(p[0], 96, p[1])
if state != AIR and not ('stone_brick_wall[' in state or
(p in edge and state == 'minecraft:smooth_sandstone_slab[type=bottom,waterlogged=false]')):
raise ValueError(f'Protected decoration intersects fence at {p}: {state}')
if before.state(p[0], 97, p[1]) != AIR:
raise ValueError(f'Protected decoration intersects handrail at {p}')
# Rotate at an opening, then split into uninterrupted fence runs.
cut = next(i for i, p in enumerate(chain) if p not in selected)
linear = chain[cut:]+chain[:cut]
runs, run = [], []
for p in linear:
if p in selected:
run.append(p)
elif run:
runs.append(run)
run = []
if run:
runs.append(run)
piers = set()
for run in runs:
segments = max(1, round((len(run)-1)/8))
piers |= {run[round(i*(len(run)-1)/segments)] for i in range(segments+1)}
piers |= {tuple(p) for p in design['outer_hex'] if tuple(p) in run}
desired, groups, footing_columns, replaced_rims = {}, {}, [], []
def put(x, y, z, state, group):
if (x, z) in roads:
raise ValueError(f'Protected road cell at {(x, z)}')
before.state(x, y, z)
desired[x, y, z] = 'minecraft:'+state
groups[x, y, z] = group
for x, z in sorted(selected):
if (x, z) not in outer:
# Stop at an observed full support; never assume air or bury plants.
y = 95
while before.state(x, y, z) == AIR:
y -= 1
support = before.state(x, y, z).split('[')[0].removeprefix('minecraft:')
if support not in survey.FULL or y > 95:
raise ValueError(f'No simple observed footing at {(x, y, z)}')
if y < 95:
footing_columns.append({'x': x, 'z': z, 'support_y': y})
if support == 'grass_block':
put(x, y, z, 'dirt', 'stable-buried-footing-soil')
for yy in range(y+1, 96):
put(x, yy, z, 'cut_sandstone' if yy == 95 else 'stone_bricks', 'grounded-elbow-footing')
if before.state(x, 96, z).startswith('minecraft:smooth_sandstone_slab'):
replaced_rims.append([x, z])
if (x, z) in piers:
state = 'cut_sandstone'
else:
connected = {}
for name, (dx, dz) in N.items():
neighbor = before.state(x+dx, 96, z+dz).split('[')[0].removeprefix('minecraft:')
connected[name] = (x+dx, z+dz) in selected or neighbor.endswith('_wall') or neighbor in survey.FULL
straight = (connected['east'] and connected['west'] and not connected['north'] and not connected['south']) or (connected['north'] and connected['south'] and not connected['east'] and not connected['west'])
props = {name: 'tall' if value else 'none' for name, value in connected.items()}
props |= {'up': 'false' if straight else 'true', 'waterlogged': 'false'}
state = 'stone_brick_wall['+','.join(f'{k}={v}' for k, v in sorted(props.items()))+']'
put(x, 96, z, state, 'sandstone-piers' if (x, z) in piers else 'connected-stone-balusters')
put(x, 97, z, 'smooth_sandstone_slab[type=bottom,waterlogged=false]', 'continuous-cream-handrail')
# Old uncapped road rails need reciprocal arms where the new fence joins them.
adjacent = {(x+dx, z+dz) for x, z in selected for dx, dz in N.values()} - selected
neighboring_rails = {p for p in adjacent if before.state(p[0], 96, p[1]).startswith('minecraft:stone_brick_wall[')}
for x, z in sorted(neighboring_rails):
if before.state(x, 97, z) != AIR:
raise ValueError('Neighboring rail has an unsupported cap configuration')
links = {}
for name, (dx, dz) in N.items():
p = x+dx, 96, z+dz
neighbor = desired.get(p, before.state(*p)).split('[')[0].removeprefix('minecraft:')
links[name] = neighbor.endswith('_wall') or neighbor in survey.FULL
straight = (links['east'] and links['west'] and not links['north'] and not links['south']) or (links['north'] and links['south'] and not links['east'] and not links['west'])
props = {name: 'low' if linked else 'none' for name, linked in links.items()}
props |= {'up': 'false' if straight else 'true', 'waterlogged': 'false'}
put(x, 96, z, 'stone_brick_wall['+','.join(f'{k}={v}' for k, v in sorted(props.items()))+']', 'reciprocal-road-rail-joins')
blocks = [dict(zip(('x', 'y', 'z'), p)) | {'block': state, 'expected': before.state(*p), 'group': groups[p]}
for p, state in sorted(desired.items()) if state != before.state(*p)]
meta = {'version': 1, 'scope': before.scope, 'floor_y': 95, 'handrail_top_y': 97.5,
'fence_columns': sorted(selected), 'pier_columns': sorted(piers), 'path_runs': runs,
'elbow_columns': sorted(set(elbows) & selected), 'footing_columns': footing_columns,
'neighboring_rail_columns': sorted(neighboring_rails),
'replaced_planter_rims': replaced_rims, 'protected_road_columns': sorted(roads),
'by_group': dict(Counter(b['group'] for b in blocks)), 'changed_blocks': len(blocks)}
# Reuse the independent garden and inherited-route auditor with the new obstacle mask.
garden_meta = json.loads((ROOT / '.runtime/plaza-stage03/plaza-polished.metadata.json').read_text())
garden_meta['unwalkable_columns'] = sorted({tuple(p) for p in garden_meta['unwalkable_columns']} | selected)
walk = json.loads((ROOT / '.runtime/plaza-stage03/plaza-polished.walk.json').read_text())
walk['points'] = [p for p in walk['points'] if (p['x'], p['z']) not in selected]
garden_meta['walk_samples'] = len(walk['points'])
return {'version': 1, 'scope': before.scope, 'blocks': blocks}, meta, garden_meta, walk
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--before', type=Path, default=STAGE / 'before-full.json.gz')
parser.add_argument('--output', type=Path, default=STAGE / 'balustrade.json')
args = parser.parse_args()
before = survey.load_snapshot(args.before)
plan, meta, garden_meta, walk = compile_plan(before)
args.output.parent.mkdir(parents=True, exist_ok=True)
for suffix, document in (('.json', plan), ('.metadata.json', meta), ('.garden-metadata.json', garden_meta), ('.walk.json', walk)):
args.output.with_suffix(suffix).write_text(json.dumps(document, separators=(',', ':'))+'\n')
print(json.dumps({k: meta[k] for k in ('changed_blocks', 'by_group', 'replaced_planter_rims')}
| {'fence_columns': len(meta['fence_columns']), 'piers': len(meta['pier_columns']),
'runs': [len(r) for r in meta['path_runs']], 'footings': len(meta['footing_columns'])}))
if __name__ == '__main__':
main()
-226
View File
@@ -1,226 +0,0 @@
#!/usr/bin/env python3
"""Compile the reviewed foundations and streets into a checked, reversible block plan.
No server writes here. A full live voxel survey is required, and differences from
the known natural world + previous marker receipts are protected, not adopted.
Apply the resulting JSON with scripts/layout.py.
"""
import argparse
from collections import Counter, deque
import importlib.util
import json
import math
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
def module(name,path):
spec=importlib.util.spec_from_file_location(name,path)
value=importlib.util.module_from_spec(spec);spec.loader.exec_module(value);return value
geometry=module('foundation_geometry',ROOT/'scripts/foundation-study/geometry.py')
survey=module('foundation_survey',ROOT/'scripts/foundation-survey.py')
N=((1,0),(-1,0),(0,1),(0,-1))
def distances(mask):
dist={p:0 for p in mask if any((p[0]+dx,p[1]+dz) not in mask for dx,dz in N)}
q=deque(dist)
while q:
x,z=q.popleft()
for dx,dz in N:
p=(x+dx,z+dz)
if p in mask and p not in dist:dist[p]=dist[(x,z)]+1;q.append(p)
return dist
def compile_plan(design,layout,before,original,marker_documents):
scope=before.document['scope'];geo=geometry.build_geometry(design,layout);cells=geo['cells']
mask=set(cells);edge=distances(mask);desired={};groups={}
known={}
for doc in marker_documents:
for b in doc['blocks']:known[(b['x'],b['y'],b['z'])]=b['block']
def natural(x,z):
i=(z-original['min_z'])*original['width']+x-original['min_x']
return original['surface_y'][i],original['palette'][original['material_index'][i]]
def predicted(x,y,z):
if (x,y,z) in known:return known[(x,y,z)]
h,material=natural(x,z)
if y>h:return 'minecraft:air'
if material=='minecraft:water':raise ValueError('Water column outside foundation scope')
if y==h:return material+'[snowy=false]' if material=='minecraft:grass_block' else material
return 'minecraft:dirt' if material=='minecraft:grass_block' and y>=h-3 else 'minecraft:stone'
def put(x,y,z,block,group):
if not block.startswith('minecraft:'):block='minecraft:'+block
desired[(x,y,z)]=block;groups[(x,y,z)]=group
# Remove only old survey blocks within this stage's exact footprint + 1-column
# cleanup margin. Outside district markers remain unchanged.
cleanup=mask|{(x+dx,z+dz) for x,z in mask for dx,dz in N}
for (x,y,z),state in known.items():
if (x,z) not in cleanup:continue
try:before.state(x,y,z)
except (KeyError,ValueError):continue # Only the optional cleanup margin may extend beyond the survey.
h,m=natural(x,z)
if y>h:new='minecraft:air'
elif y==h:new=m+'[snowy=false]' if m=='minecraft:grass_block' else m
else:continue
put(x,y,z,new,'remove-obsolete-survey')
road_clear={tuple(p) for r in geo['routes'] for p in r['clear_cells']}
road_buffer=road_clear|{(x+dx,z+dz) for x,z in road_clear for dx,dz in N}
# Exact solid footings and two structural courses beneath every walking deck.
for (x,z),c in cells.items():
y=c['block_y'];h,_=natural(x,z);d=edge[(x,z)];group=c['group']
bottom=min(h-1,y-2) if d<=1 else min(h,y-2)
for yy in range(bottom,y):
block='stone'
if d==0:
block='deepslate_bricks' if yy<=h+1 else 'stone_bricks'
if yy==y-1:block='polished_andesite'
if (x+z)%12 in (0,1) and yy>h+1:block='smooth_sandstone'
elif d==1 and yy==y-1:block='stone_bricks'
put(x,yy,z,block,group+'-foundation')
# Clear all natural overburden and former stakes above the finished floor.
for yy in range(y+1,max(h+2,y+4)+1):put(x,yy,z,'air',group+'-clearance')
if c['kind']=='stairs':
paving=f"stone_brick_stairs[facing={c['facing']},half=bottom,shape=straight,waterlogged=false]"
elif not c['clear'] or d==0:paving='polished_andesite'
elif d==1:paving='stone_bricks'
elif d==2:paving='smooth_sandstone'
elif group=='clock-station':
# Quiet structural floor; regular narrow foundation setting-out bands.
paving='stone_bricks' if x%16==0 or z%16==0 else 'smooth_stone'
elif group in ('arrival-hex','station-forecourt'):
paving='smooth_sandstone'
if x%12==0 or z%12==0:paving='smooth_stone'
else:
paving='smooth_stone'
if c['kind']=='full' and ((x if 'radial' in group or 'ring-' in group else z)%8==0):paving='stone_bricks'
put(x,y,z,paving,group+'-paving')
# Green inset medallion. All tesserae are flush with the arrival paving.
hexagon=[(round(16*math.sin(math.pi/3*i)),round(9-16*math.cos(math.pi/3*i))) for i in range(6)]
medallion=geometry.polygon_cells(hexagon);md=distances(medallion)
for x,z in medallion:
put(x,95,z,'smooth_quartz' if md[(x,z)]<=1 else 'green_concrete','arrival-medallion')
glyph=['01110','11000','11000','01110','00011','00011','01110']
for row,bits in enumerate(glyph):
for col,on in enumerate(bits):
if on=='1':
for dx in (0,1):
for dz in (0,1):put(-5+col*2+dx,95,2+row*2+dz,'smooth_quartz','arrival-medallion')
# Keep the future tower and pavilion footing outlines readable in the deck.
for f in layout['features']:
if f['id'] not in ('station-clock-base','station-pavilion--63','station-pavilion-29'):continue
vertices=f['points'];outline=geometry.polygon_cells(vertices)
for x,z in outline:
if any((x+dx,z+dz) not in outline for dx,dz in N):put(x,98,z,'polished_andesite','station-structural-bands')
# A shallow blind arcade breaks up the tall western station retaining wall.
# Each opening is one block deep, with an intact solid backing and lintel.
for center in (-132,-124,-116,-108):
for offset in range(-2,3):
z=center+offset;h,_=natural(-74,z);top=94-abs(offset)
for y in range(max(h+2,85),top+1):
put(-74,y,z,'air','station-west-blind-arcade')
put(-73,y,z,'deepslate_bricks','station-west-blind-arcade')
if top>=h+2:put(-74,top+1,z,'smooth_sandstone','station-west-arch-stones')
for z0 in (-138,-128,-120,-112,-104,-99):
for z in (z0,z0+1):
h,_=natural(-75,z)
for y in range(h-1,98):put(-75,y,z,'deepslate_bricks' if y<h+2 else 'stone_bricks','station-west-pilasters')
put(-75,98,z,'smooth_sandstone','station-west-pilasters')
# Guard exposed edges while reserving every planned road opening at full width.
rail={}
for (x,z),c in cells.items():
if edge[(x,z)]!=0:continue
if c['clear'] and (x,z) in road_buffer:continue
outside=[(x+dx,z+dz) for dx,dz in N if (x+dx,z+dz) not in cells]
drop=max([c['block_y']-natural(*p)[0] for p in outside] or [0])
if drop>=3 or c['group']=='station-entrance-stair':rail[(x,z)]=c['block_y']+1
for (x,z),y in rail.items():
props={name:('low' if (x+dx,z+dz) in rail and abs(rail[(x+dx,z+dz)]-y)<=1 else 'none')
for name,(dx,dz) in {'east':(1,0),'north':(0,-1),'south':(0,1),'west':(-1,0)}.items()}
straight=(props['east']==props['west']=='low' and props['north']==props['south']=='none') or (props['north']==props['south']=='low' and props['east']==props['west']=='none')
up='false' if straight and (x+z)%8 else 'true'
state=f"stone_brick_wall[east={props['east']},north={props['north']},south={props['south']},up={up},waterlogged=false,west={props['west']}]"
put(x,y,z,state,'edge-balustrades')
# Roads meet the reserved bridge decks exactly. A temporary end balustrade
# prevents a finished street from leading straight into an unbuilt span.
bridge_gates=[]
for ident in ('east-radial-local','ring-northeast-local'):
r=next(r for r in geo['routes'] if r['id']==ident)
end_x,end_z=r['centerline'][-1];deck=cells[(end_x,end_z)]['block_y']
zs=sorted(z for x,z in r['corridor'] if x==end_x)
for z in zs:
x=end_x+1;h,_=natural(x,z)
for y in range(min(h,deck-1),deck+1):put(x,y,z,'stone_bricks','temporary-bridge-threshold')
north='low' if z-1 in zs else 'none';south='low' if z+1 in zs else 'none'
put(x,deck+1,z,f'stone_brick_wall[east=none,north={north},south={south},up=true,waterlogged=false,west=none]','temporary-bridge-gates')
bridge_gates.append({'x':end_x+1.5,'y':deck+4,'z':end_z+.5,'deck_y':deck})
# Lit piers are part of the stone edge, never obstacles in the clear road lane.
candidates=[p for p in rail if cells[p]['kind']=='full']
chosen=[]
landmarks=[(0,-37),(38,-14),(42,30),(0,56),(-42,30),(-38,-14),
(-36,-61),(27,-61),(-25,-83),(13,-83),(-74,-139),(40,-139),(-74,-98),(40,-98)]
for target in landmarks:
options=sorted(candidates,key=lambda p:(p[0]-target[0])**2+(p[1]-target[1])**2)
if options and math.dist(options[0],target)<12 and all(math.dist(options[0],p)>8 for p in chosen):chosen.append(options[0])
for point in sorted(candidates,key=lambda p:(p[1],p[0])):
if all(math.dist(point,p)>19 for p in chosen):chosen.append(point)
for x,z in chosen:
y=cells[(x,z)]['block_y']
put(x,y+1,z,'chiseled_stone_bricks','lamp-piers');put(x,y+2,z,'stone_bricks','lamp-piers')
put(x,y+3,z,'smooth_stone_slab[type=double,waterlogged=false]','lamp-piers')
put(x,y+4,z,'lantern[hanging=false,waterlogged=false]','lamps')
# Preserve any unexpected human edits, including underground blocks. We do
# not silently rebase onto arbitrary newly observed content.
blocks=[];mismatches=[]
for (x,y,z),block in sorted(desired.items()):
actual=before.state(x,y,z);expected=predicted(x,y,z)
if actual!=expected:
mismatches.append({'x':x,'y':y,'z':z,'expected':expected,'actual':actual})
continue
if block!=actual:blocks.append({'x':x,'y':y,'z':z,'block':block,'expected':actual,'group':groups[(x,y,z)]})
if mismatches:raise ValueError(f'Unexpected live edits preserved: {len(mismatches)}, first {mismatches[:5]}')
# Sample both treads of every stair and every usable full floor column. Rails
# and lamp piers are excluded; actual after-survey tests their surrounding lanes.
walk=[]
for (x,z),c in cells.items():
if (x,z) in rail or not c['clear']:continue
if c['kind']=='stairs':
for sub in (.25,.75):
sx,sz=(sub,.5) if c['facing'] in ('east','west') else (.5,sub)
walk.append({'x':x,'z':z,'standing_y':geometry.tread_height(c,sx,sz),'sub_x':sx,'sub_z':sz})
else:walk.append({'x':x,'z':z,'standing_y':c['block_y']+1})
metadata={'scope':scope,'geometry_checks':geo['checks'],'changed_blocks':len(blocks),'walk_samples':len(walk),
'lamps':len(chosen),'rail_columns':len(rail),'by_material':dict(Counter(b['block'] for b in blocks)),
'temporary_bridge_gates':bridge_gates,
'source_snapshot_finished_at':before.document['finished_at'],'source_snapshot_atomic':False,
'note':'Only zones01/02 foundations and local access roads; other districts remain marked reservations.'}
return {'version':1,'scope':scope,'blocks':blocks},metadata,{'scope':scope,'points':walk},geo
def main():
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--design',type=Path,required=True);p.add_argument('--snapshot',type=Path,required=True)
p.add_argument('--output',type=Path,required=True);a=p.parse_args()
before=survey.load_snapshot(a.snapshot)
design=json.loads(a.design.read_text());layout=json.loads((ROOT/'examples/layout/shacraft-lobby-layout.json').read_text())
original=json.loads((ROOT/'.runtime/server/plugins/ShacraftTerrain/maps/layout-before.json').read_text())
markers=[json.loads((ROOT/name).read_text()) for name in ('.runtime/layout-study/markers-final.json','.runtime/layout-study/access-blocks.json')]
plan,meta,walk,geo=compile_plan(design,layout,before,original,markers)
a.output.parent.mkdir(parents=True,exist_ok=True)
a.output.write_text(json.dumps(plan,separators=(',',':'))+'\n')
a.output.with_suffix('.metadata.json').write_text(json.dumps(meta,indent=2)+'\n')
a.output.with_suffix('.walk.json').write_text(json.dumps(walk,separators=(',',':'))+'\n')
a.output.with_suffix('.geometry.json').write_text(json.dumps(geometry.serializable(geo),separators=(',',':'))+'\n')
print(json.dumps(meta))
if __name__=='__main__':main()
-294
View File
@@ -1,294 +0,0 @@
#!/usr/bin/env python3
"""Compile a reference-led arrival garden against observed, protected voxel states.
No world writes. Apply the resulting checked recipe with scripts/layout.py.
The brand bitmap is sampled into block coordinates, not used as a rendered fake.
"""
import argparse
from collections import Counter, deque
import hashlib
import importlib.util
import json
import math
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
N2 = ((1, 0), (-1, 0), (0, 1), (0, -1))
N3 = ((1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1))
AIR = 'minecraft:air'
def module(name, path):
spec = importlib.util.spec_from_file_location(name, path)
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
return m
geometry = module('plaza_geometry', ROOT / 'scripts/foundation-study/geometry.py')
survey = module('plaza_survey', ROOT / 'scripts/foundation-survey.py')
assets = module('plaza_assets', ROOT / 'scripts/plaza-assets.py')
def distances(mask):
result = {p: 0 for p in mask if any((p[0]+dx, p[1]+dz) not in mask for dx, dz in N2)}
pending = deque(result)
while pending:
x, z = pending.popleft()
for dx, dz in N2:
p = x+dx, z+dz
if p in mask and p not in result:
result[p] = result[x, z]+1
pending.append(p)
return result
def brand_cells(path, width=25, height=35):
from PIL import Image
source = Image.open(path).convert('RGBA')
# Select the green artwork, excluding transparency and the pale antialias fringe.
mask = Image.new('L', source.size)
pixels = source.get_flattened_data() if hasattr(source, 'get_flattened_data') else source.getdata()
mask.putdata([255 if a > 100 and g > r*1.15 and g > b*1.15 else 0 for r, g, b, a in pixels])
box = mask.getbbox()
if not box:
raise ValueError('Brand image contains no green artwork')
cells = mask.crop(box).resize((width, height), Image.Resampling.BOX)
return {(x-width//2, z+9-height//2) for z in range(height) for x in range(width)
if cells.getpixel((x, z)) >= 115}
def compile_plan(design, before, previous, logo):
base_geometry = json.loads((ROOT / '.runtime/foundations-stage02/foundations-final.geometry.json').read_text())
cells = {(c['x'], c['z']): c for c in base_geometry['cells']}
outer = geometry.polygon_cells(design['outer_hex'])
floor = {p for p in outer if cells[p]['kind'] == 'full' and cells[p]['block_y'] == 95}
edge = distances(outer)
protected = {tuple(p) for route in base_geometry['routes'] for p in route['clear_cells']}
desired, groups = {}, {}
def put(x, y, z, state, group):
if not state.startswith('minecraft:'):
state = 'minecraft:'+state
before.state(x, y, z) # Require observed support and air, including canopy overhangs.
desired[x, y, z], groups[x, y, z] = state, group
def current(x, y, z):
return desired.get((x, y, z), before.state(x, y, z))
# Retire only still-matching zone01 survey marks, including its exterior
# stakes and number. Other districts and changed human blocks are preserved.
marker_groups = {'arrival-hex', 'spawn-medallion', 'spawn-monogram', 'label-01', 'wayfinding-01'}
markers = json.loads((ROOT/'.runtime/layout-study/markers-final.json').read_text())
for b in markers['blocks']:
if b.get('group') not in marker_groups:
continue
p = b['x'], b['y'], b['z']
try:
observed = before.state(*p)
except (KeyError, ValueError):
continue
if observed == b['block']:
put(*p, b['expected'], 'retire-zone01-survey')
# Preserve stair treads, the foundation footprint, and all neighboring districts.
for x, z in sorted(floor):
material = 'smooth_sandstone'
if edge[x, z] == 0:
material = 'cut_sandstone'
elif edge[x, z] == 1:
material = 'smooth_stone'
put(x, 95, z, material, 'cream-paving')
for radius, material in ((22, 'polished_andesite'), (24, 'smooth_stone'), (28, 'cut_sandstone')):
poly = [(round(radius*math.sin(i*math.pi/3)), 9-round(radius*math.cos(i*math.pi/3))) for i in range(6)]
ring = geometry.polygon_cells(poly)
for x, z in ring:
if any((x+dx, z+dz) not in ring for dx, dz in N2):
put(x, 95, z, material, 'hexagonal-paving-bands')
logo_mask = brand_cells(logo)
for x, z in logo_mask:
if (x, z) not in floor:
raise ValueError('Logo exceeds the paving')
put(x, 95, z, 'green_concrete', 'original-brand-inlay')
# Replace the former bulky survey-stage light piers. Their perimeter rails remain.
old_plan = json.loads((ROOT / '.runtime/foundations-stage02/foundations-final.json').read_text())
old_lamps = [(b['x'], b['z']) for b in old_plan['blocks'] if b.get('group') == 'lamps'
and ((b['x'], b['z']) in outer or (b['x'], b['z']) == (-5, 56))]
for x, z in old_lamps:
for y in range(96, 100):
put(x, y, z, 'air', 'replace-old-lamp-piers')
props = {}
for name, (dx, dz) in {'east': (1, 0), 'north': (0, -1), 'south': (0, 1), 'west': (-1, 0)}.items():
neighbor = before.state(x+dx, 96, z+dz)
props[name] = 'low' if any(n in neighbor for n in ('stone_brick_wall', 'chiseled_stone_bricks')) else 'none'
put(x, 96, z, 'stone_brick_wall['+','.join(f'{k}={v}' for k, v in sorted(props.items() | {'up': 'true', 'waterlogged': 'false'}.items()))+']', 'restored-perimeter-rail')
beds, beds_union, bench_aprons, fixture_records = [], set(), set(), []
flower_types = ('pink_tulip', 'white_tulip', 'oxeye_daisy', 'allium', 'azure_bluet')
for index, bed in enumerate(design['beds']):
mask = geometry.polygon_cells(bed['outline'])
mask |= {tuple(p) for p in bed.get('additional_planting_columns', [])}
if not mask <= floor or mask & protected:
raise ValueError('Garden intersects a protected road or non-flat foundation')
beds.append(mask)
beds_union |= mask
inset = distances(mask)
for x, z in sorted(mask):
put(x, 94, z, 'dirt', 'garden-soil')
put(x, 95, z, 'grass_block[snowy=false]', 'garden-soil')
if inset[x, z] == 0:
put(x, 95, z, 'smooth_sandstone', 'planter-rim')
put(x, 96, z, 'smooth_sandstone_slab[type=bottom,waterlogged=false]', 'planter-rim')
else:
# Drifts follow small clusters, rather than an alternating plant checkerboard.
patch = (x//3+2*(z//3)+index) % 7
if inset[x, z] == 1 and patch in (0, 1, 5):
put(x, 96, z, 'oak_leaves[distance=7,persistent=true,waterlogged=false]', 'low-evergreen-hedge')
elif (x*17+z*31) % 5 != 0:
flower = flower_types[patch % len(flower_types)]
put(x, 96, z, flower, 'flower-drifts')
tree = bed['tree']
put(tree['x'], 95, tree['z'], 'dirt', 'stable-tree-soil')
height = max(11, min(15, tree['height_above_floor']))
for (dx, y, dz), state in assets.conifer(height, seed=1337+index*71).items():
if 'leaves' in state and y < 4:
continue
put(tree['x']+dx, 96+y, tree['z']+dz, state, 'custom-conifers')
fixture_records.append({'type': 'conifer', 'x': tree['x'], 'z': tree['z'], 'height': height})
t = bed['small_topiary']
put(t['x'], 95, t['z'], 'dirt', 'stable-tree-soil')
for y in range(4):
put(t['x'], 96+y, t['z'], 'spruce_log[axis=y]', 'small-topiary')
for y, radius in ((2, 1), (3, 1), (4, 0)):
for dx in range(-radius, radius+1):
for dz in range(-radius, radius+1):
if dx*dx+dz*dz <= 2 and (dx or dz or y == 4):
put(t['x']+dx, 96+y, t['z']+dz, 'spruce_leaves[distance=7,persistent=true,waterlogged=false]', 'small-topiary')
fixture_records.append({'type': 'topiary', 'x': t['x'], 'z': t['z'], 'height': 5})
facing_vectors = {'north': (0, -1), 'east': (1, 0), 'south': (0, 1), 'west': (-1, 0)}
opposite = {'north': 'south', 'south': 'north', 'east': 'west', 'west': 'east'}
for bed, mask in zip(design['beds'], beds):
b = bed['bench']
cx, cz = b['center']
facing = opposite[b['back_faces']]
dx, dz = facing_vectors[facing]
# Open a level, three-block seat approach through the planter rim.
for offset in (-1, 0, 1):
for step in range(1, 8):
x, z = cx+dx*step-dz*offset, cz+dz*step+dx*offset
if (x, z) not in floor:
raise ValueError('Bench approach exceeds the plaza')
for y in (96, 97):
if '_log[' in current(x, y, z):
raise ValueError('Bench approach intersects a tree')
put(x, y, z, 'air', 'bench-access')
put(x, 95, z, 'smooth_sandstone', 'bench-access')
bench_aprons.add((x, z))
if (x, z) not in mask:
break
for (ox, y, oz), state in assets.bench(b['length'], facing).items():
x, z = cx+ox, cz+oz
if (x, z) not in floor or (x, z) in protected:
raise ValueError('Bench exceeds its clear garden bay')
for yy in (96, 97):
if '_log[' in current(x, yy, z):
raise ValueError('Bench intersects a tree root')
put(x, yy, z, 'air', 'bench-access')
put(x, 95, z, 'smooth_sandstone', 'bench-foundation')
put(x, 96+y, z, state, 'garden-benches')
fixture_records.append({'type': 'bench', 'x': cx, 'z': cz, 'facing': facing, 'seats': 3})
lamps = [(v['x'], v['z']) for v in design['lighting']['lamps']]
for x, z in lamps:
c = cells.get((x, z), {})
if (x, z) in protected or c.get('kind') != 'full' or c.get('block_y') != 95:
raise ValueError('Lamp base intrudes into an approach')
put(x, 95, z, 'chiseled_stone_bricks', 'lamp-footing')
for (dx, y, dz), state in assets.lamp(6).items():
put(x+dx, 96+y, z+dz, state, 'copper-garden-lamps')
fixture_records.append({'type': 'lamp', 'x': x, 'z': z, 'lantern_y': 100})
# Leaves use their stable distance to the composed logs, including touching hedges.
leaf_positions = {p for p, state in desired.items() if '_leaves[' in state}
logs = {p for p, state in desired.items() if '_log[' in state}
leaf_dist, pending = {}, deque()
for x, y, z in logs:
for dx, dy, dz in N3:
p = x+dx, y+dy, z+dz
if p in leaf_positions:
leaf_dist[p] = 1
pending.append(p)
while pending:
x, y, z = pending.popleft()
if leaf_dist[x, y, z] >= 6:
continue
for dx, dy, dz in N3:
p = x+dx, y+dy, z+dz
if p in leaf_positions and p not in leaf_dist:
leaf_dist[p] = leaf_dist[x, y, z]+1
pending.append(p)
for p in leaf_positions:
material = desired[p].split('[', 1)[0]
desired[p] = f'{material}[distance={leaf_dist.get(p, 7)},persistent=true,waterlogged=false]'
# Every floor column with a low obstacle is excluded from the walking network.
blocked = set()
for x, z in floor:
if current(x, 96, z) != AIR or current(x, 97, z) != AIR:
blocked.add((x, z))
blocked |= beds_union - bench_aprons
if blocked & protected:
raise ValueError(f'Decoration obstructs protected road cells: {sorted(blocked & protected)[:8]}')
for x, z in blocked:
if abs(x) <= 6 and (x, z) not in beds_union:
# Existing outer balustrades are handled by the previous navigation mask.
if any(groups.get((x, y, z), '') not in ('restored-perimeter-rail', '') for y in (96, 97)):
raise ValueError('Central sightline/walking axis was obstructed')
blocks = []
for p, state in sorted(desired.items()):
observed = before.state(*p)
try:
prior = previous.state(*p)
except (KeyError, ValueError):
if p[1] <= 114:
raise
prior = AIR
if observed != prior:
raise ValueError(f'Unexpected manual edit preserved at {p}')
if state != observed:
blocks.append(dict(zip(('x', 'y', 'z'), p)) | {'block': state, 'expected': observed, 'group': groups[p]})
walk = [{'x': x, 'z': z, 'standing_y': 96} for x, z in sorted(floor-blocked)]
meta = {'scope': before.scope, 'district': '01', 'changed_blocks': len(blocks), 'planters': len(beds),
'planter_columns': len(beds_union), 'trees': 6, 'topiary': 6, 'benches': 6, 'new_lamps': len(lamps),
'old_lamps_replaced': len(old_lamps), 'logo_blocks': len(logo_mask), 'walk_samples': len(walk),
'unwalkable_columns': sorted(blocked), 'bench_access_columns': sorted(bench_aprons),
'fixtures': fixture_records, 'by_material': dict(Counter(b['block'] for b in blocks)),
'by_group': dict(Counter(b['group'] for b in blocks)), 'source': 'Observed after-foundation baseline; approved reference sheets 03 and 11'}
return {'version': 1, 'scope': before.scope, 'blocks': blocks}, meta, {'scope': before.scope, 'points': walk}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--design', type=Path, default=ROOT/'.runtime/plaza-stage03/design-final.json')
parser.add_argument('--before', type=Path, default=ROOT/'.runtime/plaza-stage03/before.json.gz')
parser.add_argument('--output', type=Path, default=ROOT/'.runtime/plaza-stage03/plaza.json')
parser.add_argument('--logo', type=Path, default=Path('/home/emil/Desktop/Shacraft-Lobby-References/brand/logo-180.png'))
args = parser.parse_args()
before = survey.load_snapshot(args.before)
previous = survey.load_snapshot(ROOT/'.runtime/foundations-stage02/after.json.gz')
design = json.loads(args.design.read_text())
plan, meta, walk = compile_plan(design, before, previous, args.logo)
meta['source_logo_sha256'] = hashlib.sha256(args.logo.read_bytes()).hexdigest()
args.output.write_text(json.dumps(plan, separators=(',', ':'))+'\n')
args.output.with_suffix('.metadata.json').write_text(json.dumps(meta, indent=2)+'\n')
args.output.with_suffix('.walk.json').write_text(json.dumps(walk, separators=(',', ':'))+'\n')
print(json.dumps({k: v for k, v in meta.items() if k not in ('unwalkable_columns', 'bench_access_columns', 'fixtures', 'by_material')}))
if __name__ == '__main__':
main()
-91
View File
@@ -1,91 +0,0 @@
#!/usr/bin/env python3
"""Compile the two-floor clock station against observed, unchanged foundation voxels.
No live writes: apply the resulting recipe using scripts/layout.py after QA.
"""
import argparse
import importlib.util
import json
from collections import Counter
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
STAGE=ROOT/'.runtime/station-stage07'
def module(name,path):
spec=importlib.util.spec_from_file_location(name,path)
value=importlib.util.module_from_spec(spec);spec.loader.exec_module(value);return value
survey=module('station_survey',ROOT/'scripts/foundation-survey.py')
def canonical(state):
if '[' not in state:return state
name,raw=state[:-1].split('[',1)
return name+'['+','.join(sorted(raw.split(',')))+']'
def compile_station(before):
layout=json.loads((ROOT/'docs/references/zone02-interior-v1/layout.json').read_text())
geometry=json.loads((ROOT/'.runtime/foundations-stage02/foundations-final.geometry.json').read_text())
foundation=survey.load_snapshot(ROOT/'.runtime/foundations-stage02/after.json.gz')
foot={(c['x'],c['z']) for c in geometry['cells'] if c['group']=='clock-station'}
allowed=set(json.loads((STAGE/'context-public.json').read_text())['supported_materials'])
exterior=module('station_exterior',ROOT/'scripts/station-exterior.py')
interior=module('station_interior',ROOT/'scripts/station-interior.py')
states,groups,ext=exterior.compile_exterior(foot,layout)
decorations,labels,intmeta=interior.compile_interior(foot,layout)
changes=Counter()
for p,v in decorations.items():
if p in states and states[p]!=v:changes[(groups[p],labels[p])]+=1
states.update(decorations);groups.update(labels)
rows=[];conflicts=[]
for p,value in sorted(states.items()):
state=canonical(value)
if state.split('[')[0] not in allowed:raise ValueError(f'Material unavailable: {state}')
observed=before.state(*p)
if observed==state:continue
if observed not in survey.AIR:
try: prior=foundation.state(*p)
except KeyError:prior=None
if observed!=prior:conflicts.append({'at':p,'current':observed,'foundation_stage':prior})
rows.append(dict(zip(('x','y','z'),p))|{'block':state,'expected':observed,'group':groups[p]})
if conflicts:raise ValueError(f'Unexpected existing changes preserved: {conflicts[:12]} ({len(conflicts)} total)')
recipe={'version':1,'scope':before.scope,'blocks':rows}
desired={(b['x'],b['y'],b['z']):b['block'] for b in rows}
def state(x,y,z):return desired.get((x,y,z),before.state(x,y,z))
inner=exterior._erode(foot,2)
floors=[]
for feet,name in [(99,'vestibule'),(113,'smash')]:
candidates=set(inner)
if feet==99:candidates|={(x,z) for x in range(-9,-2) for z in range(-85,-82)}
clear=sorted(p for p in candidates if all(state(p[0],y,p[1]) in survey.AIR for y in range(feet,feet+4)))
floors.append({'id':name,'standing_y':feet,'source':{'x':-6,'z':-120},'clear_columns':clear,'min_headroom':4})
def region(name,x0,x1,y0,y1,z0,z1):
return {'id':name,'min':{'x':x0,'y':y0,'z':z0},'max':{'x':x1,'y':y1,'z':z1}}
clear_regions=[region('entrance',-9,-3,99,102,-85,-83)]
for feet in [99,113]:
clear_regions += [region(f'cabin-{feet}',-8,-4,feet,feet+3,-122,-118),
region(f'lift-door-{feet}',-8,-4,feet,feet+3,-117,-116)]
clear_regions += [region('ground-entry-aisle',-9,-3,99,102,-115,-86),
region('smash-bay-front',-46,11,113,116,-135,-129)]
metadata={'scope':before.scope,'exterior':ext,'interior':intmeta,'public_floors':floors,
'clear_regions':clear_regions,'footprint':sorted(foot),
'containment':{'bounds':{'min':{'x':-79,'y':94,'z':-150},'max':{'x':45,'y':163,'z':-76}},
'authorized_caps':[region('ground-entrance-audit-cap',-9,-3,99,110,-84,-84)],
'forbidden_y_at_or_above':126,
'seeds':[{'id':'vestibule-and-cabin','x':-6,'y':99,'z':-120,'min_y':99,'max_y':110},
{'id':'smash-and-cabin','x':-6,'y':113,'z':-120,'min_y':113,'max_y':123}]},
'compile_summary':{'written_blocks':len(rows),'intended_states':len(states),'materials':dict(Counter(b['block'].split('[')[0] for b in rows)),
'layer_overrides':[{'exterior':a,'interior':b,'count':n} for (a,b),n in changes.items()]}}
return recipe,metadata
def main():
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--before',type=Path,default=STAGE/'before.json.gz')
parser.add_argument('--output',type=Path,default=STAGE/'compiled')
args=parser.parse_args();recipe,metadata=compile_station(survey.load_snapshot(args.before))
args.output.mkdir(parents=True,exist_ok=True)
for name,data in [('station.json',recipe),('station.metadata.json',metadata)]:
(args.output/name).write_text(json.dumps(data,separators=(',',':'))+'\n')
print(json.dumps(metadata['compile_summary']))
if __name__=='__main__':main()
-291
View File
@@ -1,291 +0,0 @@
"""Main Gothic hall geometry in local coordinates; pure voxel composition, no IO."""
def build(v):
"""Compose the north-facing hall, hollow interior, roof, and attached masonry."""
stone = "minecraft:stone_bricks"
ashlar = "minecraft:polished_andesite"
plinth = "minecraft:andesite"
pale = "minecraft:polished_diorite"
dark = "minecraft:deepslate_tiles"
glass = "minecraft:tinted_glass"
wood = "minecraft:dark_oak_planks"
oak = "minecraft:spruce_planks"
def slab(material="stone_brick", half="bottom"):
return f"minecraft:{material}_slab[type={half},waterlogged=false]"
def stair(material, facing, half="bottom"):
return (f"minecraft:{material}_stairs[facing={facing},half={half},"
"shape=straight,waterlogged=false]")
def log(axis="y"):
return f"minecraft:dark_oak_log[axis={axis}]"
def roof_height(x):
return 43 - (abs(x - 19) * 16 + 13) // 14
def pinnacle(x, z, base, height=8):
"""Square masonry shaft with a cap, taper, and slender stone finial."""
v.box(x - 1, base, z - 1, x + 1, base, z + 1, ashlar)
v.box(x, base + 1, z, x, base + height - 3, z, stone)
v.box(x - 1, base + height - 4, z - 1,
x + 1, base + height - 4, z + 1, slab())
v.set(x, base + height - 2, z, ashlar)
v.set(x, base + height - 1, z, slab())
def side_window(face, inner, center, bottom, tops, trim_face):
"""Carved pointed aperture with glass one block behind the wall face."""
half = max(tops)
lo, hi = sorted((face, inner))
for dz in range(-half, half + 1):
top = tops[abs(dz)]
v.clear(lo, bottom, center + dz, hi, top, center + dz)
v.box(inner, bottom, center + dz, inner, top, center + dz, glass)
v.set(trim_face, top + 1, center + dz, ashlar)
for dz in (-half - 1, half + 1):
v.box(trim_face, bottom - 1, center + dz,
trim_face, tops[half] + 1, center + dz, ashlar)
v.box(trim_face, bottom - 1, center - half - 1,
trim_face, bottom - 1, center + half + 1, pale)
# Alternating vertical/horizontal pieces describe the arch, rather than
# colouring an arch outline on an otherwise flat facade.
for dz in range(-half, half + 1):
top = tops[abs(dz)]
if dz:
facing = "south" if dz < 0 else "north"
v.set(trim_face, top + 2, center + dz, stair("stone_brick", facing))
v.set(trim_face, tops[0] + 2, center, slab())
def front_aperture(z_face, z_glass, center, bottom, tops):
for dx in range(-max(tops), max(tops) + 1):
top = tops[abs(dx)]
v.clear(center + dx, bottom, z_face, center + dx, top, z_glass)
v.box(center + dx, bottom, z_glass, center + dx, top, z_glass, glass)
# Dense foundations; two genuinely hollow occupied storeys above them.
v.box(7, 0, 13, 31, 0, 56, plinth)
v.box(7, 1, 13, 31, 1, 56, ashlar)
v.box(7, 2, 13, 31, 27, 56, stone)
v.clear(9, 2, 15, 29, 5, 54)
v.clear(9, 7, 15, 29, 43, 54)
v.box(9, 6, 15, 29, 6, 54, wood)
v.box(17, 6, 15, 21, 6, 53, ashlar)
for x in (9, 29):
v.box(x, 6, 15, x, 6, 54, stone)
for z in (15, 54):
v.box(9, 6, z, 29, 6, z, stone)
# Continuous ledges make the raised main floor legible from the courtyard.
for x in (6, 32):
v.box(x, 0, 13, x, 1, 56, ashlar)
v.box(x, 5, 13, x, 5, 56, stone)
v.box(x, 6, 13, x, 6, 56, slab("smooth_stone"))
v.box(x, 25, 12, x, 25, 57, ashlar)
v.box(x, 26, 12, x, 26, 57, pale)
v.box(x, 27, 12, x, 27, 57, slab())
for z in (12, 57):
v.box(6, 5, z, 32, 5, z, stone)
v.box(6, 6, z, 32, 6, z, slab("smooth_stone"))
v.box(6, 25, z, 32, 25, z, ashlar)
v.box(6, 26, z, 32, 26, z, pale)
# Timber is visible in the short shadow immediately below the roof edge.
for x in (7, 31):
v.box(x, 26, 15, x, 26, 54, log("z"))
for z in range(15, 55, 2):
v.set(x, 25, z, stair("spruce", "east" if x == 7 else "west", "top"))
bays = (18, 26, 34, 42, 50)
piers = (14, 22, 30, 38, 46, 54)
for center in bays:
for face, inner, trim in ((7, 8, 6), (31, 30, 32)):
side_window(face, inner, center, 10, {0: 22, 1: 21, 2: 19}, trim)
# The recessed central mullion and transom divide four dark lancets.
v.box(inner, 10, center, inner, 20, center, ashlar)
v.box(inner, 15, center - 2, inner, 15, center + 2, ashlar)
v.set(inner, 21, center, wood)
# A modest three-wide basement window below each high bay.
side_window(face, inner, center, 2, {0: 4, 1: 3}, trim)
v.set(inner, 2, center, wood)
# Deep, bevelled main-window sill; its ends connect to the piers.
outside = trim - 1 if trim < 19 else trim + 1
v.box(outside, 8, center - 3, outside, 8, center + 3, slab())
v.box(trim, 9, center - 3, trim, 9, center + 3, stone)
# Each buttress has an outward foot and two real setbacks.
for z in piers:
for left in (True, False):
if left:
foot, middle, shaft, outside = (3, 7), (4, 7), (5, 7), 5
else:
foot, middle, shaft, outside = (31, 35), (31, 34), (31, 33), 33
v.box(foot[0], 0, z - 1, foot[1], 1, z + 1, plinth)
v.box(middle[0], 2, z - 1, middle[1], 5, z + 1, stone)
v.box(middle[0], 6, z - 1, middle[1], 6, z + 1, slab("smooth_stone"))
v.box(shaft[0], 7, z - 1, shaft[1], 11, z + 1, stone)
v.box(shaft[0], 12, z - 1, shaft[1], 12, z + 1, ashlar)
v.box(min(outside, 7 if left else 31), 13, z,
max(outside, 7 if left else 31), 24, z, stone)
v.set(outside, 19, z, ashlar)
v.box(shaft[0], 25, z - 1, shaft[1], 25, z + 1, ashlar)
v.set(outside, 26, z, slab("smooth_stone"))
pinnacle(outside + (1 if left else -1), z, 27, 7)
# Recessed rear lancets, kept separate from the side gallery connection.
for center in (12, 19, 26):
front_aperture(55, 56, center, 10, {0: 22, 1: 20})
for dx in (-2, 2):
v.box(center + dx, 9, 57, center + dx, 21, 57, ashlar)
v.set(center, 24, 57, ashlar)
v.box(center - 2, 9, 57, center + 2, 9, 57, pale)
# Steep, two-cell-thick stepped roof. Both sides slope to the central ridge.
for x in range(5, 34):
high = roof_height(x)
if x == 19:
v.box(x, 42, 12, x, 43, 57, dark)
else:
v.box(x, high - 1, 12, x, high, 57, dark)
v.box(x, high, 12, x, high, 57,
stair("deepslate_tile", "east" if x < 19 else "west"))
# A restrained ridge crest uses slabs and piers instead of unsupported fences.
v.box(19, 43, 14, 19, 43, 55, slab("stone_brick"))
for z in range(15, 56, 4):
v.set(19, 43, z, ashlar)
# Front and rear stepped gables: substantial masonry underneath the coping.
for z in (12, 57):
for x in range(6, 33):
high = roof_height(x)
v.box(x, 27, z, x, high, z, stone)
v.set(x, high, z, ashlar)
if x != 19:
v.set(x, high + 1, z, stair("stone_brick", "east" if x < 19 else "west"))
v.box(19, 44, z, 19, 46, z, ashlar)
v.box(18, 47, z, 20, 47, z, stone)
v.set(19, 48, z, slab())
# Tall north facade, projecting three-layer porch, and its open pointed door.
v.box(13, 6, 9, 25, 6, 14, ashlar)
v.box(14, 6, 8, 24, 6, 8, ashlar)
portal_top = {0: 19, 1: 18, 2: 17, 3: 15, 4: 13}
for dx, top in portal_top.items():
for sign in (-1, 1) if dx else (1,):
x = 19 + sign * dx
v.clear(x, 7, 9, x, top, 15)
for z, material, expand in ((9, ashlar, 1), (10, stone, 0), (11, pale, 0)):
for dx in (-5, 5):
v.box(19 + dx, 7, z, 19 + dx, 14, z, material)
for dx, top in portal_top.items():
for sign in (-1, 1) if dx else (1,):
x = 19 + sign * dx
v.box(x, top + 1, z, x, top + 1 + expand, z, material)
for x in (13, 25):
v.box(x, 7, 10, x, 14, 12, stone)
v.box(x, 15, 10, x, 15, 12, slab())
# Open wooden leaves are flush with the inner jambs, not across the entrance.
v.box(15, 7, 14, 15, 12, 15, log())
v.box(23, 7, 14, 23, 12, 15, log())
v.clear(16, 7, 9, 22, 12, 15)
# Two slim flanking lancets and a large upper traceried front window.
for center in (10, 28):
front_aperture(12, 14, center, 10, {0: 23, 1: 21})
for x in (center - 2, center + 2):
v.box(x, 9, 11, x, 22, 11, ashlar)
v.set(center, 25, 11, slab())
v.box(center - 2, 9, 11, center + 2, 9, 11, pale)
front_aperture(12, 14, 19, 29, {0: 39, 1: 38, 2: 36, 3: 33})
for dx, top in {0: 39, 1: 38, 2: 36, 3: 33}.items():
for sign in (-1, 1) if dx else (1,):
v.set(19 + dx * sign, top + 1, 11, ashlar)
for x in (15, 23):
v.box(x, 28, 11, x, 34, 11, ashlar)
for x in (18, 20):
v.box(x, 29, 14, x, 36, 14, ashlar)
v.box(16, 33, 14, 22, 33, 14, ashlar)
v.box(15, 28, 11, 23, 28, 11, pale)
# Small heraldic mosaic echoes the reference's central hanging cross.
v.box(17, 22, 11, 21, 27, 11, dark)
v.box(19, 23, 10, 19, 26, 10, pale)
v.box(18, 25, 10, 20, 25, 10, pale)
v.set(19, 21, 11, dark)
for x in (7, 31):
v.box(x - 1, 2, 11, x + 1, 9, 13, stone)
v.box(x, 10, 11, x, 28, 12, ashlar)
for y in (6, 13, 25):
v.box(x - 1, y, 10, x + 1, y, 13, slab("smooth_stone"))
pinnacle(x, 12, 29, 9)
# Five small pointed dormers on each long roof slope.
for z in bays:
for left in (True, False):
lo, hi, face, inner = (10, 14, 10, 11) if left else (24, 28, 28, 27)
v.clear(lo, 33, z - 1, hi, 36, z + 1)
for dz in (-2, 2):
v.box(lo, 32, z + dz, hi, 37, z + dz, dark)
v.box(face, 32, z - 1, face, 37, z + 1, ashlar)
v.clear(min(face, inner), 34, z, max(face, inner), 36, z)
v.box(inner, 34, z, inner, 36, z, glass)
for dz in range(-2, 3):
top = 39 - abs(dz)
v.box(lo, top, z + dz, hi, top, z + dz, dark)
v.set(face, top, z + dz, ashlar)
v.set(face, 40, z, slab())
# Galleries retain a broad, open central nave and three-block walkways.
for x1, x2 in ((9, 12), (26, 29)):
v.box(x1, 16, 16, x2, 16, 52, wood)
rail = x2 if x1 < 19 else x1
v.box(rail, 17, 16, rail, 17, 52, slab("stone_brick"))
for z in range(16, 53, 4):
v.set(rail, 17, z, ashlar)
v.set(rail, 18, z, slab())
for z in piers[1:]:
if z > 52:
continue
v.box(rail, 7, z, rail, 15, z, stone)
v.box(rail - 1, 7, z - 1, rail + 1, 7, z + 1, ashlar)
v.box(rail - 1, 15, z, rail + 1, 15, z, ashlar)
# A rear bridge connects both galleries to the single staircase.
v.box(9, 16, 51, 29, 16, 53, wood)
v.box(12, 17, 50, 25, 17, 50, slab())
for x in (12, 19, 25):
v.set(x, 17, 50, ashlar)
v.set(x, 18, 50, slab())
for x in (12, 26):
v.box(x, 7, 52, x, 15, 52, stone)
# Transverse oak roof frames are visible from the nave between the dormers.
for z in (22, 30, 38, 46, 54):
v.box(9, 28, z, 29, 28, z, log("x"))
for x in range(9, 30):
y = 40 - abs(x - 19)
v.set(x, y, z, wood)
for x in (9, 29):
v.box(x, 19, z, x, 28, z, log())
# Rear right gallery stair: ten rises, with its complete headroom shaft.
v.clear(26, 7, 39, 28, 19, 49)
for step in range(10):
y, z = 7 + step, 40 + step
if y > 7:
v.box(26, 7, z, 28, y - 1, z, wood)
v.box(26, y, z, 28, y, z, stair("spruce", "south"))
# Separate basement access under the west gallery; the main floor is pierced.
v.clear(10, 2, 43, 11, 9, 48)
for step in range(5):
y, z = 2 + step, 44 + step
if y > 2:
v.box(10, 2, z, 11, y - 1, z, stone)
v.box(10, y, z, 11, y, z, stair("stone_brick", "south"))
# Modest furnishings preserve a five-block processional route to the dais.
v.box(14, 7, 50, 24, 7, 53, wood)
v.box(16, 7, 49, 22, 7, 49, stair("spruce", "south"))
for z in (24, 30, 36, 42):
for x1, x2 in ((14, 16), (22, 24)):
v.box(x1, 7, z, x2, 7, z, stair("spruce", "north"))
v.set(x1, 8, z, slab("spruce"))
v.set(x2, 8, z, slab("spruce"))
# Agreed lower-level passage to the east gallery/wing, cut after decoration.
v.clear(30, 7, 36, 35, 11, 39)
@@ -1,120 +0,0 @@
"""Add the architecture polish layer to the finished v1 scene, without I/O.
The input is scene.Voxels after the eighteen finishing corrections. V1 modules
remain immutable; removed blocks disappear from this sparse voxel composition.
"""
def build(v):
"""Restore the roof silhouette and add restrained Gothic stone/iron detail."""
stone = "minecraft:stone_bricks"
trim = "minecraft:polished_andesite"
dark = "minecraft:deepslate_tiles"
glass = "minecraft:gray_stained_glass"
wall = ("minecraft:stone_brick_wall[east=none,north=none,south=none,"
"up=true,waterlogged=false,west=none]")
def stair(material, facing, half="bottom"):
return (f"minecraft:{material}_stairs[facing={facing},half={half},"
"shape=straight,waterlogged=false]")
def bars(north=False, south=False, east=False, west=False):
flags = {"east": east, "north": north, "south": south, "west": west}
return "minecraft:iron_bars[" + ",".join(
f"{name}={str(value).lower()}" for name, value in flags.items()
) + ",waterlogged=false]"
def roof_height(x):
return 43 - (abs(x - 19) * 16 + 13) // 14
# Use the actual input mask so a material replacement cannot fill an opening.
# Preserve the six pale blocks of the heraldic cross on the north facade.
crest = {(19, y, 10) for y in range(23, 27)} | {
(x, 25, 10) for x in range(18, 21)
}
timber = {
p: block for p, block in v.blocks.items()
if 9 <= p[0] <= 29 and 28 <= p[1] <= 40 and 15 <= p[2] <= 54
and (block.startswith("minecraft:dark_oak_log[")
or block == "minecraft:dark_oak_planks")
}
for p, block in tuple(v.blocks.items()):
if block == "minecraft:polished_diorite" and p not in crest:
v.set(*p, trim)
elif block == "minecraft:tinted_glass":
v.set(*p, glass)
elif (block == "minecraft:cut_sandstone"
and 39 <= p[0] <= 41 and 34 <= p[1] <= 37 and 48 <= p[2] <= 50):
v.set(*p, "minecraft:gold_block")
# Remove only the ten old dormer envelopes, then reconstruct the same
# two-cell roof section. These envelopes exclude both gables and all trusses.
for z in (18, 26, 34, 42, 50):
for x1, x2 in ((10, 14), (24, 28)):
v.clear(x1, 32, z - 2, x2, 40, z + 2)
for x in range(x1, x2 + 1):
high = roof_height(x)
for y in (high - 1, high):
if 32 <= y <= 40:
block = dark if y < high else stair(
"deepslate_tile", "east" if x < 19 else "west")
v.box(x, y, z - 2, x, y, z + 2, block)
# Three narrow, low dormers per slope: a one-by-two recessed light, three
# blocks of facade width, and a short roof merging into the original slope.
for z in (22, 34, 46):
for face, inner, back in ((10, 11, 13), (28, 27, 25)):
x1, x2 = sorted((face, back))
near = back - 1 if face < back else back + 1
v.clear(min(face, near), 33, z, max(face, near), 34, z)
for dz in (-1, 1):
v.box(x1, 32, z + dz, x2, 34, z + dz, dark)
facing = "south" if dz < 0 else "north"
v.box(x1, 35, z + dz, x2, 35, z + dz,
stair("deepslate_tile", facing))
v.box(face, 33, z + dz, face, 34, z + dz, trim)
v.set(face, 35, z + dz, stair("stone_brick", facing))
v.box(x1, 36, z, x2, 36, z, dark)
v.box(face, 32, z - 1, face, 32, z + 1, trim)
v.box(inner, 33, z, inner, 34, z, glass)
v.set(face, 35, z, stone)
v.set(face, 36, z, wall)
# The old bright, chunky ridge is now a dark backing for one thin iron rail.
v.box(19, 43, 14, 19, 43, 55, dark)
for z in range(14, 56):
v.set(19, 44, z, bars(north=z > 14, south=z < 55))
# Replace full-block mullions with slender rods in their original glazing
# plane. Connected horizontal bars provide a clear transom without a grille.
for center in (18, 26, 34, 42, 50):
for inner, outside in ((8, 6), (30, 32)):
for y in range(10, 21):
v.set(inner, y, center, bars())
for dz in range(-2, 3):
v.set(inner, 15, center + dz,
bars(north=dz > -2, south=dz < 2))
# A bevel on the underside of each stepped arch reduces square caps.
for dz, top in ((-2, 19), (-1, 21), (1, 21), (2, 19)):
v.set(outside, top + 1, center + dz,
stair("stone_brick", "north" if dz < 0 else "south", "top"))
for x in (18, 20):
for y in range(29, 37):
v.set(x, y, 14, bars())
for x in range(16, 23):
v.set(x, 33, 14, bars(east=x < 22, west=x > 16))
# Taper the tips, retaining the full support blocks installed by finish v1.
for x in (6, 32):
for z in (14, 22, 30, 38, 46, 54):
v.box(x, 32, z, x, 33, z, wall)
for x in (7, 31):
v.box(x, 36, 12, x, 37, 12, wall)
for x in (35, 45):
for z in (43, 55):
v.box(x, 49, z, x, 50, z, wall)
# Two new dormer centers cross truss planes. Keep every original timber
# voxel, including the inclined members, instead of cutting a frame for glass.
for p, block in timber.items():
v.set(*p, block)
-159
View File
@@ -1,159 +0,0 @@
"""Reference-driven finishing layer; the original scene and its ledgers stay immutable."""
from .scene import build_scene as original_scene
from .polish_architecture import build as architecture
STONE = 'minecraft:stone_bricks'
TRIM = 'minecraft:polished_andesite'
LEAVES = 'minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]'
CHAIN = 'minecraft:iron_chain[axis=y,waterlogged=false]'
SLAB = 'minecraft:stone_brick_slab[type=bottom,waterlogged=false]'
def stair(facing, half='top'):
return f'minecraft:stone_brick_stairs[facing={facing},half={half},shape=straight,waterlogged=false]'
def bars(north=False, east=False, south=False, west=False):
return ('minecraft:iron_bars[' + ','.join(f'{key}={str(value).lower()}' for key, value in
[('north', north), ('east', east), ('south', south), ('west', west)]) + ',waterlogged=false]')
def finished_scene():
v = original_scene()
for x in (6, 32):
for z in (14, 22, 30, 38, 46, 54):
v.set(x, 30, z, STONE)
for x in (7, 31):
v.set(x, 34, 12, STONE)
for z in range(36, 40):
v.set(35, 8, z, stair('east', 'bottom'))
return v
def lamp(v, x, y, z, hanging=True):
v.set(x, y, z, f'minecraft:lantern[hanging={str(hanging).lower()},waterlogged=false]')
def lighting(v):
v.stage = 'lanterns and interior lighting'
# Portal fixtures attach to the existing masonry jambs.
for x in (13, 25):
v.set(x, 14, 9, stair('south'))
v.set(x, 13, 9, CHAIN)
lamp(v, x, 12, 9)
for x, facing, bays in ((4, 'east', (14, 22, 30, 38, 46, 54)),
(34, 'west', (14, 22, 30))):
for z in bays:
v.set(x, 16, z, stair(facing))
v.set(x, 15, z, CHAIN)
lamp(v, x, 14, z)
for x in (43, 52):
v.set(x, 8, 14, stair('south'))
v.set(x, 7, 14, CHAIN)
lamp(v, x, 6, 14)
for z in (21, 29, 37):
v.set(59, 14, z, TRIM)
v.set(60, 14, z, stair('west'))
v.set(60, 13, z, CHAIN)
lamp(v, 60, 12, z)
# Existing low piers become courtyard lamps, with a full supporting cap.
for x in (8, 30, 35, 61):
for z in (6, 59):
v.set(x, 4, z, TRIM)
lamp(v, x, 5, z, False)
# Three chandeliers hang in the clear nave, below the preserved timber ties.
for z in (22, 38, 46):
v.box(19, 19, z, 19, 27, z, CHAIN)
for dx in range(-2, 3):
v.set(19 + dx, 18, z, bars(dx == 0, dx < 2, dx == 0, dx > -2))
for dz in (-2, -1, 1, 2):
v.set(19, 18, z + dz, bars(dz > -2, False, dz < 2, False))
for x, zz in ((17, z), (21, z), (19, z - 2), (19, z + 2)):
lamp(v, x, 17, zz)
for x, facing in ((13, 'west'), (25, 'east')):
for z in (22, 38, 46):
v.set(x, 12, z, stair(facing))
v.set(x, 11, z, CHAIN)
lamp(v, x, 10, z)
# Wing ground floor: lights hang from the existing floor beams.
for x in (43, 50):
for z in (23, 31):
v.set(x, 6, z, CHAIN)
lamp(v, x, 5, z)
for z in (23, 35):
v.box(38, 17, z, 57, 17, z, 'minecraft:spruce_log[axis=x]')
v.box(47, 14, z, 47, 16, z, CHAIN)
lamp(v, 47, 13, z)
# Tower landings and the block-built bell receive a restrained warm light.
for y in (7, 16, 25):
v.box(40, y + 1, 46, 40, y + 2, 46, CHAIN)
lamp(v, 40, y, 46)
for x in (37, 43):
v.box(x, 39, 49, x, 40, 49, CHAIN)
lamp(v, x, 38, 49)
def landscape(v):
v.stage = 'planted stone terrace'
def bed(x1, z1, x2, z2, high=3):
# Soil replaces only the known terrace surface, with a low dressed rim.
for x in range(x1, x2 + 1):
for z in range(z1, z2 + 1):
edge = x in (x1, x2) or z in (z1, z2)
if edge:
if (x, 1, z) not in v.blocks:
v.set(x, 1, z, SLAB)
else:
v.set(x, 0, z, 'minecraft:dirt')
height = high - int((x * 7 + z * 11) % 5 == 0)
for y in range(1, height + 1):
if (x, y, z) not in v.blocks:
v.set(x, y, z, LEAVES)
for z in (18, 26, 34, 42, 50):
bed(1, z - 2, 5, z + 2, 2)
for z in (21, 29, 37):
bed(60, z - 2, 64, z + 2, 2)
bed(5, 9, 12, 11, 2)
bed(26, 9, 32, 11, 2)
bed(39, 11, 43, 13, 2)
bed(52, 11, 56, 13, 2)
bed(9, 59, 28, 61, 2)
bed(48, 45, 59, 47, 2)
def narrow_tree(x, z, height):
# Persistent leaves cannot decay; every addition respects existing masonry.
if (x, 0, z) not in v.blocks or v.blocks[(x, 0, z)].split('[')[0] in (
'minecraft:smooth_stone', 'minecraft:polished_andesite', 'minecraft:stone_bricks'):
v.set(x, 0, z, 'minecraft:moss_block')
for y in range(1, height - 1):
if (x, y, z) not in v.blocks or v.blocks[(x, y, z)] == LEAVES:
v.set(x, y, z, 'minecraft:spruce_log[axis=y]')
for y in range(2, height + 1):
radius = 2 if y <= height - 4 else 1 if y <= height - 1 else 0
for dx in range(-radius, radius + 1):
for dz in range(-radius, radius + 1):
if abs(dx) + abs(dz) > radius + 1:
continue
p = x + dx, y, z + dz
if p not in v.blocks or v.blocks[p] == LEAVES:
v.set(*p, LEAVES)
for x, z, h in ((10, 9, 8), (28, 9, 8), (62, 16, 7), (62, 44, 7),
(6, 60, 8), (32, 60, 7)):
narrow_tree(x, z, h)
# Slight wear follows the edges, leaving the main approach calm and readable.
for (x, y, z), block in list(v.blocks.items()):
if y == 0 and block == 'minecraft:smooth_stone' and (x < 6 or x > 59 or z > 57):
if (x * 31 + z * 17) % 29 == 0:
v.set(x, y, z, 'minecraft:andesite')
if y in (1, 2, 3) and block == STONE and (x < 8 or x > 56) and (x * 13 + y * 7 + z * 19) % 31 == 0:
v.set(x, y, z, 'minecraft:mossy_stone_bricks')
def build_scene():
v = finished_scene()
architecture(v)
lighting(v)
landscape(v)
return v
-157
View File
@@ -1,157 +0,0 @@
"""Deterministic voxel blueprint for the generated Gothic hall reference."""
from collections import Counter, defaultdict
import importlib
import re
ORIGIN = (-50, -60, -40)
class Voxels:
def __init__(self):
self.blocks = {}
self.stage = 'site'
self.owners = {}
def set(self, x, y, z, block):
assert all(isinstance(v, int) for v in (x, y, z)), (x, y, z)
assert -2 <= x <= 68 and -1 <= y <= 64 and -2 <= z <= 68, (x, y, z)
if not block.startswith('minecraft:'):
block = 'minecraft:' + block
assert re.fullmatch(r'minecraft:[a-z0-9_]+(?:\[[a-z0-9_=,]+\])?', block), block
if block == 'minecraft:air':
self.blocks.pop((x, y, z), None)
self.owners.pop((x, y, z), None)
else:
self.blocks[(x, y, z)] = block
self.owners[(x, y, z)] = self.stage
def box(self, x1, y1, z1, x2, y2, z2, block):
x1, x2 = sorted((x1, x2))
y1, y2 = sorted((y1, y2))
z1, z2 = sorted((z1, z2))
for y in range(y1, y2 + 1):
for z in range(z1, z2 + 1):
for x in range(x1, x2 + 1):
self.set(x, y, z, block)
def clear(self, x1, y1, z1, x2, y2, z2):
self.box(x1, y1, z1, x2, y2, z2, 'air')
def site(v):
v.box(1, 0, 1, 63, 0, 62, 'smooth_stone')
for z in (1, 62):
v.box(1, 0, z, 63, 0, z, 'polished_andesite')
for x in (1, 63):
v.box(x, 0, 1, x, 0, 62, 'polished_andesite')
# A few continuous paving bands give the terrace scale without noisy texture.
for x in (5, 33, 60):
v.box(x, 0, 2, x, 0, 61, 'stone_bricks')
for z in (4, 59):
v.box(2, 0, z, 62, 0, z, 'stone_bricks')
for step in range(1, 7):
z = step + 1
v.box(13, 1, z, 25, step, z, 'stone_bricks')
v.box(14, step, z, 24, step, z,
'stone_brick_stairs[facing=south,half=bottom,shape=straight,waterlogged=false]')
for x in (12, 26):
v.box(x, 1, z, x, step + 1, z, 'polished_andesite')
v.set(x, step + 2, z, 'stone_brick_slab[type=bottom,waterlogged=false]')
v.box(13, 1, 8, 25, 6, 9, 'stone_bricks')
for x in (8, 30, 35, 61):
for z in (6, 59):
v.box(x, 1, z, x + 1, 1, z + 1, 'polished_andesite')
v.box(x, 2, z, x + 1, 3, z + 1, 'stone_bricks')
v.box(x, 4, z, x + 1, 4, z + 1,
'stone_brick_slab[type=bottom,waterlogged=false]')
def connection(v):
# Two-level enclosed passage between the great hall and companion wing.
v.stage = 'connecting gallery'
v.box(31, 0, 34, 40, 6, 42, 'stone_bricks')
v.box(31, 7, 34, 40, 13, 34, 'stone_bricks')
v.box(31, 7, 42, 40, 13, 42, 'stone_bricks')
v.box(31, 13, 33, 40, 13, 43, 'polished_andesite')
v.box(31, 14, 34, 40, 14, 42, 'deepslate_tiles')
v.box(31, 15, 36, 40, 15, 40, 'deepslate_tiles')
v.box(31, 16, 38, 40, 16, 38, 'deepslate_tiles')
for z, facing, y in [(34, 'south', 14), (35, 'south', 14),
(36, 'south', 15), (37, 'south', 15),
(39, 'north', 15), (40, 'north', 15),
(41, 'north', 14), (42, 'north', 14)]:
v.box(31, y, z, 40, y, z,
f'deepslate_tile_stairs[facing={facing},half=bottom,shape=straight,waterlogged=false]')
v.clear(30, 7, 36, 32, 11, 39)
v.clear(33, 8, 36, 34, 11, 39)
v.clear(35, 9, 36, 40, 12, 39)
v.box(31, 6, 36, 32, 6, 39, 'spruce_planks')
for x, y in [(33, 6), (34, 7)]:
v.box(x, y, 36, x, y, 39,
'spruce_stairs[facing=east,half=bottom,shape=straight,waterlogged=false]')
v.box(35, 8, 36, 40, 8, 39, 'spruce_planks')
def build_scene():
v = Voxels()
site(v)
for name, stage in [('main_hall', 'great hall'), ('side_wing', 'side wing'), ('tower', 'bell tower')]:
v.stage = stage
importlib.import_module('builds.gothic_hall.' + name).build(v)
connection(v)
return v
def boxes(blocks):
"""Merge runs on X, then Z and Y, preserving the exact sparse block mask."""
rows = defaultdict(list)
for (x, y, z), block in blocks.items():
rows[(y, z, block)].append(x)
runs = []
for (y, z, block), xs in sorted(rows.items()):
xs.sort(); start = end = xs[0]
for x in xs[1:]:
if x == end + 1:
end = x
else:
runs.append((start, y, z, end, y, z, block)); start = end = x
runs.append((start, y, z, end, y, z, block))
merged = []
groups = defaultdict(list)
for x1, y1, z1, x2, y2, z2, block in runs:
groups[(x1, x2, y1, block)].append(z1)
for (x1, x2, y, block), zs in sorted(groups.items()):
zs.sort(); start = end = zs[0]
for z in zs[1:]:
if z == end + 1: end = z
else:
merged.append((x1, y, start, x2, y, end, block)); start = end = z
merged.append((x1, y, start, x2, y, end, block))
result = []; groups = defaultdict(list)
for x1, y1, z1, x2, y2, z2, block in merged:
groups[(x1, x2, z1, z2, block)].append(y1)
for (x1, x2, z1, z2, block), ys in sorted(groups.items()):
ys.sort(); start = end = ys[0]
for y in ys[1:]:
if y == end + 1: end = y
else:
result.append((x1, start, z1, x2, end, z2, block)); start = end = y
result.append((x1, start, z1, x2, end, z2, block))
return result
def manifest(v):
tiles = defaultdict(dict)
for p, block in v.blocks.items():
tiles[(p[1] // 8, p[2] // 16, p[0] // 16)][p] = block
batches = []
for key, data in sorted(tiles.items()):
recipe = []
for x1, y1, z1, x2, y2, z2, block in boxes(data):
lo = dict(zip(('x', 'y', 'z'), (x1 + ORIGIN[0], y1 + ORIGIN[1], z1 + ORIGIN[2])))
hi = dict(zip(('x', 'y', 'z'), (x2 + ORIGIN[0], y2 + ORIGIN[1], z2 + ORIGIN[2])))
recipe.append({'type': 'box', 'min': lo, 'max': hi, 'block': block})
positions = list(data)
minimum = [min(p[i] for p in positions) + ORIGIN[i] for i in range(3)]
maximum = [max(p[i] for p in positions) + ORIGIN[i] for i in range(3)]
batches.append({'key': '-'.join(map(str, key)), 'blocks': len(data),
'min': dict(zip(('x', 'y', 'z'), minimum)), 'max': dict(zip(('x', 'y', 'z'), maximum)),
'recipe': {'version': 1, 'operations': recipe},
'stages': dict(Counter(v.owners[p] for p in data))})
return {'name': 'Gothic hall reference reconstruction', 'origin': ORIGIN,
'blocks': len(v.blocks), 'stages': dict(Counter(v.owners.values())),
'palette': dict(Counter(v.blocks.values())), 'batches': batches}

Some files were not shown because too many files have changed in this diff Show More