minerender 2.1.0-beta.6 → 2.1.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/browser/esm/Materials.mjs +3 -1
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/Ticker.mjs +3 -1
- package/dist/browser/esm/Ticker.mjs.map +1 -1
- package/dist/browser/esm/UVMapper.mjs +9 -9
- package/dist/browser/esm/UVMapper.mjs.map +1 -1
- package/dist/browser/esm/armor/Armor.mjs +84 -0
- package/dist/browser/esm/armor/Armor.mjs.map +1 -0
- package/dist/browser/esm/armor/index.mjs +3 -0
- package/dist/browser/esm/armor/index.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetKey.mjs +1 -1
- package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
- package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
- package/dist/browser/esm/assets/Assets.mjs +1 -5
- package/dist/browser/esm/assets/Assets.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockEntities.mjs +5 -1
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +40 -12
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
- package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
- package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
- package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
- package/dist/browser/esm/assets/Models.mjs +1 -1
- package/dist/browser/esm/assets/Models.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
- package/dist/browser/esm/assets/index.mjs +1 -0
- package/dist/browser/esm/assets/index.mjs.map +1 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/cache/Caching.mjs +8 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
- package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
- package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
- package/dist/browser/esm/image/ImageLoader.mjs +3 -3
- package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +191 -22
- package/dist/browser/esm/index.browser.mjs.map +1 -1
- package/dist/browser/esm/index.mjs +1 -0
- package/dist/browser/esm/index.mjs.map +1 -1
- package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
- package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
- package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
- package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
- package/dist/browser/esm/model/ItemGlint.mjs +7 -6
- package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +19 -6
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
- package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
- package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
- package/dist/browser/esm/renderer/Renderer.mjs +4 -2
- package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
- package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
- package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
- package/dist/browser/esm/request/Requests.mjs +3 -3
- package/dist/browser/esm/request/Requests.mjs.map +1 -1
- package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
- package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
- package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
- package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
- package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinPart.mjs +2 -0
- package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
- package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
- package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
- package/dist/browser/esm/skin/Skins.mjs +6 -4
- package/dist/browser/esm/skin/Skins.mjs.map +1 -1
- package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
- package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
- package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
- package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
- package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
- package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
- package/dist/browser/esm/texture/index.mjs +1 -0
- package/dist/browser/esm/texture/index.mjs.map +1 -1
- package/dist/browser/esm/util/log.mjs +75 -0
- package/dist/browser/esm/util/log.mjs.map +1 -1
- package/dist/browser/esm/util/performance.mjs.map +1 -1
- package/dist/browser/esm/util/util.mjs +0 -2
- package/dist/browser/esm/util/util.mjs.map +1 -1
- package/dist/browser/esm/world/Chunk.mjs +70 -38
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +187 -60
- package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
- package/dist/browser/esm/world/SectionMesh.mjs +65 -9
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/esm/world/SectionModels.mjs +21 -15
- package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
- package/dist/browser/esm/world/SectionWorker.mjs +8 -2
- package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
- package/dist/browser/esm/world/WorldStreamer.mjs +129 -34
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
- package/dist/browser/index.d.ts +191 -22
- package/dist/browser/index.js +4461 -3648
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +13482 -12651
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +179 -21
- package/dist/node/index.d.ts +179 -21
- package/dist/node/index.js +4495 -3666
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +4412 -3586
- package/dist/node/index.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/world/MineRenderWorld.ts"],"sourcesContent":["import { MineRenderScene } from \"../renderer/MineRenderScene\";\nimport { Block } from \"../model/block/Block\";\nimport { Raycaster, Vector3 } from \"three\";\nimport { isTripleArray, TripleArray } from \"../model/Model\";\nimport { Maybe, yieldToEventLoop } from \"../util/util\";\nimport { Chunk } from \"./Chunk\";\nimport { BlockInfo } from \"./BlockInfo\";\nimport { MultiBlockBlock, MultiBlockStructure } from \"../model/multiblock/MultiBlockStructure\";\nimport { BatchedExecutor } from \"../util/BatchedExecutor\";\nimport { AssetKey } from \"../assets/AssetKey\";\nimport { BlockStates } from \"../assets/BlockStates\";\nimport { CUBE_FACE_OFFSETS } from \"../CubeFace\";\nimport type { AnvilChunk } from \"./AnvilParser\";\nimport { SectionModels } from \"./SectionModels\";\nimport { WorldEntities } from \"./_entities/WorldEntities\";\nimport { fluidKindOf } from \"../model/fluid/FluidQuads\";\nimport type { WorldBlockIntersection } from \"./WorldBlockIntersection\";\nimport type { WorldEntityIntersection } from \"./WorldEntityIntersection\";\nimport { BiomeBlend, validateBiomeBlendRadius } from \"./_biomes/BiomeBlend\";\nimport { copySectionLight, sampleSectionLight, SavedLightSample, SectionLightData } from \"./WorldLight\";\nimport { loadBlockCulling } from \"./_culling/BlockCulling\";\n\n//TODO: maybe make this an Object3D to add children\n/**\n * Stores and renders blocks in sparse 16×16×16 chunks.\n * Positions use integer block coordinates, including negatives. One block is 16 scene units.\n * Set `options.sectionMeshing` in `new MineRenderWorld(scene, options)` to merge compatible terrain.\n */\nexport class MineRenderWorld<SectionMeshing extends boolean = false> {\n\n public readonly scene: MineRenderScene;\n\n private readonly _chunks: Map<string, Chunk<SectionMeshing>> = new Map();\n private readonly biomes = new Map<string, Map<number, readonly string[]>>();\n private readonly light = new Map<string, Map<number, SectionLightData>>();\n private readonly lightValidity = new Map<string, boolean>();\n private readonly highestSkySection = new Map<string, number>();\n private readonly savedLighting: boolean;\n private readonly ambientLight: number;\n private _ambientOcclusion: boolean;\n private ambientOcclusionPending = false;\n private _biomeBlendRadius: number;\n private biomeBlend?: BiomeBlend;\n private readonly pendingBiomes = new Map<Chunk<SectionMeshing>, { x: number; z: number }[] | undefined>();\n private biomeRefreshing?: Promise<Map<Chunk<SectionMeshing>, unknown>>;\n private readonly sectionModels?: SectionModels;\n private readonly entities?: WorldEntities;\n private readonly pendingCulling = new Map<Chunk<SectionMeshing>, Set<number> | \"all\">();\n private culling?: Promise<void>;\n\n constructor(scene: MineRenderScene, options: MineRenderWorldOptions<SectionMeshing> = {}) {\n if (options.savedLighting && !options.sectionMeshing) throw new TypeError(\"savedLighting requires sectionMeshing\");\n if (options.ambientOcclusion && !options.sectionMeshing) throw new TypeError(\"ambientOcclusion requires sectionMeshing\");\n if (options.ambientLight !== undefined && (!Number.isFinite(options.ambientLight) || options.ambientLight < 0 || options.ambientLight > 1)) {\n throw new RangeError(\"ambientLight must be a number from 0 to 1\");\n }\n this._biomeBlendRadius = options.biomeBlendRadius ?? 0;\n validateBiomeBlendRadius(this._biomeBlendRadius);\n if (this._biomeBlendRadius > 0 && !options.sectionMeshing) throw new TypeError(\"biomeBlendRadius requires sectionMeshing\");\n if (this._biomeBlendRadius) this.biomeBlend = new BiomeBlend((x, y, z) => this.getBiomeAt(x, y, z), this._biomeBlendRadius);\n this.scene = scene;\n this.savedLighting = options.savedLighting ?? false;\n this.ambientLight = options.ambientLight ?? 0;\n this._ambientOcclusion = options.ambientOcclusion ?? false;\n if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);\n if (options.renderEntities) this.entities = new WorldEntities(scene);\n }\n\n /**\n * Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.\n * Includes fluids and block entities; texture alpha does not change triangle intersections.\n */\n public raycast(raycaster: Raycaster): WorldBlockIntersection | undefined {\n return Chunk.raycast(this._chunks.values(), raycaster);\n }\n\n /**\n * Returns the nearest visible mob geometry hit when renderEntities is enabled.\n * Respects layers and near/far; compare its distance with raycast() to account for blocks.\n * Texture alpha does not change triangle intersections.\n */\n public raycastEntities(raycaster: Raycaster): WorldEntityIntersection | undefined {\n return this.entities?.raycast(raycaster);\n }\n\n /** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */\n public get ambientOcclusion(): boolean {\n return this._ambientOcclusion;\n }\n\n /** Rebuilds loaded blocks with or without corner shading. Block data and saved lighting are preserved. */\n public async setAmbientOcclusion(enabled: boolean): Promise<void> {\n if (typeof enabled !== \"boolean\") throw new TypeError(\"Ambient occlusion must be a boolean\");\n if (enabled && !this.sectionModels) throw new TypeError(\"ambientOcclusion requires sectionMeshing\");\n if (enabled === this._ambientOcclusion && !this.ambientOcclusionPending) {\n await this.culling;\n return;\n }\n this._ambientOcclusion = enabled;\n this.ambientOcclusionPending = true;\n for (const chunk of this._chunks.values()) this.pendingCulling.set(chunk, \"all\");\n await this.updateCulling([]);\n this.ambientOcclusionPending = false;\n }\n\n /** Horizontal biome-color sampling radius, from 0 to 7 blocks. Zero disables blending. */\n public get biomeBlendRadius(): number {\n return this._biomeBlendRadius;\n }\n\n /** Refreshes loaded grass, foliage, and water colors without reloading their source chunks. */\n public async setBiomeBlendRadius(radius: number): Promise<void> {\n validateBiomeBlendRadius(radius);\n if (radius > 0 && !this.sectionModels) throw new TypeError(\"biomeBlendRadius requires sectionMeshing\");\n if (radius !== this._biomeBlendRadius) {\n this._biomeBlendRadius = radius;\n this.biomeBlend?.clear();\n this.biomeBlend = radius ? new BiomeBlend((x, y, z) => this.getBiomeAt(x, y, z), radius) : undefined;\n for (const chunk of this._chunks.values()) this.pendingBiomes.set(chunk, undefined);\n }\n const failures = await this.refreshBiomes();\n if (failures.size) throw failures.values().next().value;\n }\n\n private markBiomesChanged(x: number, z: number, y?: number, includeColumn = true): Chunk<SectionMeshing>[] {\n const queued: Chunk<SectionMeshing>[] = [];\n if (!this.biomeBlend) return queued;\n this.biomeBlend.invalidateColumn(x, z);\n for (const chunk of this._chunks.values()) {\n if (Math.abs(chunk.x - x) > 1 || Math.abs(chunk.z - z) > 1\n || !includeColumn && chunk.x === x && chunk.z === z\n || y !== undefined && chunk.y !== y && chunk.y !== y + 1) continue;\n queued.push(chunk);\n if (!this.pendingBiomes.has(chunk)) this.pendingBiomes.set(chunk, []);\n const columns = this.pendingBiomes.get(chunk);\n if (columns && !columns.some(column => column.x === x && column.z === z)) columns.push({ x, z });\n }\n return queued;\n }\n\n private async refreshBiomes(): Promise<Map<Chunk<SectionMeshing>, unknown>> {\n if (this.biomeRefreshing) await this.biomeRefreshing;\n if (!this.pendingBiomes.size) return new Map();\n return this.biomeRefreshing ??= Promise.resolve().then(async () => {\n const failures = new Map<Chunk<SectionMeshing>, unknown>();\n const batch = [...this.pendingBiomes.keys()];\n let sliceStart = performance.now();\n try {\n for (const chunk of batch) {\n const columns = this.pendingBiomes.get(chunk);\n this.pendingBiomes.delete(chunk);\n if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) !== chunk) continue;\n try {\n await chunk.refreshBiomes(columns);\n } catch (error) {\n failures.set(chunk, error);\n if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) === chunk) this.pendingBiomes.set(chunk, undefined);\n }\n if (performance.now() - sliceStart > 8) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n return failures;\n } finally {\n this.biomeRefreshing = undefined;\n }\n });\n }\n\n /** Returns a placed block at world block coordinates, or `undefined` for an empty position. */\n public getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo<SectionMeshing>>;\n public getBlockAt(pos: Vector3): Maybe<BlockInfo<SectionMeshing>>;\n public getBlockAt(pos: TripleArray): Maybe<BlockInfo<SectionMeshing>>;\n public getBlockAt(posOrX: number | Vector3 | TripleArray, y?: number, z?: number): Maybe<BlockInfo<SectionMeshing>> {\n if (typeof posOrX == \"number\") {\n return this.getBlockAt(new Vector3(posOrX, y, z));\n }\n if (isTripleArray(posOrX)) {\n return this.getBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]))\n }\n this.validatePosBounds(posOrX);\n return this.getChunkAt(posOrX)?.getBlockAt(posOrX);\n }\n\n /** Returns the saved 4-block biome sample at integer world block coordinates, or `undefined` if absent. */\n public getBiomeAt(x: number, y: number, z: number): Maybe<string>;\n public getBiomeAt(pos: Vector3): Maybe<string>;\n public getBiomeAt(pos: TripleArray): Maybe<string>;\n public getBiomeAt(posOrX: number | Vector3 | TripleArray, y?: number, z?: number): Maybe<string> {\n if (typeof posOrX === \"number\") return this.getBiomeAt(new Vector3(posOrX, y, z));\n if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector3(...posOrX));\n this.validatePosBounds(posOrX);\n const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);\n const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;\n return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[\n Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];\n }\n\n /**\n * Returns saved light at integer world block coordinates, including data marked invalid by the save.\n * Sky light is 15 above a column's highest saved sky-light array.\n */\n public getLightAt(x: number, y: number, z: number): Maybe<SavedLightSample>;\n public getLightAt(pos: Vector3): Maybe<SavedLightSample>;\n public getLightAt(pos: TripleArray): Maybe<SavedLightSample>;\n public getLightAt(posOrX: number | Vector3 | TripleArray, y?: number, z?: number): Maybe<SavedLightSample> {\n if (typeof posOrX === \"number\") return this.getLightAt(new Vector3(posOrX, y, z));\n if (isTripleArray(posOrX)) return this.getLightAt(new Vector3(...posOrX));\n this.validatePosBounds(posOrX);\n const { x, y: py, z: pz } = posOrX;\n const cx = Math.floor(x / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);\n const key = `${cx}_${cz}`, top = this.highestSkySection.get(key);\n const sample = sampleSectionLight(this.light.get(key)?.get(cy), (x & 15) + (pz & 15) * 16 + (py & 15) * 256);\n return top !== undefined && cy > top ? { block: sample?.block ?? 0, sky: 15 } : sample;\n }\n\n private lightLevelAt(x: number, y: number, z: number): number {\n const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16), key = `${cx}_${cz}`;\n if (this.lightValidity.get(key) === false) return 255;\n const top = this.highestSkySection.get(key);\n if (top !== undefined && cy > top) return 15;\n const sample = sampleSectionLight(this.light.get(key)?.get(cy), (x & 15) + (z & 15) * 16 + (y & 15) * 256);\n return sample ? Math.max(sample.block, sample.sky) : 255;\n }\n\n /**\n * Places or replaces a block and refreshes neighboring faces.\n * Pass `undefined` or an air block to remove the block at these world block coordinates.\n */\n public async setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;\n public async setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;\n public async setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;\n public async setBlockAt(posOrX: number | Vector3 | TripleArray, yOrBlock?: number | Block, z?: number, block?: Block): Promise<Maybe<BlockInfo<SectionMeshing>>> {\n if (typeof posOrX == \"number\") {\n return this.setBlockAt(new Vector3(posOrX, yOrBlock as number, z), block as Block);\n }\n if (isTripleArray(posOrX)) {\n return this.setBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock as Block);\n }\n return this.placeBlock(posOrX, yOrBlock as Maybe<Block>);\n }\n\n private async placeBlock(pos: Vector3, value: Maybe<Block>, onBlocksChanged?: (positions: Vector3[]) => Promise<void>): Promise<Maybe<BlockInfo<SectionMeshing>>> {\n this.validatePosBounds(pos);\n const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);\n return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);\n }\n\n /**\n * Shows or hides a placed block without changing its data. Hidden blocks do not occlude neighbors.\n * Missing blocks are ignored; replacing or removing a block resets its visibility.\n */\n public async setBlockVisibleAt(x: number, y: number, z: number, visible: boolean): Promise<void>;\n public async setBlockVisibleAt(pos: Vector3, visible: boolean): Promise<void>;\n public async setBlockVisibleAt(pos: TripleArray, visible: boolean): Promise<void>;\n public async setBlockVisibleAt(posOrX: number | Vector3 | TripleArray, yOrVisible: number | boolean,\n z?: number, visible?: boolean): Promise<void> {\n if (typeof posOrX === \"number\") {\n return this.setBlockVisibleAt(new Vector3(posOrX, yOrVisible as number, z), visible!);\n }\n if (isTripleArray(posOrX)) {\n return this.setBlockVisibleAt(new Vector3(...posOrX), yOrVisible as boolean);\n }\n this.validatePosBounds(posOrX);\n await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible as boolean);\n }\n\n\n /**\n * Places a structure's blocks at their stored positions, then refreshes neighboring faces.\n * With `renderEntities`, also places supported saved mobs and applies supported appearance fields.\n *\n * @param useBatches - Yields between chunks by default. Set to `false` for sequential placement.\n * @param executor - Optional queue for batched placement. The caller remains responsible for stopping it.\n */\n public async placeMultiBlock(multiblock: MultiBlockStructure, useBatches: boolean = true, executor?: BatchedExecutor): Promise<void> {\n const placeEntities = this.entities?.prepare(multiblock.entities);\n const changes = new Map<string, Vector3>();\n try {\n await this.placeBlocks(multiblock, useBatches, executor, changes);\n await placeEntities?.();\n } finally {\n await this.updateCulling([...changes.values()]);\n }\n }\n\n private async placeBlocks(multiblock: MultiBlockStructure, useBatches: boolean, executor: BatchedExecutor | undefined,\n changes: Map<string, Vector3>): Promise<void> {\n const collect = async (positions: Vector3[]) => {\n for (const pos of positions) changes.set(pos.toArray().join(\",\"), pos);\n };\n const place = (block: MultiBlockBlock) => this.placeBlock(new Vector3(...block.position), block, collect);\n const keys = new Map<string, AssetKey>();\n const types = new Set<string>();\n for (const block of multiblock.blocks) {\n if (Chunk.isAir(block) || types.has(block.type)) continue;\n types.add(block.type);\n const key = AssetKey.parse(\"blockstates\", block.type);\n keys.set(key.serialize(), key);\n }\n await BlockStates.getAll(keys.values());\n\n if (!useBatches) {\n for (const block of multiblock.blocks) await place(block);\n return;\n }\n\n if (!executor) {\n const groups = new Map<Chunk<SectionMeshing>, { index: number; block: Maybe<Block> }[]>();\n const position = new Vector3();\n for (const block of multiblock.blocks) {\n const [x, y, z] = block.position;\n this.validatePosBounds(position.set(x, y, z));\n const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16);\n const key = `${cx}_${cy}_${cz}`;\n const chunk = this._chunks.get(key) ?? (Chunk.isAir(block) ? undefined : this.getOrCreateChunkAt(position));\n if (!chunk) continue;\n let group = groups.get(chunk);\n if (!group) groups.set(chunk, group = []);\n group.push({ index: (y - cy * 16) * 256 + (z - cz * 16) * 16 + x - cx * 16, block });\n }\n await this.placeChunkGroups(groups, changes);\n return;\n }\n\n // Writes to the same position retain their input order.\n const positions = new Map<string, MultiBlockBlock[]>();\n for (const block of multiblock.blocks) {\n const key = block.position.join(\",\");\n const group = positions.get(key);\n if (group) group.push(block);\n else positions.set(key, [block]);\n }\n const groups = [...positions.values()];\n for (let i = 0; i < groups.length; i += executor.batch) {\n const results = await Promise.allSettled(groups.slice(i, i + executor.batch).map(blocks =>\n executor.submit(async () => {\n for (const block of blocks) await place(block);\n })\n ));\n const failure = results.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n }\n }\n\n private async placeChunkGroups(groups: Map<Chunk<SectionMeshing>, { index: number; block: Maybe<Block> }[]>,\n changes: Map<string, Vector3>): Promise<void> {\n let sliceStart = performance.now();\n for (const [chunk, blocks] of groups) {\n let positions: Vector3[] | undefined;\n try {\n positions = await chunk.placeBlocks(blocks);\n } finally {\n // Failed groups still clear cells and place their remaining blocks.\n positions ??= blocks.map(({ index }) => new Vector3(chunk.x * 16 + index % 16,\n chunk.y * 16 + Math.floor(index / 256), chunk.z * 16 + Math.floor(index / 16) % 16));\n for (const pos of positions) changes.set(`${pos.x},${pos.y},${pos.z}`, pos);\n }\n if (performance.now() - sliceStart > 8) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n }\n\n\n /** Replaces a chunk column's blocks, biomes, and saved light and, with `renderEntities`, its supported saved mobs. */\n public async placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void> {\n if (![chunk.x, chunk.z].every(Number.isSafeInteger)) {\n throw new RangeError(\"Chunk column coordinates must be safe integers\");\n }\n if (!chunk.sections.every(section => Number.isSafeInteger(section.y))) {\n throw new RangeError(\"Chunk section coordinates must be safe integers\");\n }\n const lights = new Map<number, SectionLightData>();\n for (const section of chunk.sections) {\n const light = section.light ?? (chunk.lightValid === true ? {} : undefined);\n if (light) lights.set(section.y, copySectionLight(light));\n }\n this.entities?.clearColumn(chunk.x, chunk.z);\n const placeEntities = this.entities?.prepare(chunk.entities, [chunk.x, chunk.z]);\n const changes = new Map<string, Vector3>();\n const occupiedSections = new Set<number>();\n if (!executor) {\n for (const section of chunk.sections) {\n for (let index = 0; index < 4096; index++) {\n if (!section.data.idAt(index)) continue;\n occupiedSections.add(section.y);\n break;\n }\n }\n }\n try {\n await this.clearChunkColumn(chunk.x, chunk.z);\n const columnKey = `${chunk.x}_${chunk.z}`;\n if (lights.size) this.light.set(columnKey, lights);\n for (const [y, light] of lights) {\n if (light.sky) this.highestSkySection.set(columnKey, Math.max(y, this.highestSkySection.get(columnKey) ?? -Infinity));\n }\n if (chunk.lightValid !== undefined) this.lightValidity.set(columnKey, chunk.lightValid);\n if (this.savedLighting) {\n for (const y of lights.keys()) this.markSectionChanged({ x: chunk.x, y, z: chunk.z });\n }\n // Tall plants can sample the section below, so install all biomes before rendering.\n for (const section of chunk.sections) {\n if (section.biomes) {\n const position = new Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);\n this.validatePosBounds(position);\n const copy = [...section.biomes];\n if (copy.length !== 64 || !copy.every(id => typeof id === \"string\" && id.length > 0)) {\n throw new RangeError(\"Section biomes must contain 64 nonempty biome IDs\");\n }\n const key = `${chunk.x}_${chunk.z}`;\n let column = this.biomes.get(key);\n if (!column) this.biomes.set(key, column = new Map());\n column.set(section.y, copy);\n }\n }\n let sliceStart = performance.now();\n for (const section of chunk.sections) {\n if (!executor) {\n if (!occupiedSections.has(section.y)) continue;\n const position = new Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);\n this.validatePosBounds(position);\n const target = this.getOrCreateChunkAt(position);\n try {\n await target.placeSection(section.data);\n } finally {\n this.markSectionChanged(target);\n }\n if (performance.now() - sliceStart > 8) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n continue;\n }\n const blocks: MultiBlockBlock[] = [];\n for (let index = 0; index < 4096; index++) {\n const block = section.data.get(index);\n if (block) blocks.push({\n ...block,\n position: [chunk.x * 16 + index % 16,\n section.y * 16 + Math.floor(index / 256),\n chunk.z * 16 + Math.floor(index / 16) % 16]\n });\n }\n await this.placeBlocks({ size: [16, 16, 16], blocks }, true, executor, changes);\n }\n await placeEntities?.();\n } finally {\n this.markBiomesChanged(chunk.x, chunk.z, undefined, false);\n const failures = await this.refreshBiomes();\n if (failures.size) console.warn(\"Failed to refresh biome colors\", failures.values().next().value);\n await this.updateCulling([...changes.values()]);\n }\n }\n\n /**\n * Removes blocks and owned entities at chunk-column coordinates, then refreshes neighboring faces and fluids.\n * Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.\n */\n public async unloadChunkColumn(x: number, z: number): Promise<void> {\n if (!Number.isInteger(x) || !Number.isInteger(z)) {\n throw new RangeError(\"Chunk column coordinates must be integers\");\n }\n this.entities?.clearColumn(x, z);\n await this.culling;\n try {\n await this.clearChunkColumn(x, z);\n } finally {\n const failures = await this.refreshBiomes();\n if (failures.size) console.warn(\"Failed to refresh biome colors\", failures.values().next().value);\n await this.updateCulling([]);\n }\n }\n\n private async clearChunkColumn(x: number, z: number): Promise<void> {\n this.biomes.delete(`${x}_${z}`);\n this.markBiomesChanged(x, z, undefined, false);\n if (this.savedLighting) {\n for (const y of this.light.get(`${x}_${z}`)?.keys() ?? []) this.markSectionChanged({ x, y, z });\n }\n this.light.delete(`${x}_${z}`);\n this.lightValidity.delete(`${x}_${z}`);\n this.highestSkySection.delete(`${x}_${z}`);\n const previous = [...this._chunks.entries()].filter(([, section]) => section.x === x && section.z === z);\n for (const [key, section] of previous) {\n this._chunks.delete(key);\n this.pendingCulling.delete(section);\n this.pendingBiomes.delete(section);\n await section.clear(false);\n this.markSectionChanged(section);\n }\n }\n\n private markSectionChanged(chunk: { x: number; y: number; z: number }): void {\n const current = this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`);\n if (current && current === chunk) this.pendingCulling.set(current, \"all\");\n for (let dy = -1; dy <= 1; dy++) {\n for (let dz = -1; dz <= 1; dz++) {\n for (let dx = -1; dx <= 1; dx++) {\n if (dx === 0 && dy === 0 && dz === 0) continue;\n const neighbor = this._chunks.get(`${chunk.x + dx}_${chunk.y + dy}_${chunk.z + dz}`);\n if (!neighbor) continue;\n let pending = this.pendingCulling.get(neighbor);\n if (pending === \"all\") continue;\n if (!pending) this.pendingCulling.set(neighbor, pending = new Set());\n for (let y = dy < 0 ? 15 : 0; y <= (dy > 0 ? 0 : 15); y++) {\n for (let z = dz < 0 ? 15 : 0; z <= (dz > 0 ? 0 : 15); z++) {\n for (let x = dx < 0 ? 15 : 0; x <= (dx > 0 ? 0 : 15); x++) {\n pending.add(y * 256 + z * 16 + x);\n }\n }\n }\n }\n }\n }\n }\n\n /** Removes all chunks and releases their blocks, section meshes, and owned entities. */\n public async clear(): Promise<void> {\n this.entities?.clear();\n await this.culling;\n const chunks = [...this._chunks.values()];\n this._chunks.clear();\n this.biomes.clear();\n this.biomeBlend?.clear();\n this.pendingBiomes.clear();\n this.light.clear();\n this.lightValidity.clear();\n this.highestSkySection.clear();\n for (const chunk of chunks) {\n await chunk.dispose();\n }\n this.sectionModels?.clear();\n }\n\n private updateCulling(positions: Vector3[]): Promise<void> {\n const neighbor = new Vector3();\n for (const pos of positions) {\n const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);\n const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);\n const lx = pos.x - cx * 16, ly = pos.y - cy * 16, lz = pos.z - cz * 16;\n // Fluid surfaces and ambient occlusion also depend on edge and corner neighbors.\n for (let y = -1; y <= 1; y++) {\n for (let z = -1; z <= 1; z++) {\n for (let x = -1; x <= 1; x++) {\n const nx = lx + x, ny = ly + y, nz = lz + z;\n const section = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16 ? chunk\n : this._chunks.get(`${cx + Math.floor(nx / 16)}_${cy + Math.floor(ny / 16)}_${cz + Math.floor(nz / 16)}`);\n if (!section) continue;\n const index = (ny & 15) * 256 + (nz & 15) * 16 + (nx & 15);\n let pending = this.pendingCulling.get(section);\n if (pending === \"all\" || pending?.has(index)) continue;\n if (Math.abs(x) + Math.abs(y) + Math.abs(z) > 1\n && !this._ambientOcclusion && !section.isFluidIndex(index)) continue;\n if (!pending) this.pendingCulling.set(section, pending = new Set());\n pending.add(index);\n }\n }\n }\n }\n // Adjacent batched placements share one drain so they cannot replace the same model concurrently.\n return this.culling ??= Promise.resolve().then(async () => {\n let sliceStart = performance.now();\n try {\n const culling = await loadBlockCulling();\n while (this.pendingCulling.size) {\n const batch = [...this.pendingCulling];\n this.pendingCulling.clear();\n for (const [chunk, indices] of batch) {\n const neighbors = CUBE_FACE_OFFSETS.map(([x, y, z]) =>\n this._chunks.get(`${chunk.x + x}_${chunk.y + y}_${chunk.z + z}`));\n const neighborAt = (x: number, y: number, z: number): [Maybe<Chunk<SectionMeshing>>, number] => {\n const lx = x - chunk.x * 16, ly = y - chunk.y * 16, lz = z - chunk.z * 16;\n const section = neighbors[lx >= 16 ? 0 : lx < 0 ? 1 : ly >= 16 ? 2 : ly < 0 ? 3 : lz >= 16 ? 4 : 5];\n return [section, (ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)];\n };\n const masks = chunk.updateCullMasks(indices === \"all\" ? undefined : indices, (x, y, z) => {\n const [section, i] = neighborAt(x, y, z);\n return section?.isOccludingIndex(i) ?? false;\n }, culling, (x, y, z) => {\n const [section, i] = neighborAt(x, y, z);\n return section?.visibleBlockIndex(i);\n });\n const fluidIndices = indices === \"all\" ? (function* () {\n for (let index = 0; index < 4096; index++) yield index;\n })() : indices;\n for (const index of fluidIndices) {\n if (!chunk.fluidByteIndex(index) || !chunk.isBlockVisibleIndex(index)) continue;\n const lx = index % 16, ly = Math.floor(index / 256), lz = Math.floor(index / 16) % 16;\n const wx = chunk.x * 16 + lx, wy = chunk.y * 16 + ly, wz = chunk.z * 16 + lz;\n const block = chunk.getBlockAt(neighbor.set(wx, wy, wz))!;\n if (block.object?.fluidKind) {\n await block.object.updateFluid((x, y, z) => {\n const nx = lx + x, ny = ly + y, nz = lz + z;\n const section = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16 ? chunk\n : this._chunks.get(`${chunk.x + Math.floor(nx / 16)}_${chunk.y + Math.floor(ny / 16)}_${chunk.z + Math.floor(nz / 16)}`);\n const neighborIndex = (ny & 15) * 256 + (nz & 15) * 16 + (nx & 15);\n const byte = section?.fluidByteIndex(neighborIndex) ?? 0;\n return { fluid: fluidKindOf(byte), level: byte & 15,\n solid: section?.isOccludingIndex(neighborIndex) ?? false };\n });\n }\n }\n for (const [index, mask] of masks) await chunk.setCullMaskIndex(index, mask);\n await chunk.refreshLight(indices === \"all\" ? undefined : indices);\n chunk.refreshAmbientOcclusion(this._ambientOcclusion);\n if ((this._ambientOcclusion || this.ambientOcclusionPending) && performance.now() - sliceStart > 8) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n await Promise.all(batch.map(([chunk]) => chunk.rebuildSectionMesh()));\n }\n } finally {\n this.culling = undefined;\n }\n });\n }\n\n private getOrCreateChunkAt(pos: Vector3): Chunk<SectionMeshing> {\n const key = this.worldPosToChunkKey(pos);\n let chunk = this._chunks.get(key);\n if (typeof chunk === \"undefined\") {\n const x = Math.floor(pos.x / 16), y = Math.floor(pos.y / 16), z = Math.floor(pos.z / 16);\n chunk = new Chunk<SectionMeshing>(this.scene, x, y, z,\n positions => this.updateCulling(positions), this.sectionModels, (x, y, z) => {\n const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16);\n const section = this._chunks.get(`${cx}_${cy}_${cz}`);\n const index = (y - cy * 16) * 256 + (z - cz * 16) * 16 + x - cx * 16;\n return (section?.fluidByteIndex(index) ?? 0) | (section?.isOccludingIndex(index) ? 64 : 0);\n }, (x, y, z) => this.getBiomeAt(x, y, z), async biomes => {\n if (this._chunks.get(key) !== chunk) return;\n const columnKey = `${x}_${z}`;\n let column = this.biomes.get(columnKey);\n if (biomes) {\n if (!column) this.biomes.set(columnKey, column = new Map());\n column.set(y, biomes);\n } else {\n column?.delete(y);\n if (!column?.size) this.biomes.delete(columnKey);\n }\n if (this.biomeBlend) {\n const queued = this.markBiomesChanged(x, z, y);\n const failures = await this.refreshBiomes();\n for (const chunk of queued) if (failures.has(chunk)) throw failures.get(chunk);\n } else {\n await chunk!.refreshBiomes();\n // Upper tall-plant halves at the boundary sample the section below.\n await this._chunks.get(`${x}_${y + 1}_${z}`)?.refreshBiomes();\n }\n }, this.savedLighting ? (x, y, z) => this.lightLevelAt(x, y, z) : undefined, async () => {\n if (this._chunks.get(key) !== chunk) return;\n const columnKey = `${x}_${z}`, column = this.light.get(columnKey);\n if (!column?.delete(y)) return;\n if (!column.size) this.light.delete(columnKey);\n this.highestSkySection.delete(columnKey);\n for (const [y, light] of column) {\n if (light.sky) this.highestSkySection.set(columnKey, Math.max(y, this.highestSkySection.get(columnKey) ?? -Infinity));\n }\n if (this.savedLighting) {\n this.markSectionChanged(chunk!);\n await this.updateCulling([]);\n }\n }, this.ambientLight, () => this.biomeBlend);\n this._chunks.set(key, chunk);\n }\n return chunk;\n }\n\n /** Returns the loaded chunk containing a world block position, without creating a chunk. */\n public getChunkAt(pos: Vector3): Maybe<Chunk<SectionMeshing>> {\n return this._chunks.get(this.worldPosToChunkKey(pos));\n }\n\n\n /** Converts block coordinates to scene units by multiplying each component by 16. */\n static worldToScenePosition(pos: Vector3): Vector3 {\n return new Vector3(\n pos.x * 16.0,\n pos.y * 16.0,\n pos.z * 16.0\n );\n }\n\n /** Converts scene units to block coordinates without rounding to an integer block. */\n static sceneToWorldPosition(pos: Vector3): Vector3 {\n return new Vector3(\n pos.x / 16.0,\n pos.y / 16.0,\n pos.z / 16.0\n );\n }\n\n worldPosToChunkKey(pos: Vector3): string {\n const chunkX = Math.floor(pos.x / 16);\n const chunkY = Math.floor(pos.y / 16);\n const chunkZ = Math.floor(pos.z / 16);\n return `${chunkX}_${chunkY}_${chunkZ}`;\n }\n\n validatePosBounds(pos: Vector3): void {\n if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {\n throw new RangeError(\"Block coordinates must be integers\");\n }\n }\n\n}\n\n\n/** Settings passed as the second argument to `new MineRenderWorld(scene, options)`. */\nexport interface MineRenderWorldOptions<SectionMeshing extends boolean = boolean> {\n /** Render supported saved mobs at their position and yaw, including supported appearance fields. Defaults to false. */\n renderEntities?: boolean;\n /** Merge static opaque cubes into section meshes. Merged blocks have no individual object. */\n sectionMeshing?: SectionMeshing;\n /** Shade blocks and fluids with saved sky/block light. Missing or invalid data keeps preview brightness. Defaults to false. Requires `sectionMeshing`. */\n savedLighting?: boolean;\n /** Minimum brightness for saved lighting, from 0 to 1, like a dimension type's `ambient_light`. Defaults to 0. */\n ambientLight?: number;\n /** Bake corner shading from neighboring opaque full cubes. Defaults to false; no per-frame shading pass is added. Requires `sectionMeshing`. */\n ambientOcclusion?: boolean;\n /** Average neighboring biome colors within this horizontal radius, from 0 to 7 blocks. Defaults to 0 (off). Requires `sectionMeshing`. */\n biomeBlendRadius?: number;\n /** Maximum width and height of each section atlas page, in pixels. */\n maxAtlasSize?: number;\n}\n"],"mappings":"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","names":["positions","groups","x","y","z","chunk"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/world/MineRenderWorld.ts"],"sourcesContent":["import { MineRenderScene } from \"../renderer/MineRenderScene\";\nimport { Block } from \"../model/block/Block\";\nimport { Raycaster, Vector3 } from \"three\";\nimport { isTripleArray, TripleArray } from \"../model/Model\";\nimport { Maybe, yieldToEventLoop } from \"../util/util\";\nimport { Chunk } from \"./Chunk\";\nimport { ChunkData } from \"./ChunkData\";\nimport { BlockInfo } from \"./BlockInfo\";\nimport { MultiBlockBlock, MultiBlockStructure } from \"../model/multiblock/MultiBlockStructure\";\nimport { BatchedExecutor } from \"../util/BatchedExecutor\";\nimport { AssetKey } from \"../assets/AssetKey\";\nimport { BlockStates } from \"../assets/BlockStates\";\nimport { BlockEntities } from \"../assets/BlockEntities\";\nimport { CUBE_FACE_OFFSETS } from \"../CubeFace\";\nimport type { AnvilChunk } from \"./AnvilParser\";\nimport { SectionModels } from \"./SectionModels\";\nimport { WorldEntities } from \"./_entities/WorldEntities\";\nimport { fluidKindOf } from \"../model/fluid/FluidQuads\";\nimport type { WorldBlockIntersection } from \"./WorldBlockIntersection\";\nimport type { WorldEntityIntersection } from \"./WorldEntityIntersection\";\nimport { BiomeBlend, validateBiomeBlendRadius } from \"./_biomes/BiomeBlend\";\nimport { copySectionLight, sampleSectionLight, SavedLightSample, SectionLightData } from \"./WorldLight\";\nimport { loadBlockCulling } from \"./_culling/BlockCulling\";\nimport { logger } from \"../util/log\";\n\nconst log = logger(\"MineRenderWorld\");\nconst YIELD_INTERVAL_MS = 8;\n\n//TODO: maybe make this an Object3D to add children\n/**\n * Stores and renders blocks in sparse 16×16×16 chunks.\n * Positions use integer block coordinates, including negatives. One block is 16 scene units.\n * Set `options.sectionMeshing` in `new MineRenderWorld(scene, options)` to merge compatible terrain.\n */\nexport class MineRenderWorld<SectionMeshing extends boolean = false> {\n\n public readonly scene: MineRenderScene;\n\n private readonly _chunks: Map<string, Chunk<SectionMeshing>> = new Map();\n private readonly biomes = new Map<string, Map<number, readonly string[]>>();\n private readonly light = new Map<string, Map<number, SectionLightData>>();\n private readonly lightValidity = new Map<string, boolean>();\n private readonly highestSkySection = new Map<string, number>();\n private readonly savedLighting: boolean;\n private readonly ambientLight: number;\n private _ambientOcclusion: boolean;\n private ambientOcclusionPending = false;\n private _biomeBlendRadius: number;\n private biomeBlend?: BiomeBlend;\n private readonly pendingBiomes = new Map<Chunk<SectionMeshing>, { x: number; z: number }[] | undefined>();\n private biomeRefreshing?: Promise<Map<Chunk<SectionMeshing>, unknown>>;\n private readonly sectionModels?: SectionModels;\n private readonly entities?: WorldEntities;\n private readonly pendingCulling = new Map<Chunk<SectionMeshing>, Set<number> | \"all\">();\n private culling?: Promise<void>;\n\n constructor(scene: MineRenderScene, options: MineRenderWorldOptions<SectionMeshing> = {}) {\n if (options.savedLighting && !options.sectionMeshing) throw new TypeError(\"savedLighting requires sectionMeshing\");\n if (options.ambientOcclusion && !options.sectionMeshing) throw new TypeError(\"ambientOcclusion requires sectionMeshing\");\n if (options.ambientLight !== undefined && (!Number.isFinite(options.ambientLight) || options.ambientLight < 0 || options.ambientLight > 1)) {\n throw new RangeError(\"ambientLight must be a number from 0 to 1\");\n }\n this._biomeBlendRadius = options.biomeBlendRadius ?? 0;\n validateBiomeBlendRadius(this._biomeBlendRadius);\n if (this._biomeBlendRadius > 0 && !options.sectionMeshing) throw new TypeError(\"biomeBlendRadius requires sectionMeshing\");\n if (this._biomeBlendRadius) this.biomeBlend = new BiomeBlend((x, y, z) => this.getBiomeAt(x, y, z), this._biomeBlendRadius);\n this.scene = scene;\n this.savedLighting = options.savedLighting ?? false;\n this.ambientLight = options.ambientLight ?? 0;\n this._ambientOcclusion = options.ambientOcclusion ?? false;\n if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);\n if (options.renderEntities) this.entities = new WorldEntities(scene);\n }\n\n /**\n * Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.\n * Includes fluids and block entities; texture alpha does not change triangle intersections.\n */\n public raycast(raycaster: Raycaster): WorldBlockIntersection | undefined {\n return Chunk.raycast(this._chunks.values(), raycaster);\n }\n\n /**\n * Returns the nearest visible mob geometry hit when renderEntities is enabled.\n * Respects layers and near/far; compare its distance with raycast() to account for blocks.\n * Texture alpha does not change triangle intersections.\n */\n public raycastEntities(raycaster: Raycaster): WorldEntityIntersection | undefined {\n return this.entities?.raycast(raycaster);\n }\n\n /** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */\n public get ambientOcclusion(): boolean {\n return this._ambientOcclusion;\n }\n\n /** Rebuilds loaded blocks with or without corner shading. Block data and saved lighting are preserved. */\n public async setAmbientOcclusion(enabled: boolean): Promise<void> {\n if (typeof enabled !== \"boolean\") throw new TypeError(\"Ambient occlusion must be a boolean\");\n if (enabled && !this.sectionModels) throw new TypeError(\"ambientOcclusion requires sectionMeshing\");\n if (enabled === this._ambientOcclusion && !this.ambientOcclusionPending) {\n await this.culling;\n return;\n }\n this._ambientOcclusion = enabled;\n this.ambientOcclusionPending = true;\n for (const chunk of this._chunks.values()) this.pendingCulling.set(chunk, \"all\");\n await this.updateCulling([]);\n this.ambientOcclusionPending = false;\n }\n\n /** Horizontal biome-color sampling radius, from 0 to 7 blocks. Zero disables blending. */\n public get biomeBlendRadius(): number {\n return this._biomeBlendRadius;\n }\n\n /** Refreshes loaded grass, foliage, and water colors without reloading their source chunks. */\n public async setBiomeBlendRadius(radius: number): Promise<void> {\n validateBiomeBlendRadius(radius);\n if (radius > 0 && !this.sectionModels) throw new TypeError(\"biomeBlendRadius requires sectionMeshing\");\n if (radius !== this._biomeBlendRadius) {\n this._biomeBlendRadius = radius;\n this.biomeBlend?.clear();\n this.biomeBlend = radius ? new BiomeBlend((x, y, z) => this.getBiomeAt(x, y, z), radius) : undefined;\n for (const chunk of this._chunks.values()) this.pendingBiomes.set(chunk, undefined);\n }\n const failures = await this.refreshBiomes();\n if (failures.size) throw failures.values().next().value;\n }\n\n private markBiomesChanged(x: number, z: number, y?: number, includeColumn = true): Chunk<SectionMeshing>[] {\n const queued: Chunk<SectionMeshing>[] = [];\n if (!this.biomeBlend) return queued;\n this.biomeBlend.invalidateColumn(x, z);\n for (const chunk of this._chunks.values()) {\n if (Math.abs(chunk.x - x) > 1 || Math.abs(chunk.z - z) > 1\n || !includeColumn && chunk.x === x && chunk.z === z\n || y !== undefined && chunk.y !== y && chunk.y !== y + 1) continue;\n queued.push(chunk);\n if (!this.pendingBiomes.has(chunk)) this.pendingBiomes.set(chunk, []);\n const columns = this.pendingBiomes.get(chunk);\n if (columns && !columns.some(column => column.x === x && column.z === z)) columns.push({ x, z });\n }\n return queued;\n }\n\n private async refreshBiomes(deferCulling = false): Promise<Map<Chunk<SectionMeshing>, unknown>> {\n if (this.biomeRefreshing) {\n await this.biomeRefreshing;\n if (!deferCulling) {\n if (this.pendingCulling.size) await this.updateCulling([]);\n else await this.culling;\n }\n }\n if (!this.pendingBiomes.size) return new Map();\n return this.biomeRefreshing ??= Promise.resolve().then(async () => {\n const failures = new Map<Chunk<SectionMeshing>, unknown>();\n const batch = [...this.pendingBiomes.keys()];\n let sliceStart = performance.now();\n try {\n for (const chunk of batch) {\n const columns = this.pendingBiomes.get(chunk);\n this.pendingBiomes.delete(chunk);\n if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) !== chunk) continue;\n try {\n await chunk.refreshBiomes(columns, deferCulling);\n } catch (error) {\n failures.set(chunk, error);\n if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) === chunk) this.pendingBiomes.set(chunk, undefined);\n }\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n return failures;\n } finally {\n this.biomeRefreshing = undefined;\n }\n });\n }\n\n /** Returns a placed block at world block coordinates, or `undefined` for an empty position. */\n public getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo<SectionMeshing>>;\n public getBlockAt(pos: Vector3): Maybe<BlockInfo<SectionMeshing>>;\n public getBlockAt(pos: TripleArray): Maybe<BlockInfo<SectionMeshing>>;\n public getBlockAt(posOrX: number | Vector3 | TripleArray, y?: number, z?: number): Maybe<BlockInfo<SectionMeshing>> {\n if (typeof posOrX == \"number\") {\n return this.getBlockAt(new Vector3(posOrX, y, z));\n }\n if (isTripleArray(posOrX)) {\n return this.getBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]))\n }\n this.validatePosBounds(posOrX);\n return this.getChunkAt(posOrX)?.getBlockAt(posOrX);\n }\n\n /** Returns the saved 4-block biome sample at integer world block coordinates, or `undefined` if absent. */\n public getBiomeAt(x: number, y: number, z: number): Maybe<string>;\n public getBiomeAt(pos: Vector3): Maybe<string>;\n public getBiomeAt(pos: TripleArray): Maybe<string>;\n public getBiomeAt(posOrX: number | Vector3 | TripleArray, y?: number, z?: number): Maybe<string> {\n if (typeof posOrX === \"number\") return this.getBiomeAt(new Vector3(posOrX, y, z));\n if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector3(...posOrX));\n this.validatePosBounds(posOrX);\n const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);\n const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;\n return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[\n Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];\n }\n\n /**\n * Returns saved light at integer world block coordinates, including data marked invalid by the save.\n * Sky light is 15 above a column's highest saved sky-light array.\n */\n public getLightAt(x: number, y: number, z: number): Maybe<SavedLightSample>;\n public getLightAt(pos: Vector3): Maybe<SavedLightSample>;\n public getLightAt(pos: TripleArray): Maybe<SavedLightSample>;\n public getLightAt(posOrX: number | Vector3 | TripleArray, y?: number, z?: number): Maybe<SavedLightSample> {\n if (typeof posOrX === \"number\") return this.getLightAt(new Vector3(posOrX, y, z));\n if (isTripleArray(posOrX)) return this.getLightAt(new Vector3(...posOrX));\n this.validatePosBounds(posOrX);\n const { x, y: py, z: pz } = posOrX;\n const cx = Math.floor(x / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);\n const key = `${cx}_${cz}`, top = this.highestSkySection.get(key);\n const sample = sampleSectionLight(this.light.get(key)?.get(cy), (x & 15) + (pz & 15) * 16 + (py & 15) * 256);\n return top !== undefined && cy > top ? { block: sample?.block ?? 0, sky: 15 } : sample;\n }\n\n private lightLevelAt(x: number, y: number, z: number): number {\n const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16), key = `${cx}_${cz}`;\n if (this.lightValidity.get(key) === false) return 255;\n const top = this.highestSkySection.get(key);\n if (top !== undefined && cy > top) return 15;\n const sample = sampleSectionLight(this.light.get(key)?.get(cy), (x & 15) + (z & 15) * 16 + (y & 15) * 256);\n return sample ? Math.max(sample.block, sample.sky) : 255;\n }\n\n /**\n * Places or replaces a block and refreshes neighboring faces.\n * Pass `undefined` or an air block to remove the block at these world block coordinates.\n */\n public async setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;\n public async setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;\n public async setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;\n public async setBlockAt(posOrX: number | Vector3 | TripleArray, yOrBlock?: number | Block, z?: number, block?: Block): Promise<Maybe<BlockInfo<SectionMeshing>>> {\n if (typeof posOrX == \"number\") {\n return this.setBlockAt(new Vector3(posOrX, yOrBlock as number, z), block as Block);\n }\n if (isTripleArray(posOrX)) {\n return this.setBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock as Block);\n }\n return this.placeBlock(posOrX, yOrBlock as Maybe<Block>);\n }\n\n private async placeBlock(pos: Vector3, value: Maybe<Block>, onBlocksChanged?: (positions: Vector3[]) => Promise<void>): Promise<Maybe<BlockInfo<SectionMeshing>>> {\n this.validatePosBounds(pos);\n const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);\n return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);\n }\n\n /**\n * Shows or hides a placed block without changing its data. Hidden blocks do not occlude neighbors.\n * Missing blocks are ignored; replacing or removing a block resets its visibility.\n */\n public async setBlockVisibleAt(x: number, y: number, z: number, visible: boolean): Promise<void>;\n public async setBlockVisibleAt(pos: Vector3, visible: boolean): Promise<void>;\n public async setBlockVisibleAt(pos: TripleArray, visible: boolean): Promise<void>;\n public async setBlockVisibleAt(posOrX: number | Vector3 | TripleArray, yOrVisible: number | boolean,\n z?: number, visible?: boolean): Promise<void> {\n if (typeof posOrX === \"number\") {\n return this.setBlockVisibleAt(new Vector3(posOrX, yOrVisible as number, z), visible!);\n }\n if (isTripleArray(posOrX)) {\n return this.setBlockVisibleAt(new Vector3(...posOrX), yOrVisible as boolean);\n }\n this.validatePosBounds(posOrX);\n await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible as boolean);\n }\n\n\n /**\n * Places a structure's blocks at their stored positions, then refreshes neighboring faces.\n * With `renderEntities`, also places supported saved mobs and applies supported appearance fields.\n *\n * @param useBatches - Yields between chunks by default. Set to `false` for sequential placement.\n * @param executor - Optional queue for batched placement. The caller remains responsible for stopping it.\n */\n public async placeMultiBlock(multiblock: MultiBlockStructure, useBatches: boolean = true, executor?: BatchedExecutor): Promise<void> {\n const placeEntities = this.entities?.prepare(multiblock.entities);\n const changes = new Map<string, Vector3>();\n try {\n await this.placeBlocks(multiblock, useBatches, executor, changes);\n await placeEntities?.();\n } finally {\n await this.updateCulling([...changes.values()]);\n }\n }\n\n private async placeBlocks(multiblock: MultiBlockStructure, useBatches: boolean, executor: BatchedExecutor | undefined,\n changes: Map<string, Vector3>): Promise<void> {\n const collect = async (positions: Vector3[]) => {\n for (const pos of positions) changes.set(pos.toArray().join(\",\"), pos);\n };\n const place = (block: MultiBlockBlock) => this.placeBlock(new Vector3(...block.position), block, collect);\n const keys = new Map<string, AssetKey>();\n const types = new Set<string>();\n for (const block of multiblock.blocks) {\n if (Chunk.isAir(block) || types.has(block.type)) continue;\n types.add(block.type);\n const key = AssetKey.parse(\"blockstates\", block.type);\n keys.set(key.serialize(), key);\n }\n const loaded = await BlockStates.getAll(keys.values());\n const states = new Map([...keys.keys()].map((key, i) => [key, loaded[i]]));\n\n if (!useBatches) {\n for (const block of multiblock.blocks) await place(block);\n return;\n }\n\n if (!executor) {\n const groups = new Map<Chunk<SectionMeshing>, { index: number; block: Maybe<Block> }[]>();\n const distinct = new Map<string, MultiBlockBlock>();\n const position = new Vector3();\n for (const block of multiblock.blocks) {\n if (this.sectionModels && !Chunk.isAir(block)) distinct.set(ChunkData.paletteKey(block), block);\n const [x, y, z] = block.position;\n this.validatePosBounds(position.set(x, y, z));\n const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16);\n const key = `${cx}_${cy}_${cz}`;\n const chunk = this._chunks.get(key) ?? (Chunk.isAir(block) ? undefined : this.getOrCreateChunkAt(position));\n if (!chunk) continue;\n let group = groups.get(chunk);\n if (!group) groups.set(chunk, group = []);\n group.push({ index: (y - cy * 16) * 256 + (z - cz * 16) * 16 + x - cx * 16, block });\n }\n if (this.sectionModels) {\n // States that first appear in later chunks load while earlier chunks are placed.\n for (const block of distinct.values()) {\n const state = states.get(AssetKey.parse(\"blockstates\", block.type).serialize());\n if (!state) continue;\n void (async () => {\n if (state.key && BlockEntities.entry(await BlockEntities.getIndex(state.key.root), state.key.toNamespacedString())) return;\n await this.sectionModels!.preload(state, block.properties);\n })().catch(() => undefined);\n }\n }\n await this.placeChunkGroups(groups, changes);\n return;\n }\n\n // Writes to the same position retain their input order.\n const positions = new Map<string, MultiBlockBlock[]>();\n for (const block of multiblock.blocks) {\n const key = block.position.join(\",\");\n const group = positions.get(key);\n if (group) group.push(block);\n else positions.set(key, [block]);\n }\n const groups = [...positions.values()];\n for (let i = 0; i < groups.length; i += executor.batch) {\n const results = await Promise.allSettled(groups.slice(i, i + executor.batch).map(blocks =>\n executor.submit(async () => {\n for (const block of blocks) await place(block);\n })\n ));\n const failure = results.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n }\n }\n\n private async placeChunkGroups(groups: Map<Chunk<SectionMeshing>, { index: number; block: Maybe<Block> }[]>,\n changes: Map<string, Vector3>): Promise<void> {\n let sliceStart = performance.now();\n for (const [chunk, blocks] of groups) {\n let positions: Vector3[] | undefined;\n try {\n positions = await chunk.placeBlocks(blocks);\n } finally {\n // Failed groups still clear cells and place their remaining blocks.\n positions ??= blocks.map(({ index }) => new Vector3(chunk.x * 16 + index % 16,\n chunk.y * 16 + Math.floor(index / 256), chunk.z * 16 + Math.floor(index / 16) % 16));\n for (const pos of positions) changes.set(`${pos.x},${pos.y},${pos.z}`, pos);\n }\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n }\n\n\n /** Replaces a chunk column's blocks, biomes, and saved light and, with `renderEntities`, its supported saved mobs. */\n public async placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void> {\n return this.placeColumn(chunk, executor);\n }\n\n /**\n * Replaces parsed columns in input order, then refreshes neighboring geometry once.\n * Duplicate coordinates retain their order. A failed column stops placement; queued refreshes finish before rejection.\n */\n public async placeChunks(chunks: readonly AnvilChunk[]): Promise<void> {\n const columns: AnvilChunk[] = [];\n for (const chunk of chunks) {\n const { x, z } = chunk ?? {};\n if (![x, z].every(Number.isSafeInteger)) {\n throw new RangeError(\"Chunk column coordinates must be safe integers\");\n }\n const sections = Array.from(chunk.sections, section => {\n const { y } = section ?? {};\n if (!Number.isSafeInteger(y)) throw new RangeError(\"Chunk section coordinates must be safe integers\");\n return { ...section, y };\n });\n columns.push({ ...chunk, x, z, sections });\n }\n if (!columns.length) return;\n await this.culling;\n let failed = false, failure: unknown, sliceStart = performance.now();\n try {\n for (const column of columns) {\n await this.placeColumn(column, undefined, true);\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n } catch (error) {\n failed = true;\n failure = error;\n } finally {\n try {\n const failures = await this.refreshBiomes(true);\n if (failures.size) log.warn(\"Failed to refresh biome colors\", failures.values().next().value);\n } catch (error) {\n if (!failed) { failed = true; failure = error; }\n }\n try {\n await this.updateCulling([]);\n } catch (error) {\n if (!failed) { failed = true; failure = error; }\n }\n }\n if (failed) throw failure;\n }\n\n private async placeColumn(chunk: AnvilChunk, executor?: BatchedExecutor, deferCulling = false): Promise<void> {\n if (![chunk.x, chunk.z].every(Number.isSafeInteger)) {\n throw new RangeError(\"Chunk column coordinates must be safe integers\");\n }\n if (!chunk.sections.every(section => Number.isSafeInteger(section.y))) {\n throw new RangeError(\"Chunk section coordinates must be safe integers\");\n }\n const lights = new Map<number, SectionLightData>();\n for (const section of chunk.sections) {\n const light = section.light ?? (chunk.lightValid === true ? {} : undefined);\n if (light) lights.set(section.y, copySectionLight(light));\n }\n this.entities?.clearColumn(chunk.x, chunk.z);\n const placeEntities = this.entities?.prepare(chunk.entities, [chunk.x, chunk.z]);\n const changes = new Map<string, Vector3>();\n const occupiedSections = new Set<number>();\n if (!executor) {\n for (const section of chunk.sections) {\n for (let index = 0; index < 4096; index++) {\n if (!section.data.idAt(index)) continue;\n occupiedSections.add(section.y);\n break;\n }\n }\n }\n try {\n await this.clearChunkColumn(chunk.x, chunk.z);\n const columnKey = `${chunk.x}_${chunk.z}`;\n if (lights.size) this.light.set(columnKey, lights);\n for (const [y, light] of lights) {\n if (light.sky) this.highestSkySection.set(columnKey, Math.max(y, this.highestSkySection.get(columnKey) ?? -Infinity));\n }\n if (chunk.lightValid !== undefined) this.lightValidity.set(columnKey, chunk.lightValid);\n if (this.savedLighting) {\n for (const y of lights.keys()) this.markSectionChanged({ x: chunk.x, y, z: chunk.z });\n }\n // Tall plants can sample the section below, so install all biomes before rendering.\n for (const section of chunk.sections) {\n if (section.biomes) {\n const position = new Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);\n this.validatePosBounds(position);\n const copy = [...section.biomes];\n if (copy.length !== 64 || !copy.every(id => typeof id === \"string\" && id.length > 0)) {\n throw new RangeError(\"Section biomes must contain 64 nonempty biome IDs\");\n }\n const key = `${chunk.x}_${chunk.z}`;\n let column = this.biomes.get(key);\n if (!column) this.biomes.set(key, column = new Map());\n column.set(section.y, copy);\n }\n }\n let sliceStart = performance.now();\n for (const section of chunk.sections) {\n if (!executor) {\n if (!occupiedSections.has(section.y)) continue;\n const position = new Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);\n this.validatePosBounds(position);\n const target = this.getOrCreateChunkAt(position);\n try {\n await target.placeSection(section.data);\n } finally {\n this.markSectionChanged(target);\n }\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n continue;\n }\n const blocks: MultiBlockBlock[] = [];\n for (let index = 0; index < 4096; index++) {\n const block = section.data.get(index);\n if (block) blocks.push({\n ...block,\n position: [chunk.x * 16 + index % 16,\n section.y * 16 + Math.floor(index / 256),\n chunk.z * 16 + Math.floor(index / 16) % 16]\n });\n }\n await this.placeBlocks({ size: [16, 16, 16], blocks }, true, executor, changes);\n }\n await placeEntities?.();\n } finally {\n this.markBiomesChanged(chunk.x, chunk.z, undefined, false);\n if (deferCulling) await this.updateCulling([...changes.values()], true);\n else {\n const failures = await this.refreshBiomes();\n if (failures.size) log.warn(\"Failed to refresh biome colors\", failures.values().next().value);\n await this.updateCulling([...changes.values()]);\n }\n }\n }\n\n /**\n * Removes blocks and owned entities at chunk-column coordinates, then refreshes neighboring faces and fluids.\n * Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.\n */\n public async unloadChunkColumn(x: number, z: number): Promise<void> {\n return this.unloadChunkColumns([{ x, z }]);\n }\n\n /**\n * Removes chunk columns together and refreshes surviving neighbors once.\n * Coordinates are absolute chunk columns. Duplicate and missing columns are ignored.\n */\n public async unloadChunkColumns(positions: readonly { x: number; z: number }[]): Promise<void> {\n const columns = new Map<string, { x: number; z: number }>();\n for (const position of positions) {\n const { x, z } = position ?? {};\n if (!Number.isInteger(x) || !Number.isInteger(z)) {\n throw new RangeError(\"Chunk column coordinates must be integers\");\n }\n columns.set(`${x}_${z}`, { x, z });\n }\n if (!columns.size) return;\n await this.culling;\n let sliceStart = performance.now();\n try {\n for (const { x, z } of columns.values()) {\n this.entities?.clearColumn(x, z);\n await this.clearChunkColumn(x, z);\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n } finally {\n const failures = await this.refreshBiomes(true);\n if (failures.size) log.warn(\"Failed to refresh biome colors\", failures.values().next().value);\n await this.updateCulling([]);\n }\n }\n\n private async clearChunkColumn(x: number, z: number): Promise<void> {\n this.biomes.delete(`${x}_${z}`);\n this.markBiomesChanged(x, z, undefined, false);\n if (this.savedLighting) {\n for (const y of this.light.get(`${x}_${z}`)?.keys() ?? []) this.markSectionChanged({ x, y, z });\n }\n this.light.delete(`${x}_${z}`);\n this.lightValidity.delete(`${x}_${z}`);\n this.highestSkySection.delete(`${x}_${z}`);\n const previous = [...this._chunks.entries()].filter(([, section]) => section.x === x && section.z === z);\n for (const [key, section] of previous) {\n this._chunks.delete(key);\n this.pendingCulling.delete(section);\n this.pendingBiomes.delete(section);\n await section.clear(false);\n this.markSectionChanged(section);\n }\n }\n\n private markSectionChanged(chunk: { x: number; y: number; z: number }): void {\n const current = this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`);\n if (current && current === chunk) this.pendingCulling.set(current, \"all\");\n for (let dy = -1; dy <= 1; dy++) {\n for (let dz = -1; dz <= 1; dz++) {\n for (let dx = -1; dx <= 1; dx++) {\n if (dx === 0 && dy === 0 && dz === 0) continue;\n const neighbor = this._chunks.get(`${chunk.x + dx}_${chunk.y + dy}_${chunk.z + dz}`);\n if (!neighbor) continue;\n let pending = this.pendingCulling.get(neighbor);\n if (pending === \"all\") continue;\n if (!pending) this.pendingCulling.set(neighbor, pending = new Set());\n for (let y = dy < 0 ? 15 : 0; y <= (dy > 0 ? 0 : 15); y++) {\n for (let z = dz < 0 ? 15 : 0; z <= (dz > 0 ? 0 : 15); z++) {\n for (let x = dx < 0 ? 15 : 0; x <= (dx > 0 ? 0 : 15); x++) {\n pending.add(y * 256 + z * 16 + x);\n }\n }\n }\n }\n }\n }\n }\n\n /** Removes all chunks and releases their blocks, section meshes, and owned entities. */\n public async clear(): Promise<void> {\n this.entities?.clear();\n await this.culling;\n const chunks = [...this._chunks.values()];\n this._chunks.clear();\n this.biomes.clear();\n this.biomeBlend?.clear();\n this.pendingBiomes.clear();\n this.light.clear();\n this.lightValidity.clear();\n this.highestSkySection.clear();\n for (const chunk of chunks) {\n await chunk.dispose();\n }\n this.sectionModels?.clear();\n }\n\n private updateCulling(positions: Vector3[], defer = false): Promise<void> {\n const neighbor = new Vector3();\n for (const pos of positions) {\n const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);\n const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);\n const lx = pos.x - cx * 16, ly = pos.y - cy * 16, lz = pos.z - cz * 16;\n // Fluid surfaces and ambient occlusion also depend on edge and corner neighbors.\n for (let y = -1; y <= 1; y++) {\n for (let z = -1; z <= 1; z++) {\n for (let x = -1; x <= 1; x++) {\n const nx = lx + x, ny = ly + y, nz = lz + z;\n const section = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16 ? chunk\n : this._chunks.get(`${cx + Math.floor(nx / 16)}_${cy + Math.floor(ny / 16)}_${cz + Math.floor(nz / 16)}`);\n if (!section) continue;\n const index = (ny & 15) * 256 + (nz & 15) * 16 + (nx & 15);\n let pending = this.pendingCulling.get(section);\n if (pending === \"all\" || pending?.has(index)) continue;\n if (Math.abs(x) + Math.abs(y) + Math.abs(z) > 1\n && !this._ambientOcclusion && !section.isFluidIndex(index)) continue;\n if (!pending) this.pendingCulling.set(section, pending = new Set());\n pending.add(index);\n }\n }\n }\n }\n if (defer) return Promise.resolve();\n // Adjacent batched placements share one drain so they cannot replace the same model concurrently.\n return this.culling ??= Promise.resolve().then(async () => {\n let sliceStart = performance.now();\n try {\n const culling = await loadBlockCulling();\n while (this.pendingCulling.size) {\n const batch = new Map(this.pendingCulling);\n this.pendingCulling.clear();\n try {\n for (const [chunk, indices] of batch) {\n const neighbors = CUBE_FACE_OFFSETS.map(([x, y, z]) =>\n this._chunks.get(`${chunk.x + x}_${chunk.y + y}_${chunk.z + z}`));\n const neighborAt = (x: number, y: number, z: number): [Maybe<Chunk<SectionMeshing>>, number] => {\n const lx = x - chunk.x * 16, ly = y - chunk.y * 16, lz = z - chunk.z * 16;\n const section = neighbors[lx >= 16 ? 0 : lx < 0 ? 1 : ly >= 16 ? 2 : ly < 0 ? 3 : lz >= 16 ? 4 : 5];\n return [section, (ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)];\n };\n const masks = chunk.updateCullMasks(indices === \"all\" ? undefined : indices, (x, y, z) => {\n const [section, i] = neighborAt(x, y, z);\n return section?.isOccludingIndex(i) ?? false;\n }, culling, (x, y, z) => {\n const [section, i] = neighborAt(x, y, z);\n return section?.visibleBlockIndex(i);\n });\n const fluidIndices = indices === \"all\" ? (function* () {\n for (let index = 0; index < 4096; index++) yield index;\n })() : indices;\n for (const index of fluidIndices) {\n if (!chunk.fluidByteIndex(index) || !chunk.isBlockVisibleIndex(index)) continue;\n const lx = index % 16, ly = Math.floor(index / 256), lz = Math.floor(index / 16) % 16;\n const wx = chunk.x * 16 + lx, wy = chunk.y * 16 + ly, wz = chunk.z * 16 + lz;\n const block = chunk.getBlockAt(neighbor.set(wx, wy, wz))!;\n if (block.object?.fluidKind) {\n await block.object.updateFluid((x, y, z) => {\n const nx = lx + x, ny = ly + y, nz = lz + z;\n const section = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16 ? chunk\n : this._chunks.get(`${chunk.x + Math.floor(nx / 16)}_${chunk.y + Math.floor(ny / 16)}_${chunk.z + Math.floor(nz / 16)}`);\n const neighborIndex = (ny & 15) * 256 + (nz & 15) * 16 + (nx & 15);\n const byte = section?.fluidByteIndex(neighborIndex) ?? 0;\n return { fluid: fluidKindOf(byte), level: byte & 15,\n solid: section?.isOccludingIndex(neighborIndex) ?? false };\n });\n }\n }\n for (const [index, mask] of masks) await chunk.setCullMaskIndex(index, mask);\n await chunk.refreshLight(indices === \"all\" ? undefined : indices);\n chunk.refreshAmbientOcclusion(this._ambientOcclusion);\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n const pending: Promise<void>[] = [];\n for (const chunk of [...batch.keys()]) {\n const build = (async () => {\n await chunk.rebuildSectionMesh();\n batch.delete(chunk);\n })();\n // Handle rejections while dispatch yields; all started builds settle before their results are checked.\n void build.catch(() => undefined);\n pending.push(build);\n if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {\n await yieldToEventLoop();\n sliceStart = performance.now();\n }\n }\n const builds = await Promise.allSettled(pending);\n const failure = builds.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n } catch (error) {\n for (const [chunk, indices] of batch) {\n const pending = this.pendingCulling.get(chunk);\n this.pendingCulling.set(chunk, indices === \"all\" || pending === \"all\" ? \"all\"\n : new Set([...indices, ...pending ?? []]));\n }\n throw error;\n }\n }\n } finally {\n this.culling = undefined;\n }\n });\n }\n\n private getOrCreateChunkAt(pos: Vector3): Chunk<SectionMeshing> {\n const key = this.worldPosToChunkKey(pos);\n let chunk = this._chunks.get(key);\n if (typeof chunk === \"undefined\") {\n const x = Math.floor(pos.x / 16), y = Math.floor(pos.y / 16), z = Math.floor(pos.z / 16);\n chunk = new Chunk<SectionMeshing>(this.scene, x, y, z,\n (positions, defer) => this.updateCulling(positions, defer), this.sectionModels, (x, y, z) => {\n const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16);\n const section = this._chunks.get(`${cx}_${cy}_${cz}`);\n const index = (y - cy * 16) * 256 + (z - cz * 16) * 16 + x - cx * 16;\n return (section?.fluidByteIndex(index) ?? 0) | (section?.isOccludingIndex(index) ? 64 : 0);\n }, (x, y, z) => this.getBiomeAt(x, y, z), async biomes => {\n if (this._chunks.get(key) !== chunk) return;\n const columnKey = `${x}_${z}`;\n let column = this.biomes.get(columnKey);\n if (biomes) {\n if (!column) this.biomes.set(columnKey, column = new Map());\n column.set(y, biomes);\n } else {\n column?.delete(y);\n if (!column?.size) this.biomes.delete(columnKey);\n }\n if (this.biomeBlend) {\n const queued = this.markBiomesChanged(x, z, y);\n const failures = await this.refreshBiomes();\n for (const chunk of queued) if (failures.has(chunk)) throw failures.get(chunk);\n } else {\n await chunk!.refreshBiomes();\n // Upper tall-plant halves at the boundary sample the section below.\n await this._chunks.get(`${x}_${y + 1}_${z}`)?.refreshBiomes();\n }\n }, this.savedLighting ? (x, y, z) => this.lightLevelAt(x, y, z) : undefined, async () => {\n if (this._chunks.get(key) !== chunk) return;\n const columnKey = `${x}_${z}`, column = this.light.get(columnKey);\n if (!column?.delete(y)) return;\n if (!column.size) this.light.delete(columnKey);\n this.highestSkySection.delete(columnKey);\n for (const [y, light] of column) {\n if (light.sky) this.highestSkySection.set(columnKey, Math.max(y, this.highestSkySection.get(columnKey) ?? -Infinity));\n }\n if (this.savedLighting) {\n this.markSectionChanged(chunk!);\n await this.updateCulling([]);\n }\n }, this.ambientLight, () => this.biomeBlend);\n this._chunks.set(key, chunk);\n }\n return chunk;\n }\n\n /** Returns the loaded chunk containing a world block position, without creating a chunk. */\n public getChunkAt(pos: Vector3): Maybe<Chunk<SectionMeshing>> {\n return this._chunks.get(this.worldPosToChunkKey(pos));\n }\n\n\n /** Converts block coordinates to scene units by multiplying each component by 16. */\n static worldToScenePosition(pos: Vector3): Vector3 {\n return new Vector3(\n pos.x * 16.0,\n pos.y * 16.0,\n pos.z * 16.0\n );\n }\n\n /** Converts scene units to block coordinates without rounding to an integer block. */\n static sceneToWorldPosition(pos: Vector3): Vector3 {\n return new Vector3(\n pos.x / 16.0,\n pos.y / 16.0,\n pos.z / 16.0\n );\n }\n\n worldPosToChunkKey(pos: Vector3): string {\n const chunkX = Math.floor(pos.x / 16);\n const chunkY = Math.floor(pos.y / 16);\n const chunkZ = Math.floor(pos.z / 16);\n return `${chunkX}_${chunkY}_${chunkZ}`;\n }\n\n validatePosBounds(pos: Vector3): void {\n if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {\n throw new RangeError(\"Block coordinates must be integers\");\n }\n }\n\n}\n\n\n/** Settings passed as the second argument to `new MineRenderWorld(scene, options)`. */\nexport interface MineRenderWorldOptions<SectionMeshing extends boolean = boolean> {\n /** Render supported saved mobs at their position and yaw, including supported appearance fields. Defaults to false. */\n renderEntities?: boolean;\n /** Merge block models of any shape and fluid surfaces into per-section meshes; block entities keep individual objects. Merged blocks have no individual object. */\n sectionMeshing?: SectionMeshing;\n /** Shade blocks and fluids with saved sky/block light. Missing or invalid data keeps preview brightness. Defaults to false. Requires `sectionMeshing`. */\n savedLighting?: boolean;\n /** Minimum brightness for saved lighting, from 0 to 1, like a dimension type's `ambient_light`. Defaults to 0. */\n ambientLight?: number;\n /** Bake corner shading from neighboring opaque full cubes. Defaults to false; no per-frame shading pass is added. Requires `sectionMeshing`. */\n ambientOcclusion?: boolean;\n /** Average neighboring biome colors within this horizontal radius, from 0 to 7 blocks. Defaults to 0 (off). Requires `sectionMeshing`. */\n biomeBlendRadius?: number;\n /** Maximum width and height of each section atlas page, in pixels. Defaults to 2048. */\n maxAtlasSize?: number;\n}\n"],"mappings":";AAEA,SAAoB,eAAe;AACnC,SAAS,qBAAkC;AAC3C,SAAgB,wBAAwB;AACxC,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAI1B,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB;AAElC,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAG5B,SAAS,YAAY,gCAAgC;AACrD,SAAS,kBAAkB,0BAA8D;AACzF,SAAS,wBAAwB;AACjC,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,iBAAiB;AACpC,IAAM,oBAAoB;AAQnB,IAAM,kBAAN,MAA8D;AAAA,EAsBjE,YAAY,OAAwB,UAAkD,CAAC,GAAG;AAlB1F,SAAiB,UAA8C,oBAAI,IAAI;AACvE,SAAiB,SAAS,oBAAI,IAA4C;AAC1E,SAAiB,QAAQ,oBAAI,IAA2C;AACxE,SAAiB,gBAAgB,oBAAI,IAAqB;AAC1D,SAAiB,oBAAoB,oBAAI,IAAoB;AAI7D,SAAQ,0BAA0B;AAGlC,SAAiB,gBAAgB,oBAAI,IAAmE;AAIxG,SAAiB,iBAAiB,oBAAI,IAAgD;AAIlF,QAAI,QAAQ,iBAAiB,CAAC,QAAQ,eAAgB,OAAM,IAAI,UAAU,uCAAuC;AACjH,QAAI,QAAQ,oBAAoB,CAAC,QAAQ,eAAgB,OAAM,IAAI,UAAU,0CAA0C;AACvH,QAAI,QAAQ,iBAAiB,WAAc,CAAC,OAAO,SAAS,QAAQ,YAAY,KAAK,QAAQ,eAAe,KAAK,QAAQ,eAAe,IAAI;AACxI,YAAM,IAAI,WAAW,2CAA2C;AAAA,IACpE;AACA,SAAK,oBAAoB,QAAQ,oBAAoB;AACrD,6BAAyB,KAAK,iBAAiB;AAC/C,QAAI,KAAK,oBAAoB,KAAK,CAAC,QAAQ,eAAgB,OAAM,IAAI,UAAU,0CAA0C;AACzH,QAAI,KAAK,kBAAmB,MAAK,aAAa,IAAI,WAAW,CAAC,GAAG,GAAG,MAAM,KAAK,WAAW,GAAG,GAAG,CAAC,GAAG,KAAK,iBAAiB;AAC1H,SAAK,QAAQ;AACb,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,oBAAoB,QAAQ,oBAAoB;AACrD,QAAI,QAAQ,eAAgB,MAAK,gBAAgB,IAAI,cAAc,QAAQ,YAAY;AACvF,QAAI,QAAQ,eAAgB,MAAK,WAAW,IAAI,cAAc,KAAK;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,QAAQ,WAA0D;AACrE,WAAO,MAAM,QAAQ,KAAK,QAAQ,OAAO,GAAG,SAAS;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,gBAAgB,WAA2D;AAC9E,WAAO,KAAK,UAAU,QAAQ,SAAS;AAAA,EAC3C;AAAA;AAAA,EAGA,IAAW,mBAA4B;AACnC,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,MAAa,oBAAoB,SAAiC;AAC9D,QAAI,OAAO,YAAY,UAAW,OAAM,IAAI,UAAU,qCAAqC;AAC3F,QAAI,WAAW,CAAC,KAAK,cAAe,OAAM,IAAI,UAAU,0CAA0C;AAClG,QAAI,YAAY,KAAK,qBAAqB,CAAC,KAAK,yBAAyB;AACrE,YAAM,KAAK;AACX;AAAA,IACJ;AACA,SAAK,oBAAoB;AACzB,SAAK,0BAA0B;AAC/B,eAAW,SAAS,KAAK,QAAQ,OAAO,EAAG,MAAK,eAAe,IAAI,OAAO,KAAK;AAC/E,UAAM,KAAK,cAAc,CAAC,CAAC;AAC3B,SAAK,0BAA0B;AAAA,EACnC;AAAA;AAAA,EAGA,IAAW,mBAA2B;AAClC,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,MAAa,oBAAoB,QAA+B;AAC5D,6BAAyB,MAAM;AAC/B,QAAI,SAAS,KAAK,CAAC,KAAK,cAAe,OAAM,IAAI,UAAU,0CAA0C;AACrG,QAAI,WAAW,KAAK,mBAAmB;AACnC,WAAK,oBAAoB;AACzB,WAAK,YAAY,MAAM;AACvB,WAAK,aAAa,SAAS,IAAI,WAAW,CAAC,GAAG,GAAG,MAAM,KAAK,WAAW,GAAG,GAAG,CAAC,GAAG,MAAM,IAAI;AAC3F,iBAAW,SAAS,KAAK,QAAQ,OAAO,EAAG,MAAK,cAAc,IAAI,OAAO,MAAS;AAAA,IACtF;AACA,UAAM,WAAW,MAAM,KAAK,cAAc;AAC1C,QAAI,SAAS,KAAM,OAAM,SAAS,OAAO,EAAE,KAAK,EAAE;AAAA,EACtD;AAAA,EAEQ,kBAAkB,GAAW,GAAW,GAAY,gBAAgB,MAA+B;AACvG,UAAM,SAAkC,CAAC;AACzC,QAAI,CAAC,KAAK,WAAY,QAAO;AAC7B,SAAK,WAAW,iBAAiB,GAAG,CAAC;AACrC,eAAW,SAAS,KAAK,QAAQ,OAAO,GAAG;AACvC,UAAI,KAAK,IAAI,MAAM,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI,CAAC,IAAI,KAClD,CAAC,iBAAiB,MAAM,MAAM,KAAK,MAAM,MAAM,KAC/C,MAAM,UAAa,MAAM,MAAM,KAAK,MAAM,MAAM,IAAI,EAAG;AAC9D,aAAO,KAAK,KAAK;AACjB,UAAI,CAAC,KAAK,cAAc,IAAI,KAAK,EAAG,MAAK,cAAc,IAAI,OAAO,CAAC,CAAC;AACpE,YAAM,UAAU,KAAK,cAAc,IAAI,KAAK;AAC5C,UAAI,WAAW,CAAC,QAAQ,KAAK,YAAU,OAAO,MAAM,KAAK,OAAO,MAAM,CAAC,EAAG,SAAQ,KAAK,EAAE,GAAG,EAAE,CAAC;AAAA,IACnG;AACA,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,cAAc,eAAe,OAAqD;AAC5F,QAAI,KAAK,iBAAiB;AACtB,YAAM,KAAK;AACX,UAAI,CAAC,cAAc;AACf,YAAI,KAAK,eAAe,KAAM,OAAM,KAAK,cAAc,CAAC,CAAC;AAAA,YACpD,OAAM,KAAK;AAAA,MACpB;AAAA,IACJ;AACA,QAAI,CAAC,KAAK,cAAc,KAAM,QAAO,oBAAI,IAAI;AAC7C,WAAO,KAAK,oBAAL,KAAK,kBAAoB,QAAQ,QAAQ,EAAE,KAAK,YAAY;AAC/D,YAAM,WAAW,oBAAI,IAAoC;AACzD,YAAM,QAAQ,CAAC,GAAG,KAAK,cAAc,KAAK,CAAC;AAC3C,UAAI,aAAa,YAAY,IAAI;AACjC,UAAI;AACA,mBAAW,SAAS,OAAO;AACvB,gBAAM,UAAU,KAAK,cAAc,IAAI,KAAK;AAC5C,eAAK,cAAc,OAAO,KAAK;AAC/B,cAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,MAAM,MAAO;AACpE,cAAI;AACA,kBAAM,MAAM,cAAc,SAAS,YAAY;AAAA,UACnD,SAAS,OAAO;AACZ,qBAAS,IAAI,OAAO,KAAK;AACzB,gBAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,MAAM,MAAO,MAAK,cAAc,IAAI,OAAO,MAAS;AAAA,UAC/G;AACA,cAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,kBAAM,iBAAiB;AACvB,yBAAa,YAAY,IAAI;AAAA,UACjC;AAAA,QACJ;AACA,eAAO;AAAA,MACX,UAAE;AACE,aAAK,kBAAkB;AAAA,MAC3B;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAMO,WAAW,QAAwC,GAAY,GAA8C;AAChH,QAAI,OAAO,UAAU,UAAU;AAC3B,aAAO,KAAK,WAAW,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC;AAAA,IACpD;AACA,QAAI,cAAc,MAAM,GAAG;AACvB,aAAO,KAAK,WAAW,IAAI,QAAQ,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;AAAA,IACvE;AACA,SAAK,kBAAkB,MAAM;AAC7B,WAAO,KAAK,WAAW,MAAM,GAAG,WAAW,MAAM;AAAA,EACrD;AAAA,EAMO,WAAW,QAAwC,GAAY,GAA2B;AAC7F,QAAI,OAAO,WAAW,SAAU,QAAO,KAAK,WAAW,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC;AAChF,QAAI,cAAc,MAAM,EAAG,QAAO,KAAK,WAAW,IAAI,QAAQ,GAAG,MAAM,CAAC;AACxE,SAAK,kBAAkB,MAAM;AAC7B,UAAM,KAAK,KAAK,MAAM,OAAO,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,OAAO,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,OAAO,IAAI,EAAE;AACnG,UAAM,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,OAAO,IAAI,KAAK;AAC7E,WAAO,KAAK,OAAO,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IACzC,KAAK,MAAM,KAAK,CAAC,IAAI,KAAK,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,MAAM,KAAK,CAAC,IAAI,EAAE;AAAA,EAC7E;AAAA,EASO,WAAW,QAAwC,GAAY,GAAqC;AACvG,QAAI,OAAO,WAAW,SAAU,QAAO,KAAK,WAAW,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC;AAChF,QAAI,cAAc,MAAM,EAAG,QAAO,KAAK,WAAW,IAAI,QAAQ,GAAG,MAAM,CAAC;AACxE,SAAK,kBAAkB,MAAM;AAC7B,UAAM,EAAE,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI;AAC5B,UAAM,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,KAAK,EAAE,GAAG,KAAK,KAAK,MAAM,KAAK,EAAE;AAChF,UAAM,MAAM,GAAG,EAAE,IAAI,EAAE,IAAI,MAAM,KAAK,kBAAkB,IAAI,GAAG;AAC/D,UAAM,SAAS,mBAAmB,KAAK,MAAM,IAAI,GAAG,GAAG,IAAI,EAAE,IAAI,IAAI,OAAO,KAAK,MAAM,MAAM,KAAK,MAAM,GAAG;AAC3G,WAAO,QAAQ,UAAa,KAAK,MAAM,EAAE,OAAO,QAAQ,SAAS,GAAG,KAAK,GAAG,IAAI;AAAA,EACpF;AAAA,EAEQ,aAAa,GAAW,GAAW,GAAmB;AAC1D,UAAM,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,MAAM,GAAG,EAAE,IAAI,EAAE;AAClG,QAAI,KAAK,cAAc,IAAI,GAAG,MAAM,MAAO,QAAO;AAClD,UAAM,MAAM,KAAK,kBAAkB,IAAI,GAAG;AAC1C,QAAI,QAAQ,UAAa,KAAK,IAAK,QAAO;AAC1C,UAAM,SAAS,mBAAmB,KAAK,MAAM,IAAI,GAAG,GAAG,IAAI,EAAE,IAAI,IAAI,OAAO,IAAI,MAAM,MAAM,IAAI,MAAM,GAAG;AACzG,WAAO,SAAS,KAAK,IAAI,OAAO,OAAO,OAAO,GAAG,IAAI;AAAA,EACzD;AAAA,EASA,MAAa,WAAW,QAAwC,UAA2B,GAAY,OAA0D;AAC7J,QAAI,OAAO,UAAU,UAAU;AAC3B,aAAO,KAAK,WAAW,IAAI,QAAQ,QAAQ,UAAoB,CAAC,GAAG,KAAc;AAAA,IACrF;AACA,QAAI,cAAc,MAAM,GAAG;AACvB,aAAO,KAAK,WAAW,IAAI,QAAQ,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,QAAiB;AAAA,IAC1F;AACA,WAAO,KAAK,WAAW,QAAQ,QAAwB;AAAA,EAC3D;AAAA,EAEA,MAAc,WAAW,KAAc,OAAqB,iBAAsG;AAC9J,SAAK,kBAAkB,GAAG;AAC1B,UAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,KAAK,WAAW,GAAG,IAAI,KAAK,mBAAmB,GAAG;AACrF,WAAO,OAAO,kBAAkB,MAAM,mBAAmB,GAAG,GAAG,OAAO,KAAK,eAAe;AAAA,EAC9F;AAAA,EASA,MAAa,kBAAkB,QAAwC,YACxC,GAAY,SAAkC;AACzE,QAAI,OAAO,WAAW,UAAU;AAC5B,aAAO,KAAK,kBAAkB,IAAI,QAAQ,QAAQ,YAAsB,CAAC,GAAG,OAAQ;AAAA,IACxF;AACA,QAAI,cAAc,MAAM,GAAG;AACvB,aAAO,KAAK,kBAAkB,IAAI,QAAQ,GAAG,MAAM,GAAG,UAAqB;AAAA,IAC/E;AACA,SAAK,kBAAkB,MAAM;AAC7B,UAAM,KAAK,WAAW,MAAM,GAAG,kBAAkB,QAAQ,UAAqB;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,gBAAgB,YAAiC,aAAsB,MAAM,UAA2C;AACjI,UAAM,gBAAgB,KAAK,UAAU,QAAQ,WAAW,QAAQ;AAChE,UAAM,UAAU,oBAAI,IAAqB;AACzC,QAAI;AACA,YAAM,KAAK,YAAY,YAAY,YAAY,UAAU,OAAO;AAChE,YAAM,gBAAgB;AAAA,IAC1B,UAAE;AACE,YAAM,KAAK,cAAc,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,MAAc,YAAY,YAAiC,YAAqB,UACtD,SAA8C;AACpE,UAAM,UAAU,OAAOA,eAAyB;AAC5C,iBAAW,OAAOA,WAAW,SAAQ,IAAI,IAAI,QAAQ,EAAE,KAAK,GAAG,GAAG,GAAG;AAAA,IACzE;AACA,UAAM,QAAQ,CAAC,UAA2B,KAAK,WAAW,IAAI,QAAQ,GAAG,MAAM,QAAQ,GAAG,OAAO,OAAO;AACxG,UAAM,OAAO,oBAAI,IAAsB;AACvC,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,SAAS,WAAW,QAAQ;AACnC,UAAI,MAAM,MAAM,KAAK,KAAK,MAAM,IAAI,MAAM,IAAI,EAAG;AACjD,YAAM,IAAI,MAAM,IAAI;AACpB,YAAM,MAAM,SAAS,MAAM,eAAe,MAAM,IAAI;AACpD,WAAK,IAAI,IAAI,UAAU,GAAG,GAAG;AAAA,IACjC;AACA,UAAM,SAAS,MAAM,YAAY,OAAO,KAAK,OAAO,CAAC;AACrD,UAAM,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAEzE,QAAI,CAAC,YAAY;AACb,iBAAW,SAAS,WAAW,OAAQ,OAAM,MAAM,KAAK;AACxD;AAAA,IACJ;AAEA,QAAI,CAAC,UAAU;AACX,YAAMC,UAAS,oBAAI,IAAqE;AACxF,YAAM,WAAW,oBAAI,IAA6B;AAClD,YAAM,WAAW,IAAI,QAAQ;AAC7B,iBAAW,SAAS,WAAW,QAAQ;AACnC,YAAI,KAAK,iBAAiB,CAAC,MAAM,MAAM,KAAK,EAAG,UAAS,IAAI,UAAU,WAAW,KAAK,GAAG,KAAK;AAC9F,cAAM,CAAC,GAAG,GAAG,CAAC,IAAI,MAAM;AACxB,aAAK,kBAAkB,SAAS,IAAI,GAAG,GAAG,CAAC,CAAC;AAC5C,cAAM,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI,EAAE;AAC9E,cAAM,MAAM,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE;AAC7B,cAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG,MAAM,MAAM,MAAM,KAAK,IAAI,SAAY,KAAK,mBAAmB,QAAQ;AACzG,YAAI,CAAC,MAAO;AACZ,YAAI,QAAQA,QAAO,IAAI,KAAK;AAC5B,YAAI,CAAC,MAAO,CAAAA,QAAO,IAAI,OAAO,QAAQ,CAAC,CAAC;AACxC,cAAM,KAAK,EAAE,QAAQ,IAAI,KAAK,MAAM,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC;AAAA,MACvF;AACA,UAAI,KAAK,eAAe;AAEpB,mBAAW,SAAS,SAAS,OAAO,GAAG;AACnC,gBAAM,QAAQ,OAAO,IAAI,SAAS,MAAM,eAAe,MAAM,IAAI,EAAE,UAAU,CAAC;AAC9E,cAAI,CAAC,MAAO;AACZ,gBAAM,YAAY;AACd,gBAAI,MAAM,OAAO,cAAc,MAAM,MAAM,cAAc,SAAS,MAAM,IAAI,IAAI,GAAG,MAAM,IAAI,mBAAmB,CAAC,EAAG;AACpH,kBAAM,KAAK,cAAe,QAAQ,OAAO,MAAM,UAAU;AAAA,UAC7D,GAAG,EAAE,MAAM,MAAM,MAAS;AAAA,QAC9B;AAAA,MACJ;AACA,YAAM,KAAK,iBAAiBA,SAAQ,OAAO;AAC3C;AAAA,IACJ;AAGA,UAAM,YAAY,oBAAI,IAA+B;AACrD,eAAW,SAAS,WAAW,QAAQ;AACnC,YAAM,MAAM,MAAM,SAAS,KAAK,GAAG;AACnC,YAAM,QAAQ,UAAU,IAAI,GAAG;AAC/B,UAAI,MAAO,OAAM,KAAK,KAAK;AAAA,UACtB,WAAU,IAAI,KAAK,CAAC,KAAK,CAAC;AAAA,IACnC;AACA,UAAM,SAAS,CAAC,GAAG,UAAU,OAAO,CAAC;AACrC,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,SAAS,OAAO;AACpD,YAAM,UAAU,MAAM,QAAQ,WAAW,OAAO,MAAM,GAAG,IAAI,SAAS,KAAK,EAAE;AAAA,QAAI,YAC7E,SAAS,OAAO,YAAY;AACxB,qBAAW,SAAS,OAAQ,OAAM,MAAM,KAAK;AAAA,QACjD,CAAC;AAAA,MACL,CAAC;AACD,YAAM,UAAU,QAAQ,KAAK,YAAU,OAAO,WAAW,UAAU;AACnE,UAAI,SAAS,WAAW,WAAY,OAAM,QAAQ;AAAA,IACtD;AAAA,EACJ;AAAA,EAEA,MAAc,iBAAiB,QACA,SAA8C;AACzE,QAAI,aAAa,YAAY,IAAI;AACjC,eAAW,CAAC,OAAO,MAAM,KAAK,QAAQ;AAClC,UAAI;AACJ,UAAI;AACA,oBAAY,MAAM,MAAM,YAAY,MAAM;AAAA,MAC9C,UAAE;AAEE,kCAAc,OAAO,IAAI,CAAC,EAAE,MAAM,MAAM,IAAI;AAAA,UAAQ,MAAM,IAAI,KAAK,QAAQ;AAAA,UACvE,MAAM,IAAI,KAAK,KAAK,MAAM,QAAQ,GAAG;AAAA,UAAG,MAAM,IAAI,KAAK,KAAK,MAAM,QAAQ,EAAE,IAAI;AAAA,QAAE,CAAC;AACvF,mBAAW,OAAO,UAAW,SAAQ,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG;AAAA,MAC9E;AACA,UAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,cAAM,iBAAiB;AACvB,qBAAa,YAAY,IAAI;AAAA,MACjC;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAIA,MAAa,WAAW,OAAmB,UAA2C;AAClF,WAAO,KAAK,YAAY,OAAO,QAAQ;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,YAAY,QAA8C;AACnE,UAAM,UAAwB,CAAC;AAC/B,eAAW,SAAS,QAAQ;AACxB,YAAM,EAAE,GAAG,EAAE,IAAI,SAAS,CAAC;AAC3B,UAAI,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,OAAO,aAAa,GAAG;AACrC,cAAM,IAAI,WAAW,gDAAgD;AAAA,MACzE;AACA,YAAM,WAAW,MAAM,KAAK,MAAM,UAAU,aAAW;AACnD,cAAM,EAAE,EAAE,IAAI,WAAW,CAAC;AAC1B,YAAI,CAAC,OAAO,cAAc,CAAC,EAAG,OAAM,IAAI,WAAW,iDAAiD;AACpG,eAAO,EAAE,GAAG,SAAS,EAAE;AAAA,MAC3B,CAAC;AACD,cAAQ,KAAK,EAAE,GAAG,OAAO,GAAG,GAAG,SAAS,CAAC;AAAA,IAC7C;AACA,QAAI,CAAC,QAAQ,OAAQ;AACrB,UAAM,KAAK;AACX,QAAI,SAAS,OAAO,SAAkB,aAAa,YAAY,IAAI;AACnE,QAAI;AACA,iBAAW,UAAU,SAAS;AAC1B,cAAM,KAAK,YAAY,QAAQ,QAAW,IAAI;AAC9C,YAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,gBAAM,iBAAiB;AACvB,uBAAa,YAAY,IAAI;AAAA,QACjC;AAAA,MACJ;AAAA,IACJ,SAAS,OAAO;AACZ,eAAS;AACT,gBAAU;AAAA,IACd,UAAE;AACE,UAAI;AACA,cAAM,WAAW,MAAM,KAAK,cAAc,IAAI;AAC9C,YAAI,SAAS,KAAM,KAAI,KAAK,kCAAkC,SAAS,OAAO,EAAE,KAAK,EAAE,KAAK;AAAA,MAChG,SAAS,OAAO;AACZ,YAAI,CAAC,QAAQ;AAAE,mBAAS;AAAM,oBAAU;AAAA,QAAO;AAAA,MACnD;AACA,UAAI;AACA,cAAM,KAAK,cAAc,CAAC,CAAC;AAAA,MAC/B,SAAS,OAAO;AACZ,YAAI,CAAC,QAAQ;AAAE,mBAAS;AAAM,oBAAU;AAAA,QAAO;AAAA,MACnD;AAAA,IACJ;AACA,QAAI,OAAQ,OAAM;AAAA,EACtB;AAAA,EAEA,MAAc,YAAY,OAAmB,UAA4B,eAAe,OAAsB;AAC1G,QAAI,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,OAAO,aAAa,GAAG;AACjD,YAAM,IAAI,WAAW,gDAAgD;AAAA,IACzE;AACA,QAAI,CAAC,MAAM,SAAS,MAAM,aAAW,OAAO,cAAc,QAAQ,CAAC,CAAC,GAAG;AACnE,YAAM,IAAI,WAAW,iDAAiD;AAAA,IAC1E;AACA,UAAM,SAAS,oBAAI,IAA8B;AACjD,eAAW,WAAW,MAAM,UAAU;AAClC,YAAM,QAAQ,QAAQ,UAAU,MAAM,eAAe,OAAO,CAAC,IAAI;AACjE,UAAI,MAAO,QAAO,IAAI,QAAQ,GAAG,iBAAiB,KAAK,CAAC;AAAA,IAC5D;AACA,SAAK,UAAU,YAAY,MAAM,GAAG,MAAM,CAAC;AAC3C,UAAM,gBAAgB,KAAK,UAAU,QAAQ,MAAM,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;AAC/E,UAAM,UAAU,oBAAI,IAAqB;AACzC,UAAM,mBAAmB,oBAAI,IAAY;AACzC,QAAI,CAAC,UAAU;AACX,iBAAW,WAAW,MAAM,UAAU;AAClC,iBAAS,QAAQ,GAAG,QAAQ,MAAM,SAAS;AACvC,cAAI,CAAC,QAAQ,KAAK,KAAK,KAAK,EAAG;AAC/B,2BAAiB,IAAI,QAAQ,CAAC;AAC9B;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AACA,QAAI;AACA,YAAM,KAAK,iBAAiB,MAAM,GAAG,MAAM,CAAC;AAC5C,YAAM,YAAY,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC;AACvC,UAAI,OAAO,KAAM,MAAK,MAAM,IAAI,WAAW,MAAM;AACjD,iBAAW,CAAC,GAAG,KAAK,KAAK,QAAQ;AAC7B,YAAI,MAAM,IAAK,MAAK,kBAAkB,IAAI,WAAW,KAAK,IAAI,GAAG,KAAK,kBAAkB,IAAI,SAAS,KAAK,SAAS,CAAC;AAAA,MACxH;AACA,UAAI,MAAM,eAAe,OAAW,MAAK,cAAc,IAAI,WAAW,MAAM,UAAU;AACtF,UAAI,KAAK,eAAe;AACpB,mBAAW,KAAK,OAAO,KAAK,EAAG,MAAK,mBAAmB,EAAE,GAAG,MAAM,GAAG,GAAG,GAAG,MAAM,EAAE,CAAC;AAAA,MACxF;AAEA,iBAAW,WAAW,MAAM,UAAU;AAClC,YAAI,QAAQ,QAAQ;AAChB,gBAAM,WAAW,IAAI,QAAQ,MAAM,IAAI,IAAI,QAAQ,IAAI,IAAI,MAAM,IAAI,EAAE;AACvE,eAAK,kBAAkB,QAAQ;AAC/B,gBAAM,OAAO,CAAC,GAAG,QAAQ,MAAM;AAC/B,cAAI,KAAK,WAAW,MAAM,CAAC,KAAK,MAAM,QAAM,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC,GAAG;AAClF,kBAAM,IAAI,WAAW,mDAAmD;AAAA,UAC5E;AACA,gBAAM,MAAM,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC;AACjC,cAAI,SAAS,KAAK,OAAO,IAAI,GAAG;AAChC,cAAI,CAAC,OAAQ,MAAK,OAAO,IAAI,KAAK,SAAS,oBAAI,IAAI,CAAC;AACpD,iBAAO,IAAI,QAAQ,GAAG,IAAI;AAAA,QAC9B;AAAA,MACJ;AACA,UAAI,aAAa,YAAY,IAAI;AACjC,iBAAW,WAAW,MAAM,UAAU;AAClC,YAAI,CAAC,UAAU;AACX,cAAI,CAAC,iBAAiB,IAAI,QAAQ,CAAC,EAAG;AACtC,gBAAM,WAAW,IAAI,QAAQ,MAAM,IAAI,IAAI,QAAQ,IAAI,IAAI,MAAM,IAAI,EAAE;AACvE,eAAK,kBAAkB,QAAQ;AAC/B,gBAAM,SAAS,KAAK,mBAAmB,QAAQ;AAC/C,cAAI;AACA,kBAAM,OAAO,aAAa,QAAQ,IAAI;AAAA,UAC1C,UAAE;AACE,iBAAK,mBAAmB,MAAM;AAAA,UAClC;AACA,cAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,kBAAM,iBAAiB;AACvB,yBAAa,YAAY,IAAI;AAAA,UACjC;AACA;AAAA,QACJ;AACA,cAAM,SAA4B,CAAC;AACnC,iBAAS,QAAQ,GAAG,QAAQ,MAAM,SAAS;AACvC,gBAAM,QAAQ,QAAQ,KAAK,IAAI,KAAK;AACpC,cAAI,MAAO,QAAO,KAAK;AAAA,YACnB,GAAG;AAAA,YACH,UAAU;AAAA,cAAC,MAAM,IAAI,KAAK,QAAQ;AAAA,cAC9B,QAAQ,IAAI,KAAK,KAAK,MAAM,QAAQ,GAAG;AAAA,cACvC,MAAM,IAAI,KAAK,KAAK,MAAM,QAAQ,EAAE,IAAI;AAAA,YAAE;AAAA,UAClD,CAAC;AAAA,QACL;AACA,cAAM,KAAK,YAAY,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,GAAG,OAAO,GAAG,MAAM,UAAU,OAAO;AAAA,MAClF;AACA,YAAM,gBAAgB;AAAA,IAC1B,UAAE;AACE,WAAK,kBAAkB,MAAM,GAAG,MAAM,GAAG,QAAW,KAAK;AACzD,UAAI,aAAc,OAAM,KAAK,cAAc,CAAC,GAAG,QAAQ,OAAO,CAAC,GAAG,IAAI;AAAA,WACjE;AACD,cAAM,WAAW,MAAM,KAAK,cAAc;AAC1C,YAAI,SAAS,KAAM,KAAI,KAAK,kCAAkC,SAAS,OAAO,EAAE,KAAK,EAAE,KAAK;AAC5F,cAAM,KAAK,cAAc,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC;AAAA,MAClD;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,kBAAkB,GAAW,GAA0B;AAChE,WAAO,KAAK,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,mBAAmB,WAA+D;AAC3F,UAAM,UAAU,oBAAI,IAAsC;AAC1D,eAAW,YAAY,WAAW;AAC9B,YAAM,EAAE,GAAG,EAAE,IAAI,YAAY,CAAC;AAC9B,UAAI,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,GAAG;AAC9C,cAAM,IAAI,WAAW,2CAA2C;AAAA,MACpE;AACA,cAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;AAAA,IACrC;AACA,QAAI,CAAC,QAAQ,KAAM;AACnB,UAAM,KAAK;AACX,QAAI,aAAa,YAAY,IAAI;AACjC,QAAI;AACA,iBAAW,EAAE,GAAG,EAAE,KAAK,QAAQ,OAAO,GAAG;AACrC,aAAK,UAAU,YAAY,GAAG,CAAC;AAC/B,cAAM,KAAK,iBAAiB,GAAG,CAAC;AAChC,YAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,gBAAM,iBAAiB;AACvB,uBAAa,YAAY,IAAI;AAAA,QACjC;AAAA,MACJ;AAAA,IACJ,UAAE;AACE,YAAM,WAAW,MAAM,KAAK,cAAc,IAAI;AAC9C,UAAI,SAAS,KAAM,KAAI,KAAK,kCAAkC,SAAS,OAAO,EAAE,KAAK,EAAE,KAAK;AAC5F,YAAM,KAAK,cAAc,CAAC,CAAC;AAAA,IAC/B;AAAA,EACJ;AAAA,EAEA,MAAc,iBAAiB,GAAW,GAA0B;AAChE,SAAK,OAAO,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE;AAC9B,SAAK,kBAAkB,GAAG,GAAG,QAAW,KAAK;AAC7C,QAAI,KAAK,eAAe;AACpB,iBAAW,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC,EAAG,MAAK,mBAAmB,EAAE,GAAG,GAAG,EAAE,CAAC;AAAA,IAClG;AACA,SAAK,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE;AAC7B,SAAK,cAAc,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE;AACrC,SAAK,kBAAkB,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE;AACzC,UAAM,WAAW,CAAC,GAAG,KAAK,QAAQ,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,MAAM,QAAQ,MAAM,KAAK,QAAQ,MAAM,CAAC;AACvG,eAAW,CAAC,KAAK,OAAO,KAAK,UAAU;AACnC,WAAK,QAAQ,OAAO,GAAG;AACvB,WAAK,eAAe,OAAO,OAAO;AAClC,WAAK,cAAc,OAAO,OAAO;AACjC,YAAM,QAAQ,MAAM,KAAK;AACzB,WAAK,mBAAmB,OAAO;AAAA,IACnC;AAAA,EACJ;AAAA,EAEQ,mBAAmB,OAAkD;AACzE,UAAM,UAAU,KAAK,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE;AACnE,QAAI,WAAW,YAAY,MAAO,MAAK,eAAe,IAAI,SAAS,KAAK;AACxE,aAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC7B,eAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC7B,iBAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC7B,cAAI,OAAO,KAAK,OAAO,KAAK,OAAO,EAAG;AACtC,gBAAM,WAAW,KAAK,QAAQ,IAAI,GAAG,MAAM,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,EAAE;AACnF,cAAI,CAAC,SAAU;AACf,cAAI,UAAU,KAAK,eAAe,IAAI,QAAQ;AAC9C,cAAI,YAAY,MAAO;AACvB,cAAI,CAAC,QAAS,MAAK,eAAe,IAAI,UAAU,UAAU,oBAAI,IAAI,CAAC;AACnE,mBAAS,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK;AACvD,qBAAS,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK;AACvD,uBAAS,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK;AACvD,wBAAQ,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AAAA,cACpC;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAa,QAAuB;AAChC,SAAK,UAAU,MAAM;AACrB,UAAM,KAAK;AACX,UAAM,SAAS,CAAC,GAAG,KAAK,QAAQ,OAAO,CAAC;AACxC,SAAK,QAAQ,MAAM;AACnB,SAAK,OAAO,MAAM;AAClB,SAAK,YAAY,MAAM;AACvB,SAAK,cAAc,MAAM;AACzB,SAAK,MAAM,MAAM;AACjB,SAAK,cAAc,MAAM;AACzB,SAAK,kBAAkB,MAAM;AAC7B,eAAW,SAAS,QAAQ;AACxB,YAAM,MAAM,QAAQ;AAAA,IACxB;AACA,SAAK,eAAe,MAAM;AAAA,EAC9B;AAAA,EAEQ,cAAc,WAAsB,QAAQ,OAAsB;AACtE,UAAM,WAAW,IAAI,QAAQ;AAC7B,eAAW,OAAO,WAAW;AACzB,YAAM,KAAK,KAAK,MAAM,IAAI,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI,IAAI,EAAE,GAAG,KAAK,KAAK,MAAM,IAAI,IAAI,EAAE;AAC1F,YAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;AAClD,YAAM,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK;AAEpE,eAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC1B,iBAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC1B,mBAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC1B,kBAAM,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,KAAK;AAC1C,kBAAM,UAAU,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,KAAK,KAAK,QAC3E,KAAK,QAAQ,IAAI,GAAG,KAAK,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,KAAK,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,KAAK,KAAK,MAAM,KAAK,EAAE,CAAC,EAAE;AAC5G,gBAAI,CAAC,QAAS;AACd,kBAAM,SAAS,KAAK,MAAM,OAAO,KAAK,MAAM,MAAM,KAAK;AACvD,gBAAI,UAAU,KAAK,eAAe,IAAI,OAAO;AAC7C,gBAAI,YAAY,SAAS,SAAS,IAAI,KAAK,EAAG;AAC9C,gBAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KACvC,CAAC,KAAK,qBAAqB,CAAC,QAAQ,aAAa,KAAK,EAAG;AAChE,gBAAI,CAAC,QAAS,MAAK,eAAe,IAAI,SAAS,UAAU,oBAAI,IAAI,CAAC;AAClE,oBAAQ,IAAI,KAAK;AAAA,UACrB;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AACA,QAAI,MAAO,QAAO,QAAQ,QAAQ;AAElC,WAAO,KAAK,YAAL,KAAK,UAAY,QAAQ,QAAQ,EAAE,KAAK,YAAY;AACvD,UAAI,aAAa,YAAY,IAAI;AACjC,UAAI;AACA,cAAM,UAAU,MAAM,iBAAiB;AACvC,eAAO,KAAK,eAAe,MAAM;AAC7B,gBAAM,QAAQ,IAAI,IAAI,KAAK,cAAc;AACzC,eAAK,eAAe,MAAM;AAC1B,cAAI;AACA,uBAAW,CAAC,OAAO,OAAO,KAAK,OAAO;AAClC,oBAAM,YAAY,kBAAkB,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,MAC7C,KAAK,QAAQ,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;AACpE,oBAAM,aAAa,CAAC,GAAW,GAAW,MAAsD;AAC5F,sBAAM,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI;AACvE,sBAAM,UAAU,UAAU,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC;AAClG,uBAAO,CAAC,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,MAAM,KAAK,GAAG;AAAA,cACjE;AACA,oBAAM,QAAQ,MAAM,gBAAgB,YAAY,QAAQ,SAAY,SAAS,CAAC,GAAG,GAAG,MAAM;AACtF,sBAAM,CAAC,SAAS,CAAC,IAAI,WAAW,GAAG,GAAG,CAAC;AACvC,uBAAO,SAAS,iBAAiB,CAAC,KAAK;AAAA,cAC3C,GAAG,SAAS,CAAC,GAAG,GAAG,MAAM;AACrB,sBAAM,CAAC,SAAS,CAAC,IAAI,WAAW,GAAG,GAAG,CAAC;AACvC,uBAAO,SAAS,kBAAkB,CAAC;AAAA,cACvC,CAAC;AACD,oBAAM,eAAe,YAAY,QAAS,aAAa;AACnD,yBAAS,QAAQ,GAAG,QAAQ,MAAM,QAAS,OAAM;AAAA,cACrD,EAAG,IAAI;AACP,yBAAW,SAAS,cAAc;AAC9B,oBAAI,CAAC,MAAM,eAAe,KAAK,KAAK,CAAC,MAAM,oBAAoB,KAAK,EAAG;AACvE,sBAAM,KAAK,QAAQ,IAAI,KAAK,KAAK,MAAM,QAAQ,GAAG,GAAG,KAAK,KAAK,MAAM,QAAQ,EAAE,IAAI;AACnF,sBAAM,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK;AAC1E,sBAAM,QAAQ,MAAM,WAAW,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC;AACvD,oBAAI,MAAM,QAAQ,WAAW;AACzB,wBAAM,MAAM,OAAO,YAAY,CAAC,GAAG,GAAG,MAAM;AACxC,0BAAM,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,KAAK;AAC1C,0BAAM,UAAU,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,KAAK,KAAK,QAC3E,KAAK,QAAQ,IAAI,GAAG,MAAM,IAAI,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,IAAI,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,IAAI,KAAK,MAAM,KAAK,EAAE,CAAC,EAAE;AAC3H,0BAAM,iBAAiB,KAAK,MAAM,OAAO,KAAK,MAAM,MAAM,KAAK;AAC/D,0BAAM,OAAO,SAAS,eAAe,aAAa,KAAK;AACvD,2BAAO;AAAA,sBAAE,OAAO,YAAY,IAAI;AAAA,sBAAG,OAAO,OAAO;AAAA,sBAC7C,OAAO,SAAS,iBAAiB,aAAa,KAAK;AAAA,oBAAM;AAAA,kBACjE,CAAC;AAAA,gBACL;AAAA,cACJ;AACA,yBAAW,CAAC,OAAO,IAAI,KAAK,MAAO,OAAM,MAAM,iBAAiB,OAAO,IAAI;AAC3E,oBAAM,MAAM,aAAa,YAAY,QAAQ,SAAY,OAAO;AAChE,oBAAM,wBAAwB,KAAK,iBAAiB;AACpD,kBAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,sBAAM,iBAAiB;AACvB,6BAAa,YAAY,IAAI;AAAA,cACjC;AAAA,YACJ;AACA,kBAAM,UAA2B,CAAC;AAClC,uBAAW,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG;AACnC,oBAAM,SAAS,YAAY;AACvB,sBAAM,MAAM,mBAAmB;AAC/B,sBAAM,OAAO,KAAK;AAAA,cACtB,GAAG;AAEH,mBAAK,MAAM,MAAM,MAAM,MAAS;AAChC,sBAAQ,KAAK,KAAK;AAClB,kBAAI,YAAY,IAAI,IAAI,aAAa,mBAAmB;AACpD,sBAAM,iBAAiB;AACvB,6BAAa,YAAY,IAAI;AAAA,cACjC;AAAA,YACJ;AACA,kBAAM,SAAS,MAAM,QAAQ,WAAW,OAAO;AAC/C,kBAAM,UAAU,OAAO,KAAK,YAAU,OAAO,WAAW,UAAU;AAClE,gBAAI,SAAS,WAAW,WAAY,OAAM,QAAQ;AAAA,UACtD,SAAS,OAAO;AACZ,uBAAW,CAAC,OAAO,OAAO,KAAK,OAAO;AAClC,oBAAM,UAAU,KAAK,eAAe,IAAI,KAAK;AAC7C,mBAAK,eAAe,IAAI,OAAO,YAAY,SAAS,YAAY,QAAQ,QAClE,oBAAI,IAAI,CAAC,GAAG,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAAA,YACjD;AACA,kBAAM;AAAA,UACV;AAAA,QACJ;AAAA,MACJ,UAAE;AACE,aAAK,UAAU;AAAA,MACnB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEQ,mBAAmB,KAAqC;AAC5D,UAAM,MAAM,KAAK,mBAAmB,GAAG;AACvC,QAAI,QAAQ,KAAK,QAAQ,IAAI,GAAG;AAChC,QAAI,OAAO,UAAU,aAAa;AAC9B,YAAM,IAAI,KAAK,MAAM,IAAI,IAAI,EAAE,GAAG,IAAI,KAAK,MAAM,IAAI,IAAI,EAAE,GAAG,IAAI,KAAK,MAAM,IAAI,IAAI,EAAE;AACvF,cAAQ,IAAI;AAAA,QAAsB,KAAK;AAAA,QAAO;AAAA,QAAG;AAAA,QAAG;AAAA,QAChD,CAAC,WAAW,UAAU,KAAK,cAAc,WAAW,KAAK;AAAA,QAAG,KAAK;AAAA,QAAe,CAACC,IAAGC,IAAGC,OAAM;AACzF,gBAAM,KAAK,KAAK,MAAMF,KAAI,EAAE,GAAG,KAAK,KAAK,MAAMC,KAAI,EAAE,GAAG,KAAK,KAAK,MAAMC,KAAI,EAAE;AAC9E,gBAAM,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;AACpD,gBAAM,SAASD,KAAI,KAAK,MAAM,OAAOC,KAAI,KAAK,MAAM,KAAKF,KAAI,KAAK;AAClE,kBAAQ,SAAS,eAAe,KAAK,KAAK,MAAM,SAAS,iBAAiB,KAAK,IAAI,KAAK;AAAA,QAC5F;AAAA,QAAG,CAACA,IAAGC,IAAGC,OAAM,KAAK,WAAWF,IAAGC,IAAGC,EAAC;AAAA,QAAG,OAAM,WAAU;AACtD,cAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,MAAO;AACrC,gBAAM,YAAY,GAAG,CAAC,IAAI,CAAC;AAC3B,cAAI,SAAS,KAAK,OAAO,IAAI,SAAS;AACtC,cAAI,QAAQ;AACR,gBAAI,CAAC,OAAQ,MAAK,OAAO,IAAI,WAAW,SAAS,oBAAI,IAAI,CAAC;AAC1D,mBAAO,IAAI,GAAG,MAAM;AAAA,UACxB,OAAO;AACH,oBAAQ,OAAO,CAAC;AAChB,gBAAI,CAAC,QAAQ,KAAM,MAAK,OAAO,OAAO,SAAS;AAAA,UACnD;AACA,cAAI,KAAK,YAAY;AACjB,kBAAM,SAAS,KAAK,kBAAkB,GAAG,GAAG,CAAC;AAC7C,kBAAM,WAAW,MAAM,KAAK,cAAc;AAC1C,uBAAWC,UAAS,OAAQ,KAAI,SAAS,IAAIA,MAAK,EAAG,OAAM,SAAS,IAAIA,MAAK;AAAA,UACjF,OAAO;AACH,kBAAM,MAAO,cAAc;AAE3B,kBAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,cAAc;AAAA,UAChE;AAAA,QACJ;AAAA,QAAG,KAAK,gBAAgB,CAACH,IAAGC,IAAGC,OAAM,KAAK,aAAaF,IAAGC,IAAGC,EAAC,IAAI;AAAA,QAAW,YAAY;AACrF,cAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,MAAO;AACrC,gBAAM,YAAY,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS;AAChE,cAAI,CAAC,QAAQ,OAAO,CAAC,EAAG;AACxB,cAAI,CAAC,OAAO,KAAM,MAAK,MAAM,OAAO,SAAS;AAC7C,eAAK,kBAAkB,OAAO,SAAS;AACvC,qBAAW,CAACD,IAAG,KAAK,KAAK,QAAQ;AAC7B,gBAAI,MAAM,IAAK,MAAK,kBAAkB,IAAI,WAAW,KAAK,IAAIA,IAAG,KAAK,kBAAkB,IAAI,SAAS,KAAK,SAAS,CAAC;AAAA,UACxH;AACA,cAAI,KAAK,eAAe;AACpB,iBAAK,mBAAmB,KAAM;AAC9B,kBAAM,KAAK,cAAc,CAAC,CAAC;AAAA,UAC/B;AAAA,QACJ;AAAA,QAAG,KAAK;AAAA,QAAc,MAAM,KAAK;AAAA,MAAU;AAC/C,WAAK,QAAQ,IAAI,KAAK,KAAK;AAAA,IAC/B;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGO,WAAW,KAA4C;AAC1D,WAAO,KAAK,QAAQ,IAAI,KAAK,mBAAmB,GAAG,CAAC;AAAA,EACxD;AAAA;AAAA,EAIA,OAAO,qBAAqB,KAAuB;AAC/C,WAAO,IAAI;AAAA,MACP,IAAI,IAAI;AAAA,MACR,IAAI,IAAI;AAAA,MACR,IAAI,IAAI;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA,EAGA,OAAO,qBAAqB,KAAuB;AAC/C,WAAO,IAAI;AAAA,MACP,IAAI,IAAI;AAAA,MACR,IAAI,IAAI;AAAA,MACR,IAAI,IAAI;AAAA,IACZ;AAAA,EACJ;AAAA,EAEA,mBAAmB,KAAsB;AACrC,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI,EAAE;AACpC,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI,EAAE;AACpC,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI,EAAE;AACpC,WAAO,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM;AAAA,EACxC;AAAA,EAEA,kBAAkB,KAAoB;AAClC,QAAI,CAAC,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,EAAE,MAAM,OAAO,SAAS,GAAG;AAChD,YAAM,IAAI,WAAW,oCAAoC;AAAA,IAC7D;AAAA,EACJ;AAEJ;","names":["positions","groups","x","y","z","chunk"]}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// src/world/SectionMesh.ts
|
|
2
|
-
import { BufferGeometry, Color, DoubleSide, Float32BufferAttribute, FrontSide, Group, Mesh, Uint32BufferAttribute } from "three";
|
|
2
|
+
import { BufferGeometry, Color, DoubleSide, DynamicDrawUsage, Float32BufferAttribute, FrontSide, Group, Matrix4, Mesh, Uint32BufferAttribute, Vector3 } from "three";
|
|
3
3
|
import { createCanvas } from "../canvas/CanvasCompat.mjs";
|
|
4
4
|
import { Materials } from "../Materials.mjs";
|
|
5
5
|
import { buildSectionGeometry } from "./SectionGeometry.mjs";
|
|
6
6
|
import { SectionWorker } from "./SectionWorker.mjs";
|
|
7
|
+
var BLOCK_SIZE = 16;
|
|
8
|
+
var QUAD_VERTICES = 4;
|
|
9
|
+
var QUAD_INDICES = 6;
|
|
7
10
|
var templateCache = /* @__PURE__ */ new WeakMap();
|
|
8
11
|
var WATER_TINT = new Color(4159204).toArray();
|
|
9
12
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
@@ -40,8 +43,8 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
40
43
|
if (!data) {
|
|
41
44
|
const indices = template.geometry.getIndex();
|
|
42
45
|
const position = template.geometry.getAttribute("position");
|
|
43
|
-
const quads = indices.count /
|
|
44
|
-
if (indices.count %
|
|
46
|
+
const quads = indices.count / QUAD_INDICES;
|
|
47
|
+
if (indices.count % QUAD_INDICES !== 0 || position.count !== quads * QUAD_VERTICES) {
|
|
45
48
|
throw new RangeError("Section template geometry must hold four vertices and six indices per quad");
|
|
46
49
|
}
|
|
47
50
|
data = {
|
|
@@ -51,8 +54,8 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
51
54
|
uvs: new Float32Array(quads * 8),
|
|
52
55
|
uvBounds: new Float32Array(quads * 16),
|
|
53
56
|
colors: new Float32Array(quads * 12),
|
|
54
|
-
shade: new Float32Array(quads *
|
|
55
|
-
indices: new Uint16Array(quads *
|
|
57
|
+
shade: new Float32Array(quads * QUAD_VERTICES),
|
|
58
|
+
indices: new Uint16Array(quads * QUAD_INDICES),
|
|
56
59
|
cullFaces: new Uint8Array(template.cullFaces),
|
|
57
60
|
biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : void 0,
|
|
58
61
|
atlas: 0,
|
|
@@ -64,7 +67,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
64
67
|
const bounds = template.geometry.getAttribute("uvBounds");
|
|
65
68
|
const color = template.geometry.getAttribute("color");
|
|
66
69
|
const shade = template.geometry.getAttribute("shade");
|
|
67
|
-
for (let vertex = 0; vertex < quads *
|
|
70
|
+
for (let vertex = 0; vertex < quads * QUAD_VERTICES; vertex++) {
|
|
68
71
|
data.positions.set([position.getX(vertex), position.getY(vertex), position.getZ(vertex)], vertex * 3);
|
|
69
72
|
data.normals.set([normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex)], vertex * 3);
|
|
70
73
|
data.uvs.set([uv.getX(vertex), uv.getY(vertex)], vertex * 2);
|
|
@@ -77,7 +80,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
77
80
|
data.colors.set([color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1], vertex * 3);
|
|
78
81
|
data.shade[vertex] = shade?.getX(vertex) ?? 1;
|
|
79
82
|
}
|
|
80
|
-
for (let i2 = 0; i2 < data.indices.length; i2++) data.indices[i2] = indices.getX(i2) -
|
|
83
|
+
for (let i2 = 0; i2 < data.indices.length; i2++) data.indices[i2] = indices.getX(i2) - QUAD_VERTICES * Math.floor(i2 / QUAD_INDICES);
|
|
81
84
|
templateCache.set(template, data);
|
|
82
85
|
}
|
|
83
86
|
id = input.templateData.length;
|
|
@@ -110,6 +113,54 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
110
113
|
}
|
|
111
114
|
return { input, atlases };
|
|
112
115
|
}
|
|
116
|
+
function sortTransparentQuads(mesh) {
|
|
117
|
+
const index = mesh.geometry.getIndex();
|
|
118
|
+
if (index.count <= QUAD_INDICES) return;
|
|
119
|
+
index.setUsage(DynamicDrawUsage);
|
|
120
|
+
const count = index.count / QUAD_INDICES;
|
|
121
|
+
let source, centers, depths, order;
|
|
122
|
+
const view = new Matrix4(), localCamera = new Vector3(), key = new Vector3(), previous = new Vector3();
|
|
123
|
+
let previousOrthographic;
|
|
124
|
+
mesh.onBeforeRender = (_renderer, _scene, camera) => {
|
|
125
|
+
localCamera.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(view.copy(mesh.matrixWorld).invert());
|
|
126
|
+
const orthographic = !!camera.isOrthographicCamera;
|
|
127
|
+
if (orthographic) {
|
|
128
|
+
view.multiplyMatrices(camera.matrixWorldInverse, mesh.matrixWorld);
|
|
129
|
+
key.set(view.elements[2], view.elements[6], view.elements[10]);
|
|
130
|
+
} else {
|
|
131
|
+
key.copy(localCamera).divideScalar(BLOCK_SIZE).floor();
|
|
132
|
+
}
|
|
133
|
+
if (orthographic === previousOrthographic && key.equals(previous)) return;
|
|
134
|
+
previous.copy(key);
|
|
135
|
+
previousOrthographic = orthographic;
|
|
136
|
+
if (!centers) {
|
|
137
|
+
source = new Uint32Array(index.array);
|
|
138
|
+
centers = new Float32Array(count * 3);
|
|
139
|
+
depths = new Float32Array(count);
|
|
140
|
+
order = Uint32Array.from({ length: count }, (_, quad) => quad);
|
|
141
|
+
const positions = mesh.geometry.getAttribute("position");
|
|
142
|
+
for (let quad = 0; quad < count; quad++) {
|
|
143
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
144
|
+
let center = 0;
|
|
145
|
+
for (let corner = 0; corner < QUAD_VERTICES; corner++) center += positions.getComponent(quad * QUAD_VERTICES + corner, axis);
|
|
146
|
+
centers[quad * 3 + axis] = center / QUAD_VERTICES;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (let quad = 0; quad < count; quad++) {
|
|
151
|
+
const x = centers[quad * 3], y = centers[quad * 3 + 1], z = centers[quad * 3 + 2];
|
|
152
|
+
depths[quad] = orthographic ? key.x * x + key.y * y + key.z * z : -((x - localCamera.x) ** 2 + (y - localCamera.y) ** 2 + (z - localCamera.z) ** 2);
|
|
153
|
+
}
|
|
154
|
+
order.sort((a, b) => depths[a] - depths[b] || a - b);
|
|
155
|
+
if (!order.some((quad, offset) => index.array[offset * QUAD_INDICES] !== source[quad * QUAD_INDICES])) return;
|
|
156
|
+
for (let offset = 0; offset < count; offset++) {
|
|
157
|
+
for (let indexOffset = 0; indexOffset < QUAD_INDICES; indexOffset++) {
|
|
158
|
+
index.array[offset * QUAD_INDICES + indexOffset] = source[order[offset] * QUAD_INDICES + indexOffset];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
index.needsUpdate = true;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
113
164
|
var SectionMesh = class _SectionMesh extends Group {
|
|
114
165
|
constructor() {
|
|
115
166
|
super(...arguments);
|
|
@@ -119,7 +170,11 @@ var SectionMesh = class _SectionMesh extends Group {
|
|
|
119
170
|
/** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
|
|
120
171
|
getBlockIndex(hit) {
|
|
121
172
|
if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
|
|
122
|
-
|
|
173
|
+
const mesh = hit.object;
|
|
174
|
+
const owners = this.blockIndices.get(mesh);
|
|
175
|
+
if (!owners) return void 0;
|
|
176
|
+
const vertex = mesh.geometry.getIndex().getX(hit.faceIndex * 3);
|
|
177
|
+
return owners[Math.floor(vertex / QUAD_VERTICES)];
|
|
123
178
|
}
|
|
124
179
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
125
180
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
@@ -155,13 +210,14 @@ var SectionMesh = class _SectionMesh extends Group {
|
|
|
155
210
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
156
211
|
material.side = FrontSide;
|
|
157
212
|
if (page.layer === 2) {
|
|
213
|
+
material.depthWrite = !material.transparent;
|
|
158
214
|
material.side = DoubleSide;
|
|
159
215
|
material.forceSinglePass = true;
|
|
160
|
-
material.depthWrite = !material.transparent;
|
|
161
216
|
}
|
|
162
217
|
material.vertexColors = true;
|
|
163
218
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
164
219
|
const mesh = new Mesh(geometry, material);
|
|
220
|
+
if (transparent) sortTransparentQuads(mesh);
|
|
165
221
|
section.add(mesh);
|
|
166
222
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
167
223
|
const unsubscribe = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/world/SectionMesh.ts"],"sourcesContent":["import { BufferGeometry, Color, DoubleSide, Float32BufferAttribute, FrontSide, Group, Material, Mesh, MeshBasicMaterial, ShaderMaterial, Texture, Uint32BufferAttribute } from \"three\";\nimport { createCanvas } from \"../canvas/CanvasCompat\";\nimport { Materials } from \"../Materials\";\nimport type { MineRenderScene } from \"../renderer/MineRenderScene\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { buildSectionGeometry, SectionGeometryInput, SectionGeometryPage, SectionTemplateData } from \"./SectionGeometry\";\nimport { SectionWorker } from \"./SectionWorker\";\nimport type { Intersection } from \"three\";\n\n/** Shared quad geometry and atlas data prepared for section merging. */\nexport interface SectionMeshTemplate {\n geometry: BufferGeometry;\n atlas: TextureAtlas;\n cullFaces: Uint8Array;\n /** Quads that accept a placement's biome tint, stored as zero or one. */\n biomeTint?: Uint8Array;\n occludes: boolean;\n /** Whether the model permits corner shading from neighboring full cubes. */\n ambientOcclusion?: boolean;\n layer: 0 | 1;\n}\n\n/** One block placement in a section, with its storage index and hidden-face mask. */\nexport interface SectionMeshEntry {\n index: number;\n template: SectionMeshTemplate;\n cullMask: number;\n /** Linear RGB replacing automatic biome colors on eligible quads. */\n biomeTint?: readonly [number, number, number];\n}\n\n/** Fluid cells for one section and the shared atlases of the kinds present. */\nexport interface SectionFluids {\n cells: Uint8Array;\n /** Linear RGB per section cell, indexed by (x + 16z + 256y) * 3. */\n waterTints?: Float32Array;\n water?: TextureAtlas;\n lava?: TextureAtlas;\n}\n\nconst templateCache = new WeakMap<SectionMeshTemplate, SectionTemplateData>();\nconst WATER_TINT = new Color(0x3f76e4).toArray() as [number, number, number];\n\nfunction toInput(entries: readonly SectionMeshEntry[], maxAtlasSize: number, fluids?: SectionFluids,\n lighting?: Pick<SectionGeometryInput, \"light\" | \"ambientLight\" | \"ambientOcclusion\">): { input: SectionGeometryInput; atlases: TextureAtlas[] } {\n if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError(\"Section atlas size must be a positive integer\");\n const atlases: TextureAtlas[] = [];\n const atlasIds = new Map<TextureAtlas, number>();\n const templateIds = new Map<SectionMeshTemplate, number>();\n const input: SectionGeometryInput = {\n count: entries.length, indices: new Uint16Array(entries.length), templates: new Uint16Array(entries.length),\n cullMasks: new Uint8Array(entries.length), templateData: [], atlases: [], maxAtlasSize, ...lighting\n };\n for (let i = 0; i < entries.length; i++) {\n const { index, template, cullMask, biomeTint } = entries[i];\n if (biomeTint) {\n input.biomeTints ??= new Float32Array(entries.length * 3).fill(NaN);\n input.biomeTints.set(biomeTint, i * 3);\n }\n let id = templateIds.get(template);\n if (id === undefined) {\n let atlas = atlasIds.get(template.atlas);\n if (atlas === undefined) {\n atlas = atlases.length;\n atlasIds.set(template.atlas, atlas);\n atlases.push(template.atlas);\n input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });\n }\n let data = templateCache.get(template);\n if (!data) {\n const indices = template.geometry.getIndex()!;\n const position = template.geometry.getAttribute(\"position\");\n const quads = indices.count / 6;\n if (indices.count % 6 !== 0 || position.count !== quads * 4) {\n throw new RangeError(\"Section template geometry must hold four vertices and six indices per quad\");\n }\n data = {\n quads, positions: new Float32Array(quads * 12), normals: new Float32Array(quads * 12), uvs: new Float32Array(quads * 8),\n uvBounds: new Float32Array(quads * 16), colors: new Float32Array(quads * 12), shade: new Float32Array(quads * 4), indices: new Uint16Array(quads * 6),\n cullFaces: new Uint8Array(template.cullFaces), biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : undefined, atlas: 0, layer: template.layer, ambientOcclusion: template.ambientOcclusion\n };\n const normal = template.geometry.getAttribute(\"normal\");\n const uv = template.geometry.getAttribute(\"uv\");\n const bounds = template.geometry.getAttribute(\"uvBounds\");\n const color = template.geometry.getAttribute(\"color\");\n const shade = template.geometry.getAttribute(\"shade\");\n for (let vertex = 0; vertex < quads * 4; vertex++) {\n data.positions.set([position.getX(vertex), position.getY(vertex), position.getZ(vertex)], vertex * 3);\n data.normals.set([normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex)], vertex * 3);\n data.uvs.set([uv.getX(vertex), uv.getY(vertex)], vertex * 2);\n data.uvBounds.set([bounds?.getX(vertex) ?? 0, bounds?.getY(vertex) ?? 0,\n bounds?.getZ(vertex) ?? 1, bounds?.getW(vertex) ?? 1], vertex * 4);\n data.colors.set([color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1], vertex * 3);\n data.shade![vertex] = shade?.getX(vertex) ?? 1;\n }\n for (let i = 0; i < data.indices.length; i++) data.indices[i] = indices.getX(i) - 4 * Math.floor(i / 6);\n templateCache.set(template, data);\n }\n id = input.templateData.length;\n templateIds.set(template, id);\n // Atlas IDs belong to each build; cached buffers can be shared across concurrent builds.\n input.templateData.push({ ...data, atlas });\n }\n input.indices[i] = index;\n input.templates[i] = id;\n input.cullMasks[i] = cullMask;\n }\n if (fluids) {\n input.fluids = { cells: fluids.cells, waterTints: fluids.waterTints };\n for (const kind of [\"water\", \"lava\"] as const) {\n const atlas = fluids[kind];\n if (!atlas) continue;\n let id = atlasIds.get(atlas);\n if (id === undefined) {\n id = atlases.length;\n atlasIds.set(atlas, id);\n atlases.push(atlas);\n input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });\n }\n input.fluids[kind] = {\n atlas: id, still: [...atlas.positions.still, ...atlas.sizes.still],\n flow: [...atlas.positions.flow, ...atlas.sizes.flow], tint: kind === \"water\" ? WATER_TINT : [1, 1, 1]\n };\n }\n }\n return { input, atlases };\n}\n\n/** Merged terrain geometry and atlas pages for one 16×16×16 section. Owns its generated render resources. */\nexport class SectionMesh extends Group {\n\n private readonly ownedMeshes: { mesh: Mesh<BufferGeometry, Material>; texture?: Texture; unsubscribe: (() => void)[] }[] = [];\n private readonly blockIndices = new Map<Mesh, Uint16Array>();\n\n /** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */\n public getBlockIndex(hit: Intersection): number | undefined {\n if (hit.faceIndex === undefined || hit.faceIndex === null) return undefined;\n return this.blockIndices.get(hit.object as Mesh)?.[Math.floor(hit.faceIndex / 2)];\n }\n\n /** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */\n public static build(entries: readonly SectionMeshEntry[], maxAtlasSize = 2048, fluids?: SectionFluids,\n lighting?: Pick<SectionGeometryInput, \"light\" | \"ambientLight\" | \"ambientOcclusion\">): SectionMesh {\n const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);\n return this.fromPages(buildSectionGeometry(input), atlases);\n }\n\n /** Builds section-local meshes in a browser worker when available, with synchronous fallback. */\n public static async buildAsync(entries: readonly SectionMeshEntry[], maxAtlasSize = 2048, fluids?: SectionFluids,\n lighting?: Pick<SectionGeometryInput, \"light\" | \"ambientLight\" | \"ambientOcclusion\">): Promise<SectionMesh> {\n const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);\n const worker = SectionWorker.shared();\n const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);\n return this.fromPages(pages, atlases);\n }\n\n private static fromPages(pages: SectionGeometryPage[], atlases: TextureAtlas[]): SectionMesh {\n const section = new SectionMesh();\n for (const page of pages) {\n const canvas = createCanvas(page.width, page.height);\n const context = canvas.getContext(\"2d\") as CanvasRenderingContext2D;\n for (const { atlas, x, y } of page.placements) {\n context.drawImage(atlases[atlas].image.canvas as CanvasImageSource, x, y);\n }\n const geometry = new BufferGeometry();\n // Passing buffers keeps Three's typed attributes from copying the builder's arrays.\n geometry.setAttribute(\"position\", new Float32BufferAttribute(page.positions.buffer, 3));\n geometry.setAttribute(\"normal\", new Float32BufferAttribute(page.normals.buffer, 3));\n geometry.setAttribute(\"uv\", new Float32BufferAttribute(page.uvs.buffer, 2));\n geometry.setAttribute(\"uvBounds\", new Float32BufferAttribute(page.uvBounds.buffer, 4));\n geometry.setAttribute(\"color\", new Float32BufferAttribute(page.colors.buffer, 3));\n geometry.setAttribute(\"shade\", new Float32BufferAttribute(page.shade.buffer, 1));\n geometry.setIndex(new Uint32BufferAttribute(page.indices.buffer, 1));\n geometry.computeBoundingBox();\n geometry.computeBoundingSphere();\n const transparent = page.layer === 2 ? atlases[page.placements[0].atlas].hasTranslucency : page.layer === 1;\n const material = Materials.createShadedCanvasMaterial(canvas as HTMLCanvasElement, transparent, false, true);\n material.side = FrontSide;\n if (page.layer === 2) {\n material.side = DoubleSide;\n material.forceSinglePass = true;\n material.depthWrite = !material.transparent;\n }\n material.vertexColors = true;\n const texture = (material as ShaderMaterial).uniforms?.map?.value ?? (material as MeshBasicMaterial).map;\n const mesh = new Mesh(geometry, material);\n section.add(mesh);\n section.blockIndices.set(mesh, page.blockIndices);\n const unsubscribe: (() => void)[] = [];\n for (const { atlas: id, x, y } of page.placements) {\n const atlas = atlases[id];\n if (!atlas.hasAnimation) continue;\n unsubscribe.push(atlas.subscribe(() => {\n context.clearRect(x, y, atlas.image.width, atlas.image.height);\n context.drawImage(atlas.image.canvas as CanvasImageSource, x, y);\n texture.needsUpdate = true;\n section.traverseAncestors(parent => {\n if ((parent as MineRenderScene).isMineRenderScene) (parent as MineRenderScene).dirty = true;\n });\n }));\n }\n section.ownedMeshes.push({ mesh, texture, unsubscribe });\n }\n return section;\n }\n\n public dispose(): void {\n for (const { mesh, texture, unsubscribe } of this.ownedMeshes.splice(0)) {\n for (const stop of unsubscribe) stop();\n mesh.removeFromParent();\n mesh.geometry.dispose();\n mesh.material.dispose();\n texture?.dispose();\n }\n this.blockIndices.clear();\n this.removeFromParent();\n super.dispose();\n }\n\n}\n"],"mappings":"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","names":["i"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/world/SectionMesh.ts"],"sourcesContent":["import { BufferGeometry, Color, DoubleSide, DynamicDrawUsage, Float32BufferAttribute, FrontSide, Group, Material, Matrix4, Mesh, MeshBasicMaterial, ShaderMaterial, Texture, Uint32BufferAttribute, Vector3 } from \"three\";\nimport { createCanvas } from \"../canvas/CanvasCompat\";\nimport { Materials } from \"../Materials\";\nimport type { MineRenderScene } from \"../renderer/MineRenderScene\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { buildSectionGeometry, SectionGeometryInput, SectionGeometryPage, SectionTemplateData } from \"./SectionGeometry\";\nimport { SectionWorker } from \"./SectionWorker\";\nimport type { Camera, Intersection } from \"three\";\n\n/** Shared quad geometry and atlas data prepared for section merging. */\nexport interface SectionMeshTemplate {\n geometry: BufferGeometry;\n atlas: TextureAtlas;\n cullFaces: Uint8Array;\n /** Quads that accept a placement's biome tint, stored as zero or one. */\n biomeTint?: Uint8Array;\n occludes: boolean;\n /** Whether the model permits corner shading from neighboring full cubes. */\n ambientOcclusion?: boolean;\n layer: 0 | 1;\n}\n\n/** One block placement in a section, with its storage index and hidden-face mask. */\nexport interface SectionMeshEntry {\n index: number;\n template: SectionMeshTemplate;\n cullMask: number;\n /** Linear RGB replacing automatic biome colors on eligible quads. */\n biomeTint?: readonly [number, number, number];\n}\n\n/** Fluid cells for one section and the shared atlases of the kinds present. */\nexport interface SectionFluids {\n cells: Uint8Array;\n /** Linear RGB per section cell, indexed by (x + 16z + 256y) * 3. */\n waterTints?: Float32Array;\n water?: TextureAtlas;\n lava?: TextureAtlas;\n}\n\nconst BLOCK_SIZE = 16;\nconst QUAD_VERTICES = 4;\nconst QUAD_INDICES = 6;\n\nconst templateCache = new WeakMap<SectionMeshTemplate, SectionTemplateData>();\nconst WATER_TINT = new Color(0x3f76e4).toArray() as [number, number, number];\n\nfunction toInput(entries: readonly SectionMeshEntry[], maxAtlasSize: number, fluids?: SectionFluids,\n lighting?: Pick<SectionGeometryInput, \"light\" | \"ambientLight\" | \"ambientOcclusion\">): { input: SectionGeometryInput; atlases: TextureAtlas[] } {\n if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError(\"Section atlas size must be a positive integer\");\n const atlases: TextureAtlas[] = [];\n const atlasIds = new Map<TextureAtlas, number>();\n const templateIds = new Map<SectionMeshTemplate, number>();\n const input: SectionGeometryInput = {\n count: entries.length, indices: new Uint16Array(entries.length), templates: new Uint16Array(entries.length),\n cullMasks: new Uint8Array(entries.length), templateData: [], atlases: [], maxAtlasSize, ...lighting\n };\n for (let i = 0; i < entries.length; i++) {\n const { index, template, cullMask, biomeTint } = entries[i];\n if (biomeTint) {\n input.biomeTints ??= new Float32Array(entries.length * 3).fill(NaN);\n input.biomeTints.set(biomeTint, i * 3);\n }\n let id = templateIds.get(template);\n if (id === undefined) {\n let atlas = atlasIds.get(template.atlas);\n if (atlas === undefined) {\n atlas = atlases.length;\n atlasIds.set(template.atlas, atlas);\n atlases.push(template.atlas);\n input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });\n }\n let data = templateCache.get(template);\n if (!data) {\n const indices = template.geometry.getIndex()!;\n const position = template.geometry.getAttribute(\"position\");\n const quads = indices.count / QUAD_INDICES;\n if (indices.count % QUAD_INDICES !== 0 || position.count !== quads * QUAD_VERTICES) {\n throw new RangeError(\"Section template geometry must hold four vertices and six indices per quad\");\n }\n data = {\n quads, positions: new Float32Array(quads * 12), normals: new Float32Array(quads * 12), uvs: new Float32Array(quads * 8),\n uvBounds: new Float32Array(quads * 16), colors: new Float32Array(quads * 12), shade: new Float32Array(quads * QUAD_VERTICES), indices: new Uint16Array(quads * QUAD_INDICES),\n cullFaces: new Uint8Array(template.cullFaces), biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : undefined, atlas: 0, layer: template.layer, ambientOcclusion: template.ambientOcclusion\n };\n const normal = template.geometry.getAttribute(\"normal\");\n const uv = template.geometry.getAttribute(\"uv\");\n const bounds = template.geometry.getAttribute(\"uvBounds\");\n const color = template.geometry.getAttribute(\"color\");\n const shade = template.geometry.getAttribute(\"shade\");\n for (let vertex = 0; vertex < quads * QUAD_VERTICES; vertex++) {\n data.positions.set([position.getX(vertex), position.getY(vertex), position.getZ(vertex)], vertex * 3);\n data.normals.set([normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex)], vertex * 3);\n data.uvs.set([uv.getX(vertex), uv.getY(vertex)], vertex * 2);\n data.uvBounds.set([bounds?.getX(vertex) ?? 0, bounds?.getY(vertex) ?? 0,\n bounds?.getZ(vertex) ?? 1, bounds?.getW(vertex) ?? 1], vertex * 4);\n data.colors.set([color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1], vertex * 3);\n data.shade![vertex] = shade?.getX(vertex) ?? 1;\n }\n for (let i = 0; i < data.indices.length; i++) data.indices[i] = indices.getX(i) - QUAD_VERTICES * Math.floor(i / QUAD_INDICES);\n templateCache.set(template, data);\n }\n id = input.templateData.length;\n templateIds.set(template, id);\n // Atlas IDs belong to each build; cached buffers can be shared across concurrent builds.\n input.templateData.push({ ...data, atlas });\n }\n input.indices[i] = index;\n input.templates[i] = id;\n input.cullMasks[i] = cullMask;\n }\n if (fluids) {\n input.fluids = { cells: fluids.cells, waterTints: fluids.waterTints };\n for (const kind of [\"water\", \"lava\"] as const) {\n const atlas = fluids[kind];\n if (!atlas) continue;\n let id = atlasIds.get(atlas);\n if (id === undefined) {\n id = atlases.length;\n atlasIds.set(atlas, id);\n atlases.push(atlas);\n input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });\n }\n input.fluids[kind] = {\n atlas: id, still: [...atlas.positions.still, ...atlas.sizes.still],\n flow: [...atlas.positions.flow, ...atlas.sizes.flow], tint: kind === \"water\" ? WATER_TINT : [1, 1, 1]\n };\n }\n }\n return { input, atlases };\n}\n\nfunction sortTransparentQuads(mesh: Mesh<BufferGeometry, Material>): void {\n const index = mesh.geometry.getIndex()!;\n if (index.count <= QUAD_INDICES) return;\n index.setUsage(DynamicDrawUsage);\n const count = index.count / QUAD_INDICES;\n let source: Uint32Array, centers: Float32Array, depths: Float32Array, order: Uint32Array;\n const view = new Matrix4(), localCamera = new Vector3(), key = new Vector3(), previous = new Vector3();\n let previousOrthographic: boolean | undefined;\n mesh.onBeforeRender = (_renderer, _scene, camera) => {\n localCamera.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(view.copy(mesh.matrixWorld).invert());\n const orthographic = !!(camera as Camera & { isOrthographicCamera?: boolean }).isOrthographicCamera;\n if (orthographic) {\n // Three updates mesh.modelViewMatrix after this callback.\n view.multiplyMatrices(camera.matrixWorldInverse, mesh.matrixWorld);\n key.set(view.elements[2], view.elements[6], view.elements[10]);\n } else {\n key.copy(localCamera).divideScalar(BLOCK_SIZE).floor();\n }\n if (orthographic === previousOrthographic && key.equals(previous)) return;\n previous.copy(key);\n previousOrthographic = orthographic;\n if (!centers) {\n source = new Uint32Array(index.array);\n centers = new Float32Array(count * 3);\n depths = new Float32Array(count);\n order = Uint32Array.from({ length: count }, (_, quad) => quad);\n const positions = mesh.geometry.getAttribute(\"position\");\n for (let quad = 0; quad < count; quad++) {\n for (let axis = 0; axis < 3; axis++) {\n let center = 0;\n for (let corner = 0; corner < QUAD_VERTICES; corner++) center += positions.getComponent(quad * QUAD_VERTICES + corner, axis);\n centers[quad * 3 + axis] = center / QUAD_VERTICES;\n }\n }\n }\n for (let quad = 0; quad < count; quad++) {\n const x = centers[quad * 3], y = centers[quad * 3 + 1], z = centers[quad * 3 + 2];\n depths[quad] = orthographic ? key.x * x + key.y * y + key.z * z\n : -((x - localCamera.x) ** 2 + (y - localCamera.y) ** 2 + (z - localCamera.z) ** 2);\n }\n order.sort((a, b) => depths[a] - depths[b] || a - b);\n if (!order.some((quad, offset) => index.array[offset * QUAD_INDICES] !== source[quad * QUAD_INDICES])) return;\n for (let offset = 0; offset < count; offset++) {\n for (let indexOffset = 0; indexOffset < QUAD_INDICES; indexOffset++) {\n index.array[offset * QUAD_INDICES + indexOffset] = source[order[offset] * QUAD_INDICES + indexOffset];\n }\n }\n index.needsUpdate = true;\n };\n}\n\n/** Merged terrain geometry and atlas pages for one 16×16×16 section. Owns its generated render resources. */\nexport class SectionMesh extends Group {\n\n private readonly ownedMeshes: { mesh: Mesh<BufferGeometry, Material>; texture?: Texture; unsubscribe: (() => void)[] }[] = [];\n private readonly blockIndices = new Map<Mesh, Uint16Array>();\n\n /** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */\n public getBlockIndex(hit: Intersection): number | undefined {\n if (hit.faceIndex === undefined || hit.faceIndex === null) return undefined;\n const mesh = hit.object as Mesh;\n const owners = this.blockIndices.get(mesh);\n if (!owners) return undefined;\n // Sorted triangles still refer to each quad's original four consecutive vertices.\n const vertex = mesh.geometry.getIndex()!.getX(hit.faceIndex * 3);\n return owners[Math.floor(vertex / QUAD_VERTICES)];\n }\n\n /** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */\n public static build(entries: readonly SectionMeshEntry[], maxAtlasSize = 2048, fluids?: SectionFluids,\n lighting?: Pick<SectionGeometryInput, \"light\" | \"ambientLight\" | \"ambientOcclusion\">): SectionMesh {\n const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);\n return this.fromPages(buildSectionGeometry(input), atlases);\n }\n\n /** Builds section-local meshes in a browser worker when available, with synchronous fallback. */\n public static async buildAsync(entries: readonly SectionMeshEntry[], maxAtlasSize = 2048, fluids?: SectionFluids,\n lighting?: Pick<SectionGeometryInput, \"light\" | \"ambientLight\" | \"ambientOcclusion\">): Promise<SectionMesh> {\n const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);\n const worker = SectionWorker.shared();\n const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);\n return this.fromPages(pages, atlases);\n }\n\n private static fromPages(pages: SectionGeometryPage[], atlases: TextureAtlas[]): SectionMesh {\n const section = new SectionMesh();\n for (const page of pages) {\n const canvas = createCanvas(page.width, page.height);\n const context = canvas.getContext(\"2d\") as CanvasRenderingContext2D;\n for (const { atlas, x, y } of page.placements) {\n context.drawImage(atlases[atlas].image.canvas as CanvasImageSource, x, y);\n }\n const geometry = new BufferGeometry();\n // Passing buffers keeps Three's typed attributes from copying the builder's arrays.\n geometry.setAttribute(\"position\", new Float32BufferAttribute(page.positions.buffer, 3));\n geometry.setAttribute(\"normal\", new Float32BufferAttribute(page.normals.buffer, 3));\n geometry.setAttribute(\"uv\", new Float32BufferAttribute(page.uvs.buffer, 2));\n geometry.setAttribute(\"uvBounds\", new Float32BufferAttribute(page.uvBounds.buffer, 4));\n geometry.setAttribute(\"color\", new Float32BufferAttribute(page.colors.buffer, 3));\n geometry.setAttribute(\"shade\", new Float32BufferAttribute(page.shade.buffer, 1));\n geometry.setIndex(new Uint32BufferAttribute(page.indices.buffer, 1));\n geometry.computeBoundingBox();\n geometry.computeBoundingSphere();\n const transparent = page.layer === 2 ? atlases[page.placements[0].atlas].hasTranslucency : page.layer === 1;\n const material = Materials.createShadedCanvasMaterial(canvas as HTMLCanvasElement, transparent, false, true);\n material.side = FrontSide;\n if (page.layer === 2) {\n material.depthWrite = !material.transparent;\n material.side = DoubleSide;\n material.forceSinglePass = true;\n }\n material.vertexColors = true;\n const texture = (material as ShaderMaterial).uniforms?.map?.value ?? (material as MeshBasicMaterial).map;\n const mesh = new Mesh(geometry, material);\n if (transparent) sortTransparentQuads(mesh);\n section.add(mesh);\n section.blockIndices.set(mesh, page.blockIndices);\n const unsubscribe: (() => void)[] = [];\n for (const { atlas: id, x, y } of page.placements) {\n const atlas = atlases[id];\n if (!atlas.hasAnimation) continue;\n unsubscribe.push(atlas.subscribe(() => {\n context.clearRect(x, y, atlas.image.width, atlas.image.height);\n context.drawImage(atlas.image.canvas as CanvasImageSource, x, y);\n texture.needsUpdate = true;\n section.traverseAncestors(parent => {\n if ((parent as MineRenderScene).isMineRenderScene) (parent as MineRenderScene).dirty = true;\n });\n }));\n }\n section.ownedMeshes.push({ mesh, texture, unsubscribe });\n }\n return section;\n }\n\n public dispose(): void {\n for (const { mesh, texture, unsubscribe } of this.ownedMeshes.splice(0)) {\n for (const stop of unsubscribe) stop();\n mesh.removeFromParent();\n mesh.geometry.dispose();\n mesh.material.dispose();\n texture?.dispose();\n }\n this.blockIndices.clear();\n this.removeFromParent();\n super.dispose();\n }\n\n}\n"],"mappings":"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","names":["i"]}
|
|
@@ -93,6 +93,10 @@ var SectionModels = class {
|
|
|
93
93
|
biomeTint: source ? [...templates.values()].some((template) => template.biomeTint?.some((value) => value === 1)) || void 0 : void 0
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
|
+
/** Starts loading the state's models and atlases so a later `prepareState` with the same properties finds them loaded. */
|
|
97
|
+
async preload(blockState, properties = {}) {
|
|
98
|
+
await this.state(blockState, properties);
|
|
99
|
+
}
|
|
96
100
|
async state(blockState, properties) {
|
|
97
101
|
let states = this.states.get(blockState);
|
|
98
102
|
if (!states) this.states.set(blockState, states = /* @__PURE__ */ new Map());
|
|
@@ -115,22 +119,24 @@ var SectionModels = class {
|
|
|
115
119
|
async prepare(blockState, properties) {
|
|
116
120
|
const state = { ...await BlockStateResolver.defaults(blockState), ...properties };
|
|
117
121
|
const groups = BlockStateResolver.matching(blockState, state);
|
|
118
|
-
if (!groups.length) return void 0;
|
|
122
|
+
if (!groups.length || groups.some((group) => Array.isArray(group) && !group.length)) return void 0;
|
|
123
|
+
const variants = groups.flatMap((group) => Array.isArray(group) ? group : [group]);
|
|
124
|
+
if (variants.some((variant) => !variant.model)) return void 0;
|
|
125
|
+
const settled = await Promise.allSettled(variants.map(async (variant) => {
|
|
126
|
+
const modelKey = AssetKey.parse("models", variant.model);
|
|
127
|
+
modelKey.root = blockState.key?.root;
|
|
128
|
+
const model = await Models.getMerged(modelKey);
|
|
129
|
+
if (!model?.elements?.length) return void 0;
|
|
130
|
+
const atlas = await UVMapper.getAtlas(model);
|
|
131
|
+
const rotation = BlockStateResolver.rotation(variant);
|
|
132
|
+
if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
|
|
133
|
+
return { model, atlas, rotation };
|
|
134
|
+
}));
|
|
119
135
|
const prepared = /* @__PURE__ */ new Map();
|
|
120
|
-
for (const
|
|
121
|
-
|
|
122
|
-
if (!
|
|
123
|
-
|
|
124
|
-
if (!variant.model) return void 0;
|
|
125
|
-
const modelKey = AssetKey.parse("models", variant.model);
|
|
126
|
-
modelKey.root = blockState.key?.root;
|
|
127
|
-
const model = await Models.getMerged(modelKey);
|
|
128
|
-
if (!model?.elements?.length) return void 0;
|
|
129
|
-
const atlas = await UVMapper.getAtlas(model);
|
|
130
|
-
const rotation = BlockStateResolver.rotation(variant);
|
|
131
|
-
if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
|
|
132
|
-
prepared.set(variant, { model, atlas, rotation });
|
|
133
|
-
}
|
|
136
|
+
for (const [i, result] of settled.entries()) {
|
|
137
|
+
if (result.status === "rejected") throw result.reason;
|
|
138
|
+
if (!result.value) return void 0;
|
|
139
|
+
prepared.set(variants[i], result.value);
|
|
134
140
|
}
|
|
135
141
|
return { state, groups, choices: prepared };
|
|
136
142
|
}
|