You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
3.8 KiB
JavaScript
72 lines
3.8 KiB
JavaScript
// core/grid.js; the ONE rotation convention + facing tables + ground/water probes.
|
|
|
|
import { safeGetBlock } from "./mc.js";
|
|
|
|
export const RIGHT = { south: [1, 0, 0], north: [-1, 0, 0], east: [0, 0, -1], west: [0, 0, 1] };
|
|
export const FWD = { south: [0, 0, 1], north: [0, 0, -1], east: [1, 0, 0], west: [-1, 0, 0] };
|
|
|
|
// world position of a south-frame offset g given the anchor + facing. rotating=false -> raw offset (symmetric canopies um/bu/bt).
|
|
export function cellWorld(g, ax, ay, az, dir, rotating = true) {
|
|
if (!rotating) return { x: ax + g[0], y: ay + g[1], z: az + g[2] };
|
|
const R = RIGHT[dir] || RIGHT.south, F = FWD[dir] || FWD.south;
|
|
return { x: ax + g[0] * R[0] + g[2] * F[0], y: ay + g[1], z: az + g[0] * R[2] + g[2] * F[2] };
|
|
}
|
|
// inverse of cellWorld: back compute the anchor from a cell's world position + facing.
|
|
export function anchorFrom(g, x, y, z, dir, rotating = true) {
|
|
if (!rotating) return { x: x - g[0], y: y - g[1], z: z - g[2] };
|
|
const R = RIGHT[dir] || RIGHT.south, F = FWD[dir] || FWD.south;
|
|
return { x: x - g[0] * R[0] - g[2] * F[0], y: y - g[1], z: z - g[0] * R[2] - g[2] * F[2] };
|
|
}
|
|
// Bundle a cell map into ready-to-use cellWorld/anchorFrom closures (used by every multiblock family).
|
|
export function grid(cells, rotating = true) {
|
|
return {
|
|
cells,
|
|
cellWorld: (cell, ax, ay, az, dir) => cellWorld(cells[cell], ax, ay, az, dir, rotating),
|
|
anchorFrom: (cell, x, y, z, dir) => anchorFrom(cells[cell], x, y, z, dir, rotating),
|
|
};
|
|
}
|
|
|
|
// Facing / yaw tables
|
|
export const DIR_YAW = { north: 0, south: 180, east: 90, west: 270 }; // seat: player faces OUT of the seat
|
|
export const DIR_TROT = { south: 0, north: 180, east: 90, west: -90 }; // seat: block geometry transformation angle
|
|
export const DISPLAY_DIR_YAW = { north: 0, east: 90, south: 180, west: -90 }; // DecoCraft display-entity summon yaw
|
|
export const TUBE_DIR_YAW = { south: 0, west: 90, north: 180, east: -90 }; // rideable block-facing -> entity body yaw
|
|
export const displayYawToDir = (yaw) => { const y = ((yaw % 360) + 360) % 360; if (y < 45 || y >= 315) return "north"; if (y < 135) return "east"; if (y < 225) return "south"; return "west"; };
|
|
export const tubeYawToDir = (yaw) => { const y = ((yaw % 360) + 360) % 360; if (y < 45 || y >= 315) return "south"; if (y < 135) return "west"; if (y < 225) return "north"; return "east"; };
|
|
|
|
export function fcCanReplace(nb) {
|
|
if (!nb) return false;
|
|
if (nb.isAir) return true;
|
|
const t = nb.typeId || "";
|
|
if (/grass_block|dirt|podzol|mycelium|mud|farmland|clay|gravel|sand|stone|terracotta|concrete|planks|log|wool/.test(t)) return false;
|
|
return /short_grass|tall_grass|tallgrass|fern|flower|sapling|snow_layer|dead_bush|azalea|deadbush|seagrass|\bvine|leaf_litter/.test(t);
|
|
}
|
|
|
|
export function tubeWaterTop(dim, x, z, nearY) {
|
|
const isW = (b) => { try { return b.typeId.endsWith("water"); } catch { return false; } };
|
|
for (let y = Math.floor(nearY) + 3; y >= Math.floor(nearY) - 6; y--) { const b = safeGetBlock(dim, { x, y, z }); if (isW(b)) return y; }
|
|
return null;
|
|
}
|
|
|
|
export function tubeOverWater(block) {
|
|
try { if (block.isWaterlogged) return true; } catch {}
|
|
const dim = block.dimension;
|
|
for (const [dx, dy, dz] of [[0, -1, 0], [1, 0, 0], [-1, 0, 0], [0, 0, 1], [0, 0, -1]]) {
|
|
const b = safeGetBlock(dim, { x: block.x + dx, y: block.y + dy, z: block.z + dz });
|
|
try { if (b && (b.typeId.endsWith("water") || b.isWaterlogged)) return true; } catch {}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function loungerSupportY(dim, x, z, fromY, noFloat, float = 0) {
|
|
for (let y = Math.floor(fromY) + 1; y >= Math.floor(fromY) - 48; y--) {
|
|
const b = safeGetBlock(dim, { x, y, z });
|
|
if (!b) continue;
|
|
const id = b.typeId || "";
|
|
if (id.endsWith("water")) { if (noFloat) continue; return y + 1 + float; }
|
|
let air = id === "minecraft:air"; try { air = b.isAir; } catch {}
|
|
if (!air && !/water|lava/.test(id)) return y + 1;
|
|
}
|
|
return null;
|
|
}
|