Worldshaper/src/worldshaperStudio/pixiSceneRebuildHelpers.ts

145 lines
5.5 KiB
TypeScript

/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
import { rebuildChunkEntrySurface } from "./pixiChunkSurfaceHelpers";
function buildChunkSurfaceOptions(state, scope, helpers) {
return {
baseTileSize: scope.baseTileSize,
chunkSize: state.chunkSize,
getTileOpacity: helpers.getTileOpacity,
getTileSurface: helpers.getTileSurface,
syncChunkEntryDimensions: helpers.syncChunkEntryDimensions,
tileSize: scope.tileSize,
};
}
export function rebuildSceneFromWorldChunks(state, scope, helpers) {
const worldContext = helpers.getWorldChunkRenderContext();
if (!worldContext) {
return false;
}
helpers.resetSceneRoots();
const chunkSurfaceOptions = buildChunkSurfaceOptions(state, scope, helpers);
const desiredKeys = new Set();
const activeLayerNumbers = new Set();
worldContext.chunks.forEach((chunk) => {
const chunkX = Math.floor(Number(chunk?.chunkX) || 0);
const chunkY = Math.floor(Number(chunk?.chunkY) || 0);
const tileX = (chunkX - worldContext.originChunkX) * worldContext.chunkWidth;
const tileY = (chunkY - worldContext.originChunkY) * worldContext.chunkHeight;
const roomLayers = Array.isArray(chunk?.roomLayers) ? chunk.roomLayers : [];
roomLayers.forEach((layerObj) => {
const layerNumber = Number(layerObj?.layer) || 0;
activeLayerNumbers.add(layerNumber);
const layerRoot = helpers.getOrCreateLayerRoot(layerNumber);
layerRoot.visible = scope.isLayerRendered(layerNumber);
const chunkKey = helpers.buildLayerChunkKey(layerNumber, chunkX, chunkY);
desiredKeys.add(chunkKey);
let entry = state.chunkEntries.get(chunkKey) || null;
if (!entry) {
entry = helpers.createChunkEntry(layerNumber, chunkX, chunkY, {
tileX,
tileY,
tileWidth: worldContext.chunkWidth,
tileHeight: worldContext.chunkHeight,
});
}
if (entry.tileX !== tileX || entry.tileY !== tileY) {
entry.tileX = tileX;
entry.tileY = tileY;
entry.sprite.x = tileX;
entry.sprite.y = tileY;
}
if (entry.tileWidth !== worldContext.chunkWidth || entry.tileHeight !== worldContext.chunkHeight) {
entry.tileWidth = worldContext.chunkWidth;
entry.tileHeight = worldContext.chunkHeight;
}
const hasContent = rebuildChunkEntrySurface(
entry,
(localX, localY) => helpers.resolveWorldChunkLayerSymbol(chunk, layerObj, localX, localY),
worldContext.chunkWidth,
worldContext.chunkHeight,
String(chunk?.backgroundTileId || ""),
chunkSurfaceOptions,
);
if (!hasContent && layerNumber > 0) {
helpers.destroyChunkEntry(entry);
desiredKeys.delete(chunkKey);
}
});
});
Array.from(state.chunkEntries.entries()).forEach(([key, entry]) => {
if (!desiredKeys.has(key)) {
helpers.destroyChunkEntry(entry);
}
});
Array.from(state.layerRoots.entries()).forEach(([layerNumber, layerRoot]) => {
if (!activeLayerNumbers.has(layerNumber)) {
state.npcSpritesById.forEach((sprite, npcId) => {
if (sprite?.parent && sprite.parent === state.entityLayerRoots.get(layerNumber)) {
state.npcSpritesById.delete(npcId);
}
});
state.entityLayerRoots.delete(layerNumber);
layerRoot.removeFromParent();
layerRoot.destroy({ children: true });
state.layerRoots.delete(layerNumber);
}
});
return true;
}
export function rebuildSceneFromRoomLayers(state, scope, helpers) {
state.chunkEntries.forEach((entry) => {
helpers.destroyChunkEntry(entry);
});
state.chunkEntries.clear();
state.layerRoots.forEach((layerRoot) => {
layerRoot.removeFromParent();
layerRoot.destroy({ children: true });
});
state.layerRoots.clear();
state.entityLayerRoots.clear();
state.npcSpritesById.clear();
helpers.resetSceneRoots();
const chunkSurfaceOptions = buildChunkSurfaceOptions(state, scope, helpers);
const layers = Array.isArray(scope.roomLayers)
? [...scope.roomLayers].sort((a, b) => (Number(a.layer) || 0) - (Number(b.layer) || 0))
: [];
layers.forEach((layerObj) => {
const layerNumber = Number(layerObj?.layer) || 0;
const layerRoot = helpers.getOrCreateLayerRoot(layerNumber);
layerRoot.visible = scope.isLayerRendered(layerNumber);
const chunkStartsX = Math.ceil(Math.max(1, Number(scope.width) || 1) / state.chunkSize);
const chunkStartsY = Math.ceil(Math.max(1, Number(scope.height) || 1) / state.chunkSize);
for (let chunkY = 0; chunkY < chunkStartsY; chunkY += 1) {
for (let chunkX = 0; chunkX < chunkStartsX; chunkX += 1) {
const baseTileX = chunkX * state.chunkSize;
const baseTileY = chunkY * state.chunkSize;
const tileWidth = Math.max(1, Math.min(state.chunkSize, Math.max(0, Number(scope.width) || 0) - baseTileX));
const tileHeight = Math.max(1, Math.min(state.chunkSize, Math.max(0, Number(scope.height) || 0) - baseTileY));
const chunkEntry = helpers.getOrCreateChunkEntry(layerNumber, chunkX, chunkY, {
tileX: baseTileX,
tileY: baseTileY,
tileWidth,
tileHeight,
});
const hasContent = rebuildChunkEntrySurface(
chunkEntry,
(localX, localY) => helpers.resolveStoredTileSymbol(layerObj, baseTileX + localX, baseTileY + localY),
tileWidth,
tileHeight,
String(layerNumber),
chunkSurfaceOptions,
);
if (!hasContent) {
helpers.destroyChunkEntry(chunkEntry);
}
}
}
});
return true;
}