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.
73 lines
6.6 KiB
JavaScript
73 lines
6.6 KiB
JavaScript
// features/mb_trees.js christmas / light / potted trees as multiblocks.
|
|
|
|
import { BlockPermutation, ItemStack, isCreative, getDir, safeGetBlock } from "../core/mc.js";
|
|
import { grid, fcCanReplace } from "../core/grid.js";
|
|
import { undoPlace, breakAir } from "../core/fx.js";
|
|
import { onPlace, onBreak } from "../core/events.js";
|
|
|
|
// Rainbow and white are INDEPENDENT block sets (white id = rainbow id + "_w"), each registered as a plain multiblock no
|
|
// rzb_dcs:tc state. Pick-block therefore returns the correct item (and name) natively; brush.js converts between the two.
|
|
|
|
// --- grid trees (christmas / light): a 3D cell grid placed from the anchor cell ---
|
|
function registerGridTree(cfg) { // cfg: ANCHOR, ANCHOR_KEY, CELLS, cellWorld, anchorFrom, parse, label, actionBar?
|
|
onPlace((ev) => {
|
|
const b = ev.block; if (b?.typeId !== cfg.ANCHOR) return;
|
|
const dim = b.dimension, dir = getDir(b.permutation);
|
|
for (const c of Object.keys(cfg.CELLS)) { if (c === cfg.ANCHOR_KEY) continue; const nb = safeGetBlock(dim, cfg.cellWorld(c, b.x, b.y, b.z, dir)); if (!fcCanReplace(nb)) { undoPlace(b, ev.player, cfg.ANCHOR, cfg.label); return; } }
|
|
let placed = 0;
|
|
for (const c of Object.keys(cfg.CELLS)) { if (c === cfg.ANCHOR_KEY) continue; const nb = dim.getBlock(cfg.cellWorld(c, b.x, b.y, b.z, dir)); if (fcCanReplace(nb)) { try { nb.setPermutation(BlockPermutation.resolve("rzb_dcs:" + c, { "minecraft:cardinal_direction": dir })); placed++; } catch {} } }
|
|
if (cfg.actionBar) { try { ev.player.onScreenDisplay.setActionBar(cfg.actionBar(placed, Object.keys(cfg.CELLS).length - 1)); } catch {} }
|
|
});
|
|
onBreak((ev) => {
|
|
const cell = cfg.parse(ev.brokenBlockPermutation?.type?.id || ""); if (!cell) return;
|
|
const b = ev.block, dir = getDir(ev.brokenBlockPermutation), a = cfg.anchorFrom(cell, b.x, b.y, b.z, dir);
|
|
for (const c of Object.keys(cfg.CELLS)) { if (c === cell) continue; const nb = safeGetBlock(b.dimension, cfg.cellWorld(c, a.x, a.y, a.z, dir)); if (nb && cfg.parse(nb.typeId) === c) { try { breakAir(nb); } catch {} } }
|
|
if (ev.player && !isCreative(ev.player)) { try { b.dimension.spawnItem(new ItemStack(cfg.ANCHOR, 1), { x: b.x + 0.5, y: b.y + 0.5, z: b.z + 0.5 }); } catch {} }
|
|
});
|
|
}
|
|
|
|
// register a grid tree family as BOTH a rainbow set and a "_w" white set, returning the parse/grid helpers of each variant.
|
|
function gridTreeFamily(CELLS, anchorKey, label, actionBar) {
|
|
const parseIn = (M) => (id) => { if (!id || !id.startsWith("rzb_dcs:")) return null; const c = id.slice(8); return M[c] ? c : null; };
|
|
const gR = grid(CELLS, true), parseR = parseIn(CELLS);
|
|
registerGridTree({ ANCHOR: "rzb_dcs:" + anchorKey, ANCHOR_KEY: anchorKey, CELLS, cellWorld: gR.cellWorld, anchorFrom: gR.anchorFrom, parse: parseR, label, actionBar });
|
|
const CELLS_W = {}; for (const k in CELLS) CELLS_W[k + "_w"] = CELLS[k];
|
|
const gW = grid(CELLS_W, true), parseW = parseIn(CELLS_W);
|
|
registerGridTree({ ANCHOR: "rzb_dcs:" + anchorKey + "_w", ANCHOR_KEY: anchorKey + "_w", CELLS: CELLS_W, cellWorld: gW.cellWorld, anchorFrom: gW.anchorFrom, parse: parseW, label: label + " (white)", actionBar });
|
|
return { CELLS, parse: parseR, cellWorld: gR.cellWorld, anchorFrom: gR.anchorFrom, CELLS_W, parseW, cellWorldW: gW.cellWorld, anchorFromW: gW.anchorFrom };
|
|
}
|
|
|
|
export const CT_CELLS = { "ct_1_1_0_1": [0, 0, 0], "ct_1_1_0_0": [0, 0, -1], "ct_1_0_0_1": [1, 0, 0], "ct_1_1_0_2": [0, 0, 1], "ct_1_2_0_1": [-1, 0, 0], "ct_1_1_1_1": [0, 1, 0], "ct_1_1_2_1": [0, 2, 0], "ct_1_1_3_1": [0, 3, 0], "ct_1_1_1_0": [0, 1, -1], "ct_1_2_1_1": [-1, 1, 0], "ct_1_0_1_1": [1, 1, 0], "ct_1_1_1_2": [0, 1, 1], "ct_1_1_2_0": [0, 2, -1], "ct_1_0_2_1": [1, 2, 0], "ct_1_1_2_2": [0, 2, 1], "ct_1_2_0_0": [-1, 0, -1], "ct_1_0_0_0": [1, 0, -1], "ct_1_0_0_2": [1, 0, 1], "ct_1_2_0_2": [-1, 0, 1], "ct_1_2_2_1": [-1, 2, 0], "ct_1_1_3_2": [0, 3, 1], "ct_1_1_3_0": [0, 3, -1], "ct_1_0_3_1": [1, 3, 0], "ct_1_2_2_2": [-1, 2, 1], "ct_1_2_3_2": [-1, 3, 1], "ct_1_2_2_0": [-1, 2, -1], "ct_1_0_2_2": [1, 2, 1], "ct_1_2_3_0": [-1, 3, -1], "ct_1_0_3_2": [1, 3, 1], "ct_1_2_3_1": [-1, 3, 0], "ct_1_0_2_0": [1, 2, -1], "ct_1_0_3_0": [1, 3, -1], "ct_1_2_1_0": [-1, 1, -1], "ct_1_0_1_2": [1, 1, 1], "ct_1_2_1_2": [-1, 1, 1], "ct_1_0_1_0": [1, 1, -1] };
|
|
const CT = gridTreeFamily(CT_CELLS, "ct_1_1_0_1", "christmas tree", (n, tot) => "§aChristmas tree: placed " + n + "/" + tot + " cells");
|
|
export const ctParse = CT.parse, ctCellWorld = CT.cellWorld, ctAnchorFrom = CT.anchorFrom;
|
|
export const CT_CELLS_W = CT.CELLS_W, ctParseW = CT.parseW, ctCellWorldW = CT.cellWorldW, ctAnchorFromW = CT.anchorFromW;
|
|
|
|
export const LT_CELLS = { "lt_1_1_2_1": [0, 2, 0], "lt_1_1_1_1": [0, 1, 0], "lt_1_1_0_1": [0, 0, 0], "lt_1_2_0_0": [-1, 0, -1], "lt_1_0_0_2": [1, 0, 1], "lt_1_0_0_0": [1, 0, -1], "lt_1_2_0_2": [-1, 0, 1], "lt_1_0_0_1": [1, 0, 0], "lt_1_2_0_1": [-1, 0, 0], "lt_1_1_0_2": [0, 0, 1], "lt_1_1_0_0": [0, 0, -1] };
|
|
const LT = gridTreeFamily(LT_CELLS, "lt_1_1_0_1", "light tree");
|
|
export const ltParse = LT.parse, ltCellWorld = LT.cellWorld, ltAnchorFrom = LT.anchorFrom;
|
|
export const LT_CELLS_W = LT.CELLS_W, ltParseW = LT.parseW, ltCellWorldW = LT.cellWorldW, ltAnchorFromW = LT.anchorFromW;
|
|
|
|
// --- potted christmas tree: 2-cell vertical multiblock (pct_b pot/anchor at Y, pct_t tree at Y+1) ---
|
|
function registerVerticalTree(anchorId, topId, label) {
|
|
onPlace((ev) => {
|
|
const b = ev.block; if (b?.typeId !== anchorId) return;
|
|
const dim = b.dimension, dir = getDir(b.permutation);
|
|
const top = safeGetBlock(dim, { x: b.x, y: b.y + 1, z: b.z });
|
|
if (!fcCanReplace(top)) { undoPlace(b, ev.player, anchorId, label); return; }
|
|
try { top.setPermutation(BlockPermutation.resolve(topId, { "minecraft:cardinal_direction": dir })); } catch {}
|
|
});
|
|
onBreak((ev) => {
|
|
const id = ev.brokenBlockPermutation?.type?.id || ""; if (id !== anchorId && id !== topId) return;
|
|
const b = ev.block;
|
|
const sibY = id === anchorId ? b.y + 1 : b.y - 1, want = id === anchorId ? topId : anchorId;
|
|
const nb = safeGetBlock(b.dimension, { x: b.x, y: sibY, z: b.z });
|
|
if (nb && nb.typeId === want) { try { breakAir(nb); } catch {} }
|
|
if (ev.player && !isCreative(ev.player)) { try { b.dimension.spawnItem(new ItemStack(anchorId, 1), { x: b.x + 0.5, y: b.y + 0.5, z: b.z + 0.5 }); } catch {} }
|
|
});
|
|
}
|
|
export const PCT_ANCHOR = "rzb_dcs:pct_b", PCT_TOP = "rzb_dcs:pct_t", PCT_ANCHOR_W = "rzb_dcs:pct_b_w", PCT_TOP_W = "rzb_dcs:pct_t_w";
|
|
export const pctParse = (id) => (id === PCT_ANCHOR || id === PCT_TOP) ? id.slice(8) : null;
|
|
export const pctParseW = (id) => (id === PCT_ANCHOR_W || id === PCT_TOP_W) ? id.slice(8) : null;
|
|
registerVerticalTree(PCT_ANCHOR, PCT_TOP, "potted christmas tree");
|
|
registerVerticalTree(PCT_ANCHOR_W, PCT_TOP_W, "potted christmas tree (white)");
|