66 lines
2.4 KiB
JavaScript
66 lines
2.4 KiB
JavaScript
// ==================== ХРАНИЛИЩЕ МИРА 3D — GrechkaCraft v3 ====================
|
|
// Ключ блока: "x,y,z". Единый источник для рендера, физики, сети и сейвов.
|
|
// Мир по всем трём осям: X — вперёд, Y — вверх, Z — вбок (глубина мира).
|
|
import { BLOCKS } from '../data/blocks.js';
|
|
import { state } from '../core/state.js';
|
|
|
|
const grid = state.grid; // Map: "x,y,z" => { gx, gy, gz, t, dead }
|
|
const blocks = state.blocks; // Array для перебора/рендера
|
|
|
|
function k3(gx, gy, gz) { return gx + ',' + gy + ',' + gz; }
|
|
|
|
function getBlock(gx, gy, gz) {
|
|
const b = grid.get(k3(gx, gy, gz));
|
|
if (b && b.dead) return null;
|
|
return b || null;
|
|
}
|
|
|
|
function hasBlock(gx, gy, gz) { return grid.has(k3(gx, gy, gz)); }
|
|
|
|
function isSolid(gx, gy, gz) {
|
|
const b = getBlock(gx, gy, gz);
|
|
if (!b) return false;
|
|
const def = BLOCKS[b.t];
|
|
return !!def.solid && !def.fluid && !def.decor && !def.climbable;
|
|
}
|
|
|
|
// Непрозрачный ли блок (для отсечения внутренних граней не используется — мы рендерим кубы)
|
|
function isOpaque(gx, gy, gz) {
|
|
const b = getBlock(gx, gy, gz);
|
|
if (!b) return false;
|
|
const def = BLOCKS[b.t];
|
|
return !!def.solid && !def.fluid && !def.decor && !def.climbable;
|
|
}
|
|
|
|
function setBlock(gx, gy, gz, t, isPlayerPlaced = false) {
|
|
const key = k3(gx, gy, gz);
|
|
if (grid.has(key)) return false;
|
|
const b = { gx, gy, gz, t, dead: false, active: false, fuse: 0 };
|
|
grid.set(key, b);
|
|
blocks.push(b);
|
|
if (isPlayerPlaced) {
|
|
state.placedBlocks.push({ gx, gy, gz, t });
|
|
}
|
|
state.blocksVersion = (state.blocksVersion || 0) + 1;
|
|
return true;
|
|
}
|
|
|
|
function removeBlock(gx, gy, gz) {
|
|
const key = k3(gx, gy, gz);
|
|
const b = grid.get(key);
|
|
if (!b) return null;
|
|
if (BLOCKS[b.t].unbreakable) return null;
|
|
grid.delete(key);
|
|
b.dead = true;
|
|
const wasPlayerPlaced = state.placedBlocks.some(pb => pb.gx === gx && pb.gy === gy && pb.gz === gz);
|
|
if (wasPlayerPlaced) {
|
|
state.placedBlocks = state.placedBlocks.filter(pb => !(pb.gx === gx && pb.gy === gy && pb.gz === gz));
|
|
} else {
|
|
state.removedBlocks.push({ gx, gy, gz });
|
|
}
|
|
state.blocksVersion = (state.blocksVersion || 0) + 1;
|
|
return b;
|
|
}
|
|
|
|
export { grid, blocks, k3, getBlock, hasBlock, isSolid, isOpaque, setBlock, removeBlock };
|