// === BUILD PLAN ===
// Subject: red axial-flow combine harvester, mid-harvest, facing NORTH (-Z)
// Footprint: header 27 wide (x14..40) x 5 deep (z5..9) | body 11 wide (x22..32) x 22 deep (z14..36)
// total length z2..z40, total height Y13..Y31
//
// SIDE SILHOUETTE (Z ->, Y up): FRONT SILHOUETTE (X ->, Y up):
// ___tank___ .....[=cab=]......
// [cab]| |__engine__ ...[==tank==].....
// __| | | <====[===body====]====> auger swung out LEFT
// /reel | | .OO..........oo... big front / small rear
// |head|=====body===========| header spans ~2.5x the body width
// (O) (O) (o)
//
// MATERIALS PLAN:
// body/header : red_concrete(78)+red_terracotta(22) noise — flat single red reads as plastic
// trim/frame : black/gray/polished_blackstone — dark value break so it reads as a machine
// metal : light_gray_concrete + iron_block (auger, cutter bar, ladder, screens)
// tyres : black_concrete/polished_blackstone/blackstone + lug tread every 2
// field : uncut = farmland + wheat[age=7] (z<10) | stubble = dirt_path/coarse_dirt +
// wheat[age=0] stubs | hay_block windrow trailing behind + wheel tramlines
// Cab interior: seat (chairStair), steering column, yield monitor, controls, dome light
// === END PLAN ===
var padY = 12, groundY = padY + 1;
var cxm = 27;
var x, y, z, i, t, dz, dy;
var redMain = noisePalette([{block:'red_concrete',weight:78},{block:'red_terracotta',weight:22}], {seed:5, freq:0.22});
var darkTrim = noisePalette([{block:'black_concrete',weight:60},{block:'gray_concrete',weight:25},{block:'polished_blackstone',weight:15}], {seed:8, freq:0.25});
var metal = noisePalette([{block:'light_gray_concrete',weight:55},{block:'iron_block',weight:25},{block:'gray_concrete',weight:20}], {seed:3, freq:0.25});
var tyre = noisePalette([{block:'black_concrete',weight:70},{block:'polished_blackstone',weight:20},{block:'blackstone',weight:10}], {seed:11, freq:0.3});
var stubble = noisePalette([{block:'dirt_path',weight:50},{block:'coarse_dirt',weight:30},{block:'podzol',weight:20}], {seed:14, freq:0.1});
// resolve a palette to a block id at the call site (pb() must never receive a function)
function P(m, px, py, pz) { if (typeof m === 'function') return m(px, py, pz); return m; }
function put(px, py, pz, m) { pb(px, py, pz, P(m, px, py, pz)); }
// ================= FIELD =================
var land = blob(30, 30, 34, {irregularity:0.35, seed:6});
var hfn = hills({base: padY, amp: 2, scale: 0.035, seed: 12});
var pad = flatten(hfn, {x0:0, z0:0, x1:60, z1:60}, padY, 6);
surface(land, pad, function (gx, gz) {
if (gz < 10) return 'farmland';
return stubble(gx, 0, gz);
}, {sub:'dirt', deep:'stone', depth:4});
for (x = 0; x <= 60; x++) for (z = 0; z <= 9; z++) {
if ((x * 7 + z * 5) % 17 === 0) ps(x, groundY, z, 'wheat[age=6]'); else ps(x, groundY, z, 'wheat[age=7]');
}
for (x = 0; x <= 60; x++) for (z = 10; z <= 60; z++) {
if ((x * 3 + z * 11) % 5 === 0) ps(x, groundY, z, 'wheat[age=0]');
}
for (z = 40; z <= 60; z++) {
for (x = 20; x <= 22; x++) pb(x, padY, z, 'coarse_dirt');
for (x = 32; x <= 34; x++) pb(x, padY, z, 'coarse_dirt');
}
for (z = 41; z <= 60; z++) {
var wob = ((z * 5) % 3) - 1;
for (x = cxm - 3 + wob; x <= cxm + 3 + wob; x++) if ((x + z) % 4 !== 0) ps(x, groundY, z, 'hay_block[axis=x]');
if (z % 3 === 0) ps(cxm + 4 + wob, groundY, z, 'hay_block[axis=z]');
}
// ================= WHEELS =================
function wheel(x0, cy, cz, r, thick, hubId) {
for (dz = -r - 1; dz <= r + 1; dz++) {
for (dy = -r - 1; dy <= r + 1; dy++) {
var d = Math.sqrt(dz * dz + dy * dy);
if (d > r + 0.45) continue;
var mat = tyre;
if (d <= r - 1.25 && d < r * 0.45) mat = hubId;
for (t = 0; t < thick; t++) put(x0 + t, cy + dy, cz + dz, mat);
if (d > r - 0.55 && ((dz + dy + cz) % 2 === 0)) {
pb(x0, cy + dy, cz + dz, 'blackstone');
pb(x0 + thick - 1, cy + dy, cz + dz, 'blackstone');
}
}
}
}
wheel(19, 17, 20, 4, 3, 'light_gray_concrete');
wheel(33, 17, 20, 4, 3, 'light_gray_concrete');
wheel(21, 15, 34, 2, 2, 'gray_concrete');
wheel(32, 15, 34, 2, 2, 'gray_concrete');
fill(22, 17, 20, 32, 17, 20, darkTrim);
fill(23, 15, 34, 31, 15, 34, darkTrim);
// ================= BODY =================
fill(22, 18, 14, 32, 26, 36, redMain);
fill(23, 19, 15, 31, 25, 35, 'air');
fill(22, 18, 14, 32, 18, 36, darkTrim);
for (z = 17; z <= 34; z += 5) {
fill(22, 20, z, 22, 24, z + 2, 'red_terracotta');
fill(32, 20, z, 32, 24, z + 2, 'red_terracotta');
ps(21, 22, z + 1, 'iron_trapdoor[facing=east,half=bottom,open=false]');
ps(33, 22, z + 1, 'iron_trapdoor[facing=west,half=bottom,open=false]');
}
fill(22, 25, 14, 22, 25, 36, darkTrim); fill(32, 25, 14, 32, 25, 36, darkTrim);
fill(22, 19, 14, 22, 19, 36, darkTrim); fill(32, 19, 14, 32, 19, 36, darkTrim);
for (z = 14; z <= 36; z++) {
ps(22, 26, z, 'polished_blackstone_slab[type=bottom]');
ps(32, 26, z, 'polished_blackstone_slab[type=bottom]');
}
for (z = 15; z <= 25; z++) {
ps(21, 22, z, 'red_concrete');
ps(33, 22, z, 'red_concrete');
ps(20, 22, z, 'polished_blackstone_slab[type=top]');
ps(34, 22, z, 'polished_blackstone_slab[type=top]');
}
// ================= FEEDER HOUSE =================
for (i = 0; i <= 5; i++) fill(24, 17 + i, 14 - i, 30, 21 + i, 14 - i, redMain);
fill(25, 18, 9, 29, 21, 13, 'air');
for (i = 0; i <= 5; i++) { ps(23, 21 + i, 14 - i, 'polished_blackstone_slab[type=bottom]'); ps(31, 21 + i, 14 - i, 'polished_blackstone_slab[type=bottom]'); }
fill(23, 19, 12, 23, 19, 15, metal); fill(31, 19, 12, 31, 19, 15, metal);
// ================= HEADER =================
fill(14, 13, 5, 40, 13, 9, redMain);
fill(14, 14, 9, 40, 16, 9, redMain);
fill(14, 13, 5, 14, 16, 9, redMain);
fill(40, 13, 5, 40, 16, 9, redMain);
for (x = 14; x <= 40; x++) {
ps(x, 14, 9, 'polished_blackstone_slab[type=bottom]');
ps(x, 13, 5, 'polished_andesite_slab[type=bottom]');
ps(x, 13, 4, 'iron_trapdoor[facing=north,half=bottom,open=false]');
}
for (x = 15; x <= 39; x++) {
put(x, 15, 8, metal);
if (x % 2 === 0) ps(x, 15, 7, 'iron_trapdoor[facing=north,half=bottom,open=true]');
else ps(x, 16, 8, 'light_gray_concrete_slab[type=bottom]');
}
for (x = 15; x <= 39; x++) {
ps(x, 17, 6, 'stripped_oak_log[axis=x]');
ps(x, 19, 6, 'oak_slab[type=bottom]');
ps(x, 17, 4, 'oak_slab[type=bottom]');
ps(x, 15, 6, 'oak_slab[type=top]');
ps(x, 17, 8, 'oak_slab[type=bottom]');
if (x % 2 === 0) { ps(x, 18, 4, 'iron_bars'); ps(x, 16, 4, 'iron_bars'); }
}
var armX = [16, 27, 38];
for (i = 0; i < armX.length; i++) {
put(armX[i], 18, 9, metal); put(armX[i], 18, 8, metal); put(armX[i], 18, 7, metal); put(armX[i], 17, 7, metal);
}
function divider(dx) {
ps(dx, 14, 4, 'white_concrete'); ps(dx, 14, 3, 'white_concrete');
ps(dx, 13, 3, 'white_concrete'); ps(dx, 13, 2, 'red_concrete');
ps(dx, 15, 5, 'white_concrete_slab[type=bottom]');
ps(dx, 14, 2, 'polished_andesite_slab[type=bottom]');
}
divider(14); divider(40);
// ================= CAB =================
fill(24, 22, 13, 30, 28, 18, darkTrim);
fill(25, 23, 14, 29, 27, 17, 'air');
fill(24, 22, 13, 30, 22, 18, metal);
fill(24, 28, 13, 30, 28, 18, 'white_concrete');
for (y = 23; y <= 27; y++) {
for (x = 25; x <= 29; x++) ps(x, y, 13, 'light_blue_stained_glass_pane');
for (z = 14; z <= 17; z++) { ps(24, y, z, 'light_blue_stained_glass_pane'); ps(30, y, z, 'light_blue_stained_glass_pane'); }
ps(26, y, 18, 'light_blue_stained_glass_pane'); ps(28, y, 18, 'light_blue_stained_glass_pane');
}
fill(24, 23, 18, 24, 27, 18, darkTrim); fill(30, 23, 18, 30, 27, 18, darkTrim);
chairStair(27, 23, 16, 'spruce_stairs', 'north');
ps(27, 24, 15, 'iron_trapdoor[facing=north,half=top,open=false]');
ps(28, 23, 14, 'stone_button[face=wall,facing=north]');
ps(29, 24, 15, 'black_stained_glass_pane');
ps(26, 23, 14, 'gray_carpet'); ps(28, 23, 16, 'gray_carpet');
pb(27, 27, 16, 'sea_lantern');
pb(25, 29, 13, 'sea_lantern'); pb(29, 29, 13, 'sea_lantern');
ps(27, 29, 18, 'shroomlight');
for (i = 0; i <= 5; i++) ps(23, 17 + i, 17 - i, 'iron_trapdoor[facing=south,half=bottom,open=false]');
fill(23, 22, 14, 23, 22, 16, metal);
for (z = 14; z <= 17; z++) ps(22, 23, z, 'iron_bars');
ps(23, 23, 17, 'iron_bars'); ps(23, 24, 17, 'iron_bars');
// ================= GRAIN TANK =================
fill(22, 27, 20, 32, 27, 31, redMain);
fill(21, 28, 20, 33, 30, 31, redMain);
fill(22, 28, 21, 32, 30, 30, 'air');
fill(22, 28, 21, 32, 28, 30, 'hay_block[axis=y]');
for (z = 20; z <= 31; z++) { ps(20, 28, z, 'polished_blackstone_slab[type=bottom]'); ps(34, 28, z, 'polished_blackstone_slab[type=bottom]'); }
for (z = 20; z <= 31; z += 2) { ps(21, 31, z, 'iron_bars'); ps(33, 31, z, 'iron_bars'); }
for (x = 21; x <= 33; x += 3) { ps(x, 31, 20, 'iron_bars'); ps(x, 31, 31, 'iron_bars'); }
// ================= UNLOADING AUGER =================
for (x = 11; x <= 21; x++) { ps(x, 29, 24, 'light_gray_concrete'); ps(x, 30, 24, 'light_gray_concrete_slab[type=bottom]'); }
for (x = 12; x <= 20; x += 2) ps(x, 28, 24, 'iron_trapdoor[facing=north,half=bottom,open=true]');
fill(11, 27, 24, 11, 29, 24, metal);
ps(11, 26, 24, 'gray_concrete');
ps(11, 25, 24, 'hopper[facing=down]');
fill(21, 28, 24, 21, 29, 24, metal);
ps(20, 30, 23, 'iron_bars'); ps(20, 30, 25, 'iron_bars');
// ================= ENGINE / EXHAUST / STRAW CHOPPER =================
fill(23, 27, 32, 31, 29, 36, darkTrim);
for (x = 24; x <= 30; x++) ps(x, 30, 34, 'iron_bars');
fill(31, 30, 33, 31, 33, 33, 'polished_blackstone_wall');
ps(31, 34, 33, 'polished_blackstone_slab[type=bottom]');
fill(23, 19, 37, 31, 24, 38, darkTrim);
for (x = 23; x <= 31; x++) ps(x, 19, 39, 'iron_bars');
for (x = 22; x <= 32; x++) ps(x, 24, 38, 'polished_blackstone_slab[type=top]');
pb(23, 26, 38, 'redstone_lamp[lit=true]'); pb(31, 26, 38, 'redstone_lamp[lit=true]');
// ================= FIELD DRESSING =================
for (z = 16; z <= 26; z++) for (x = 17; x <= 37; x++) {
if ((x * 5 + z * 3) % 9 === 0) pb(x, padY, z, 'coarse_dirt');
}
for (x = 12; x <= 42; x++) if ((x * 7) % 5 < 2) ps(x, groundY, 10, 'hay_block[axis=x]');
for (x = 8; x <= 46; x += 6) ps(x, groundY, 11, 'hay_block[axis=z]');
for (x = 0; x <= 60; x += 2) ps(x, groundY, 58, 'oak_fence');
fill(52, groundY, 50, 52, groundY + 5, 50, 'oak_log[axis=y]');
makeSphere(52, groundY + 7, 50, noisePalette([{block:'oak_leaves[persistent=true]',weight:85},{block:'birch_leaves[persistent=true]',weight:15}], {seed:4, freq:0.3}), 4, true);