// === BUILD PLAN ===
// Style: Victorian cast-iron & glass palm house + brick boiler-house annexe, set in a park
// Footprint: cruciform/T — glazed nave 17 wide running N-S (z12..84) + octagonal drum r=12 at centre
// + brick boiler house 12x11 bolted to the WEST face (chimney) => never a plain box
// Height: plinth Y12-13, glazing to Y20, barrel vault crown Y29; drum to Y26, stepped dome Y28..Y40, finial Y44
//
// PLAN (top-down, x right, z down):
// z12 #####D##### north arched door
// # nave # 17 wide glazed nave, vault ridge along Z
// z36 ## ##
// BOILER ####( DRUM )#### octagon r=12, gallery ring at walk Y21
// z60 ## ##
// # nave #
// z84 #####D##### south arched door + gravel path
//
// SECTION through the nave: .-~~~-. vault crown Y29 (glass + green iron ribs every 4)
// | | glazing Y14..20
// |#####| red-brick plinth Y12..13 + cornice slab
//
// MATERIALS PLAN:
// plinth : gradientPalette deepslate_bricks -> bricks -> granite up Y12..14 — WHY: heavy base, fakes AO
// ironwork : green_concrete(55)+green_terracotta(25)+dried_kelp_block(20) — WHY: dark painted iron vs pale glass = the whole look
// glazing : noisePalette glass(72)+white_stained_glass(16)+light_blue_stained_glass(12) — WHY: old uneven panes
// boiler : bricks(65)+granite(20)+mossy_stone_bricks(15), deepslate_tile_stairs roof
// dome : DRUM + stacked shrinking cylinders (build-rules "Clean Dome") + crown finial, ribs by ring parity
// Rooms: N nave (palm beds, benches), drum (pond, giant palms, gallery ring), S nave (ferns, potting benches),
// boiler house (furnaces, barrels, workbench, lantern)
// STAIR PLAN: Δ walk12 -> walk21 = 9 -> L-shape: staircase south 12->16, landing, staircase east 16->21 into ring
// PROCESS: DIRECT (final materials as placed) — masks not needed, avoids placeholder leftovers
// NOTE (from related-retrieval): chain -> iron_chain in 1.21.11+; glass panes only connect to solid blocks
// === END PLAN ===
var CX = 36, CZ = 48, DR = 12;
var NX1 = 28, NX2 = 44; // nave X span
var NZ1 = 12, NZ2 = 36; // north nave Z span
var SZ1 = 60, SZ2 = 84; // south nave Z span
var groundY = 10, floorY = 11, walkY = 12;
var plinthTop = 13;
var wallTopY = 20, SPRING = 21, VR = 8;
var drumTop = 26, domeBaseY = 28;
var galFloorY = 20, galWalkY = 21;
var BX1 = 12, BX2 = 23, BZ1 = 42, BZ2 = 53; // boiler house
var brickPal = palette([{block:"bricks",weight:65},{block:"granite",weight:20},{block:"mossy_stone_bricks",weight:15}]);
var plinthPal = gradientPalette(walkY, plinthTop + 1, [{block:"deepslate_bricks",from:0},{block:"bricks",from:0.45},{block:"granite",from:0.85}], {noise:0.25});
var ironPal = palette([{block:"green_concrete",weight:55},{block:"green_terracotta",weight:25},{block:"dried_kelp_block",weight:20}]);
var glassPal = noisePalette([{block:"glass",weight:72},{block:"white_stained_glass",weight:16},{block:"light_blue_stained_glass",weight:12}], {freq:0.15, seed:21});
var floorPal = palette([{block:"smooth_stone",weight:40},{block:"polished_diorite",weight:30},{block:"stone_bricks",weight:30}]);
function inOctR(x, z, R) {
var dx = Math.abs(x - CX), dz = Math.abs(z - CZ);
return dx <= R && dz <= R && (dx + dz) <= Math.floor(R * 1.42);
}
function onOctEdge(x, z) {
if (!inOctR(x, z, DR)) return false;
return !(inOctR(x + 1, z, DR) && inOctR(x - 1, z, DR) && inOctR(x, z + 1, DR) && inOctR(x, z - 1, DR));
}
function inNave(x, z) {
return x >= NX1 && x <= NX2 && ((z >= NZ1 && z <= NZ2) || (z >= SZ1 && z <= SZ2));
}
function inBoiler(x, z) { return x >= BX1 && x <= BX2 && z >= BZ1 && z <= BZ2; }
function inFoot(x, z) { return inNave(x, z) || inOctR(x, z, DR) || inBoiler(x, z); }
var x, y, z, i, k, dx, dz, dy, dd;
// === TERRAIN (superpowers, flat pad UNDER the build) ===
var park = blob(CX, CZ, 46, {irregularity: 0.32, seed: 17});
var hf = hills({base: 9, amp: 3, seed: 31});
var pad = flatten(hf, {x0: BX1 - 4, z0: NZ1 - 5, x1: NX2 + 6, z1: SZ2 + 5}, groundY, 10);
var gmat = patches(["grass_block", "grass_block", "podzol", "coarse_dirt"], 0.055, 8);
surface(park, pad, gmat, {sub: "dirt", deep: "stone", depth: 4});
// === CLEAR FOOTPRINT + FLOOR ===
for (x = BX1 - 1; x <= NX2 + 1; x++) {
for (z = NZ1 - 1; z <= SZ2 + 1; z++) {
if (!inFoot(x, z)) continue;
fill(x, floorY, z, x, 46, z, "air");
pb(x, floorY - 1, z, "stone_bricks");
pb(x, floorY, z, inBoiler(x, z) ? "polished_blackstone" : floorPal);
}
}
// === NAVE WALLS (glazing between iron mullions on a brick plinth) ===
function naveWall(wx, z1, z2) {
var zz, yy;
for (zz = z1; zz <= z2; zz++) {
for (yy = walkY; yy <= wallTopY; yy++) {
if (yy <= plinthTop) pb(wx, yy, zz, plinthPal);
else if (zz % 4 === 0) pb(wx, yy, zz, ironPal);
else pb(wx, yy, zz, glassPal);
}
pb(wx, wallTopY, zz, ironPal); // cornice band
}
}
naveWall(NX1, NZ1, NZ2); naveWall(NX2, NZ1, NZ2);
naveWall(NX1, SZ1, SZ2); naveWall(NX2, SZ1, SZ2);
function endWall(wz) {
var xx, yy;
for (xx = NX1; xx <= NX2; xx++) {
for (yy = walkY; yy <= wallTopY; yy++) {
if (yy <= plinthTop) pb(xx, yy, wz, plinthPal);
else if (xx % 4 === 0) pb(xx, yy, wz, ironPal);
else pb(xx, yy, wz, glassPal);
}
}
// semicircular tympanum closing the vault end
for (dx = -VR; dx <= VR; dx++) {
for (dy = 0; dy <= VR; dy++) {
dd = Math.sqrt(dx * dx + dy * dy);
if (dd < VR - 0.4) pb(CX + dx, SPRING + dy, wz, (dx % 4 === 0 || dy === 0) ? ironPal : glassPal);
}
}
}
endWall(NZ1); endWall(SZ2);
// === BARREL VAULTS (ribs every 4th bay) ===
function vault(z1, z2) {
var zz, ddx, ddy, d2, rib;
for (zz = z1; zz <= z2; zz++) {
rib = (zz % 4 === 0);
for (ddx = -VR - 1; ddx <= VR + 1; ddx++) {
for (ddy = 0; ddy <= VR + 1; ddy++) {
d2 = Math.sqrt(ddx * ddx + ddy * ddy);
if (d2 >= VR - 0.5 && d2 < VR + 0.5) {
pb(CX + ddx, SPRING + ddy, zz, rib ? ironPal : glassPal);
}
}
}
}
}
vault(NZ1, NZ2); vault(SZ1, SZ2);
// === OCTAGONAL DRUM ===
function isDrumOpening(x, z, y) {
return Math.abs(x - CX) <= VR && (z <= CZ - 9 || z >= CZ + 9) && y >= walkY && y <= 24;
}
for (x = CX - DR; x <= CX + DR; x++) {
for (z = CZ - DR; z <= CZ + DR; z++) {
if (!onOctEdge(x, z)) continue;
for (y = walkY; y <= drumTop; y++) {
if (isDrumOpening(x, z, y)) continue;
if (x === BX2 + 1 && z >= CZ - 1 && z <= CZ + 1 && y <= walkY + 2) continue; // door to boiler house
if (y <= plinthTop) pb(x, y, z, plinthPal);
else if (y === drumTop || (x + z) % 4 === 0) pb(x, y, z, ironPal);
else pb(x, y, z, glassPal);
}
// buttress piers with a stone cap — facade depth
if ((x + z) % 6 === 0 && !isDrumOpening(x, z, walkY)) {
for (y = walkY; y <= plinthTop + 3; y++) {
pb(x + (x > CX ? 1 : (x < CX ? -1 : 0)), y, z + (z > CZ ? 1 : (z < CZ ? -1 : 0)), brickPal);
}
}
}
}
// close the drum face above the nave openings (no sky gap at the junction)
for (z = CZ - DR; z <= CZ + DR; z++) {
for (x = CX - DR; x <= CX + DR; x++) {
if (!onOctEdge(x, z)) continue;
for (y = 25; y <= drumTop; y++) if (!inNave(x, z)) pb(x, y, z, (x + z) % 4 === 0 ? ironPal : glassPal);
}
}
// === DOME: drum cornice + stacked shrinking rings + crown (build-rules "Clean Dome") ===
makeCylinder(CX, drumTop + 1, CZ, brickPal, DR + 1, 1, false); // 1-block cornice overhang ring
makeCylinder(CX, drumTop + 1, CZ, ironPal, DR, 1, true);
var ringR = [12, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2];
for (i = 0; i < ringR.length; i++) {
makeCylinder(CX, domeBaseY + i, CZ, (i % 3 === 0) ? ironPal : glassPal, ringR[i], 1, true);
}
makeCylinder(CX, domeBaseY + ringR.length, CZ, ironPal, 2, 1, false);
// lantern cupola + finial
makeCylinder(CX, domeBaseY + ringR.length + 1, CZ, glassPal, 2, 3, true);
makeCylinder(CX, domeBaseY + ringR.length + 4, CZ, ironPal, 3, 1, false);
makeCone(CX, domeBaseY + ringR.length + 5, CZ, ironPal, 3, 4, false);
pb(CX, domeBaseY + ringR.length + 10, CZ, "lightning_rod");
// === BOILER HOUSE ANNEXE (brick, gable roof, chimney) ===
for (x = BX1; x <= BX2; x++) {
for (z = BZ1; z <= BZ2; z++) {
var edge = (x === BX1 || x === BX2 || z === BZ1 || z === BZ2);
if (!edge) continue;
for (y = walkY; y <= walkY + 6; y++) {
if (x === BX1 && z >= CZ - 1 && z <= CZ + 1 && y <= walkY + 2) continue; // west service door
if ((x === BX1 || x === BX2) && (z === BZ1 + 3 || z === BZ2 - 3) && y >= walkY + 2 && y <= walkY + 4) { pb(x, y, z, "glass_pane"); continue; }
if ((z === BZ1 || z === BZ2) && (x === BX1 + 3 || x === BX2 - 3) && y >= walkY + 2 && y <= walkY + 4) { pb(x, y, z, "glass_pane"); continue; }
pb(x, y, z, brickPal);
}
// pilaster relief every 4
if ((x + z) % 4 === 0) for (y = walkY; y <= walkY + 6; y++) pb(x + (x === BX1 ? -1 : (x === BX2 ? 1 : 0)), y, z + (z === BZ1 ? -1 : (z === BZ2 ? 1 : 0)), brickPal);
}
}
placeGableRoof(BX1, BX2, BZ1, BZ2, walkY + 7, "deepslate_tile_stairs", "deepslate_tile_slab", "bricks");
fill(BX1 + 1, walkY, BZ1 + 1, BX2 - 1, walkY + 8, BZ2 - 1, "air");
fill(BX1 + 1, floorY, BZ1 + 1, BX2 - 1, floorY, BZ2 - 1, "polished_blackstone");
// chimney
for (y = walkY; y <= 34; y++) makeCylinder(BX1 + 2, y, BZ1 + 2, brickPal, 2, 1, y > walkY + 8);
makeCylinder(BX1 + 2, 35, BZ1 + 2, "deepslate_tiles", 2, 1, true);
ps(BX1 + 2, 36, BZ1 + 2, "campfire[lit=true]");
// service doors
ps(BX1, walkY, CZ, "spruce_door[facing=west,half=lower,hinge=left]");
ps(BX1, walkY + 1, CZ, "spruce_door[facing=west,half=upper,hinge=left]");
ps(BX2 + 1, walkY, CZ, "spruce_door[facing=east,half=lower,hinge=right]");
ps(BX2 + 1, walkY + 1, CZ, "spruce_door[facing=east,half=upper,hinge=right]");
// boiler house interior
ps(BX1 + 2, walkY, BZ2 - 2, "blast_furnace[facing=north,lit=true]");
ps(BX1 + 3, walkY, BZ2 - 2, "furnace[facing=north,lit=true]");
ps(BX1 + 4, walkY, BZ2 - 2, "furnace[facing=north,lit=false]");
pb(BX1 + 6, walkY, BZ2 - 2, "barrel");
pb(BX1 + 7, walkY, BZ2 - 2, "chest");
pb(BX1 + 8, walkY, BZ1 + 2, "crafting_table");
ps(BX1 + 9, walkY, BZ1 + 2, "anvil[facing=south]");
pb(BX1 + 5, walkY, BZ1 + 1, "cauldron");
rug(BX1 + 5, walkY, CZ - 1, 3, 3, "brown", "gray");
pb(BX1 + 5, walkY + 6, CZ, "bricks");
ps(BX1 + 5, walkY + 5, CZ, "lantern[hanging=true]");
for (i = 0; i < 2; i++) { pb(BX1 + 2 + i * 6, walkY + 6, BZ2 - 3, "bricks"); ps(BX1 + 2 + i * 6, walkY + 5, BZ2 - 3, "lantern[hanging=true]"); }
// === ARCHED ENTRANCE DOORS (north + south ends of the nave) ===
function grandDoor(dz, facing, inward) {
var xx, yy;
fill(CX - 1, walkY, dz, CX, walkY + 3, dz, "air");
ps(CX - 1, walkY, dz, "dark_oak_door[facing=" + facing + ",half=lower,hinge=left]");
ps(CX - 1, walkY + 1, dz, "dark_oak_door[facing=" + facing + ",half=upper,hinge=left]");
ps(CX, walkY, dz, "dark_oak_door[facing=" + facing + ",half=lower,hinge=right]");
ps(CX, walkY + 1, dz, "dark_oak_door[facing=" + facing + ",half=upper,hinge=right]");
pb(CX - 1, walkY + 2, dz, "green_concrete"); pb(CX, walkY + 2, dz, "green_concrete");
pb(CX - 1, walkY + 3, dz, glassPal); pb(CX, walkY + 3, dz, glassPal);
for (yy = walkY; yy <= walkY + 5; yy++) { pb(CX - 2, yy, dz, brickPal); pb(CX + 1, yy, dz, brickPal); }
for (xx = CX - 2; xx <= CX + 1; xx++) ps(xx, walkY + 5, dz + inward * -1, "brick_slab[type=top]");
// porch canopy on iron posts
for (xx = CX - 2; xx <= CX + 1; xx++) pb(xx, walkY + 5, dz + inward * -2, "green_concrete");
pb(CX - 2, walkY, dz + inward * -2, "green_concrete"); pb(CX + 1, walkY, dz + inward * -2, "green_concrete");
pb(CX - 2, walkY + 1, dz + inward * -2, "green_concrete"); pb(CX + 1, walkY + 1, dz + inward * -2, "green_concrete");
pb(CX - 2, walkY + 2, dz + inward * -2, "green_concrete"); pb(CX + 1, walkY + 2, dz + inward * -2, "green_concrete");
pb(CX - 2, walkY + 3, dz + inward * -2, "green_concrete"); pb(CX + 1, walkY + 3, dz + inward * -2, "green_concrete");
pb(CX - 2, walkY + 4, dz + inward * -2, "green_concrete"); pb(CX + 1, walkY + 4, dz + inward * -2, "green_concrete");
}
grandDoor(NZ1, "north", 1);
grandDoor(SZ2, "south", -1);
// === GALLERY RING + L-SHAPED STAIR ===
for (x = CX - DR; x <= CX + DR; x++) {
for (z = CZ - DR; z <= CZ + DR; z++) {
if (inOctR(x, z, DR - 1) && !inOctR(x, z, 7)) pb(x, galFloorY, z, "spruce_planks");
}
}
for (x = CX - DR; x <= CX + DR; x++) {
for (z = CZ - DR; z <= CZ + DR; z++) {
if (!inOctR(x, z, DR - 1) || inOctR(x, z, 7)) continue;
if (inOctR(x + 1, z, 7) || inOctR(x - 1, z, 7) || inOctR(x, z + 1, 7) || inOctR(x, z - 1, 7)) {
pb(x, galWalkY, z, "iron_bars"); pb(x, galWalkY + 1, z, "iron_bars");
}
if ((x + z) % 7 === 0) for (y = walkY; y < galFloorY; y++) pb(x, y, z, "green_concrete"); // slim iron columns
}
}
var s1 = staircase(NX1 + 2, NZ2 - 12, walkY, walkY + 4, "south", {width: 2, material: "spruce_stairs"});
landing(NX1 + 2, walkY + 4, NZ2 - 6, 3, 3, "spruce_planks");
var s2 = staircase(NX1 + 3, NZ2 - 5, walkY + 4, galWalkY, "south", {width: 2, material: "spruce_stairs"});
// deck connecting the stair head to the ring
fill(NX1 + 2, galFloorY, NZ2 - 2, NX1 + 5, galFloorY, CZ - 8, "spruce_planks");
for (z = NZ2 - 2; z <= CZ - 8; z++) { pb(NX1 + 1, galWalkY, z, "iron_bars"); pb(NX1 + 6, galWalkY, z, "iron_bars"); }
// === PLANTING HALL ===
function palm(px, py, pz, hh) {
var kk, tx, ty, dirs, ddx2, ddz2;
for (kk = 0; kk < hh; kk++) pb(px + (kk > hh * 0.65 ? 1 : 0), py + kk, pz, kk < 2 ? "jungle_log" : "stripped_jungle_log");
tx = px + 1; ty = py + hh - 1;
dirs = [[1,0],[-1,0],[0,1],[0,-1],[1,1],[-1,-1],[1,-1],[-1,1]];
for (kk = 0; kk < dirs.length; kk++) {
ddx2 = dirs[kk][0]; ddz2 = dirs[kk][1];
ps(tx + ddx2, ty, pz + ddz2, "jungle_leaves[persistent=true]");
ps(tx + ddx2 * 2, ty - 1, pz + ddz2 * 2, "jungle_leaves[persistent=true]");
ps(tx + ddx2 * 3, ty - 2, pz + ddz2 * 3, "jungle_leaves[persistent=true]");
}
ps(tx, ty, pz, "jungle_leaves[persistent=true]"); ps(tx, ty + 1, pz, "jungle_leaves[persistent=true]");
}
function bed(x1, z1, x2, z2) {
var xx, zz;
for (xx = x1; xx <= x2; xx++) for (zz = z1; zz <= z2; zz++) {
pb(xx, floorY, zz, (xx + zz) % 4 === 0 ? "coarse_dirt" : "podzol");
if ((xx * 3 + zz * 5) % 6 === 0) ps(xx, walkY, zz, "fern");
else if ((xx * 7 + zz) % 8 === 0) pb(xx, walkY, zz, "azalea");
else if ((xx + zz * 3) % 7 === 0) ps(xx, walkY, zz, "grass");
else if ((xx * 2 + zz) % 11 === 0) pb(xx, walkY, zz, "big_dripleaf");
}
for (xx = x1 - 1; xx <= x2 + 1; xx++) { ps(xx, walkY, z1 - 1, "brick_slab[type=bottom]"); ps(xx, walkY, z2 + 1, "brick_slab[type=bottom]"); }
for (zz = z1 - 1; zz <= z2 + 1; zz++) { ps(x1 - 1, walkY, zz, "brick_slab[type=bottom]"); ps(x2 + 1, walkY, zz, "brick_slab[type=bottom]"); }
}
bed(NX1 + 2, NZ1 + 3, NX1 + 6, NZ1 + 8);
bed(NX2 - 6, NZ1 + 3, NX2 - 2, NZ1 + 8);
bed(NX2 - 6, NZ1 + 12, NX2 - 2, NZ1 + 18);
bed(NX1 + 2, SZ1 + 3, NX1 + 6, SZ1 + 9);
bed(NX2 - 6, SZ1 + 3, NX2 - 6 + 4, SZ1 + 9);
bed(NX1 + 2, SZ2 - 10, NX1 + 6, SZ2 - 4);
bed(NX2 - 6, SZ2 - 10, NX2 - 2, SZ2 - 4);
palm(NX1 + 3, walkY, NZ1 + 5, 9);
palm(NX2 - 5, walkY, NZ1 + 6, 11);
palm(NX2 - 5, walkY, NZ1 + 15, 8);
palm(NX1 + 3, walkY, SZ1 + 5, 10);
palm(NX2 - 5, walkY, SZ1 + 6, 9);
palm(NX1 + 3, walkY, SZ2 - 7, 8);
palm(NX2 - 5, walkY, SZ2 - 7, 11);
// drum: octagonal pond + giant palms + tree ferns
makeCylinder(CX, floorY, CZ, "prismarine_bricks", 6, 1, false);
makeCylinder(CX, floorY, CZ, "water", 5, 1, false);
makeCylinder(CX, floorY + 1, CZ, "prismarine_brick_wall", 6, 1, true);
fill(CX, floorY + 1, CZ, CX, floorY + 3, CZ, "prismarine_bricks");
ps(CX, floorY + 4, CZ, "water");
for (i = 0; i < 6; i++) ps(CX - 3 + i, floorY + 1, CZ + (i % 2 === 0 ? 3 : -3), "lily_pad");
palm(CX - 9, walkY, CZ - 8, 14);
palm(CX + 8, walkY, CZ + 7, 15);
palm(CX - 9, walkY, CZ + 7, 13);
palm(CX + 8, walkY, CZ - 8, 14);
bed(CX - 10, CZ - 9, CX - 7, CZ - 6);
bed(CX + 7, CZ + 5, CX + 10, CZ + 8);
bed(CX - 10, CZ + 5, CX - 7, CZ + 8);
bed(CX + 7, CZ - 9, CX + 10, CZ - 6);
// benches + potting tables
for (i = 0; i < 3; i++) {
chairStair(CX - 2, walkY, NZ1 + 6 + i * 8, "spruce_stairs", "east");
chairStair(CX + 2, walkY, SZ1 + 6 + i * 8, "spruce_stairs", "west");
}
for (i = 0; i < 3; i++) {
pb(NX1 + 8, walkY, SZ1 + 14 + i, "spruce_fence");
ps(NX1 + 8, walkY + 1, SZ1 + 14 + i, "spruce_slab[type=bottom]");
pb(NX2 - 8, walkY, NZ1 + 14 + i, "spruce_fence");
ps(NX2 - 8, walkY + 1, NZ1 + 14 + i, "spruce_slab[type=bottom]");
}
for (i = 0; i < 4; i++) { pb(NX1 + 9, walkY, NZ1 + 4 + i * 3, "flower_pot"); pb(NX2 - 9, walkY, SZ2 - 4 - i * 3, "flower_pot"); }
// gallery planters + seats
for (i = 0; i < 6; i++) { pb(CX - 9 + i * 3, galWalkY, CZ - 9, "flower_pot"); pb(CX - 9 + i * 3, galWalkY, CZ + 9, "flower_pot"); }
chairStair(CX + 9, galWalkY, CZ, "spruce_stairs", "west");
chairStair(CX - 9, galWalkY, CZ, "spruce_stairs", "east");
// === LIGHTING (iron_chain, 1.21.11+) ===
function hangLantern(lx, ly, lz, n) {
var kk;
for (kk = 0; kk < n; kk++) ps(lx, ly - kk, lz, "iron_chain[axis=y]");
ps(lx, ly - n, lz, "lantern[hanging=true]");
}
for (i = 0; i < 6; i++) { hangLantern(CX, SPRING - 1, NZ1 + 3 + i * 4, 2); hangLantern(CX, SPRING - 1, SZ1 + 3 + i * 4, 2); }
hangLantern(CX, domeBaseY - 2, CZ, 5);
hangLantern(CX - 7, domeBaseY - 3, CZ - 7, 3);
hangLantern(CX + 7, domeBaseY - 3, CZ + 7, 3);
for (i = 0; i < 4; i++) { pb(CX - 6 + i * 4, walkY, CZ - 11, "bricks"); ps(CX - 6 + i * 4, walkY + 1, CZ - 11, "lantern"); }
for (i = 0; i < 4; i++) { pb(CX - 9 + i * 6, galWalkY, CZ - 6, "green_concrete"); ps(CX - 9 + i * 6, galWalkY + 1, CZ - 6, "lantern"); }
// === PARK: paths, parterres, lamps, trees ===
for (z = SZ2 + 1; z <= SZ2 + 11; z++) for (x = CX - 2; x <= CX + 1; x++) {
pb(x, groundY, z, (x + z) % 5 === 0 ? "cobblestone" : "gravel");
fill(x, groundY + 1, z, x, groundY + 3, z, "air");
}
for (z = NZ1 - 11; z < NZ1; z++) for (x = CX - 2; x <= CX + 1; x++) {
pb(x, groundY, z, (x + z) % 5 === 0 ? "cobblestone" : "gravel");
fill(x, groundY + 1, z, x, groundY + 3, z, "air");
}
function lamp(lx, lz) {
pb(lx, groundY + 1, lz, "cobblestone_wall"); pb(lx, groundY + 2, lz, "cobblestone_wall");
pb(lx, groundY + 3, lz, "green_concrete"); ps(lx, groundY + 4, lz, "lantern");
}
lamp(CX - 4, SZ2 + 5); lamp(CX + 3, SZ2 + 5); lamp(CX - 4, NZ1 - 5); lamp(CX + 3, NZ1 - 5);
lamp(NX2 + 6, CZ - 10); lamp(NX2 + 6, CZ + 10);
function parterre(px, pz) {
var xx, zz;
for (xx = px; xx < px + 6; xx++) for (zz = pz; zz < pz + 6; zz++) {
if (xx === px || xx === px + 5 || zz === pz || zz === pz + 5) ps(xx, groundY + 1, zz, "stone_brick_slab[type=bottom]");
else { pb(xx, groundY, zz, "coarse_dirt"); ps(xx, groundY + 1, zz, (xx + zz) % 3 === 0 ? "red_tulip" : ((xx + zz) % 3 === 1 ? "oxeye_daisy" : "cornflower")); }
}
}
parterre(NX2 + 4, CZ - 4); parterre(NX2 + 12, CZ - 22); parterre(NX2 + 12, CZ + 14);
parterre(CX - 12, SZ2 + 4); parterre(CX + 6, NZ1 - 10);
function parkTree(tx, tz, hh) {
var kk;
for (kk = 1; kk <= hh; kk++) pb(tx, groundY + kk, tz, "oak_log");
makeSphere(tx, groundY + hh + 2, tz, "oak_leaves[persistent=true]", 3, false);
makeSphere(tx + 1, groundY + hh, tz - 1, "oak_leaves[persistent=true]", 2, false);
}
parkTree(NX2 + 10, CZ - 12, 6); parkTree(NX2 + 14, CZ + 4, 7);
parkTree(BX1 - 6, CZ - 16, 6); parkTree(BX1 - 5, CZ + 14, 5);
parkTree(CX + 12, NZ1 - 8, 6); parkTree(CX - 14, SZ2 + 8, 7);
// hedge border along the park edge
for (z = NZ1 - 12; z <= SZ2 + 12; z += 2) { ps(NX2 + 18, groundY + 1, z, "oak_leaves[persistent=true]"); ps(BX1 - 9, groundY + 1, z, "oak_leaves[persistent=true]"); }
chairStair(NX2 + 7, groundY + 1, CZ - 14, "spruce_stairs", "west");
chairStair(NX2 + 7, groundY + 1, CZ + 14, "spruce_stairs", "west");