minerender 2.1.0-alpha.143 → 2.1.0-alpha.144
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/index.browser.d.mts +5 -2
- package/dist/browser/esm/world/Chunk.mjs +62 -33
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +16 -1
- package/dist/browser/esm/world/MineRenderWorld.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/index.d.ts +5 -2
- package/dist/browser/index.js +98 -49
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +98 -49
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +5 -2
- package/dist/node/index.d.ts +5 -2
- package/dist/node/index.js +98 -49
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +98 -49
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.d.mts
CHANGED
|
@@ -4024,6 +4024,8 @@ declare class SectionModels {
|
|
|
4024
4024
|
pick(position?: Readonly<TripleArray>): SectionMeshTemplate[];
|
|
4025
4025
|
biomeTint?: boolean;
|
|
4026
4026
|
} | undefined>;
|
|
4027
|
+
/** Starts loading the state's models and atlases so a later `prepareState` with the same properties finds them loaded. */
|
|
4028
|
+
preload(blockState: BlockState, properties?: BlockStateProperties): Promise<void>;
|
|
4027
4029
|
private state;
|
|
4028
4030
|
/** Returns the shared still/flow atlas used by per-block fluid objects. */
|
|
4029
4031
|
fluidAtlas(kind: FluidKind, root?: string): Promise<TextureAtlas>;
|
|
@@ -4138,6 +4140,7 @@ declare class Chunk<SectionMeshing extends boolean = false> {
|
|
|
4138
4140
|
/** Replaces every cell from parsed section data. The caller refreshes neighbor culling. */
|
|
4139
4141
|
placeSection(data: ChunkData): Promise<void>;
|
|
4140
4142
|
private replaceSection;
|
|
4143
|
+
private createBlockObject;
|
|
4141
4144
|
private positionAt;
|
|
4142
4145
|
/** Refreshes saved lighting after adjacent columns load or unload, including columns with only light data. */
|
|
4143
4146
|
refreshLight(indices?: Iterable<number>): Promise<void>;
|
|
@@ -4325,7 +4328,7 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
4325
4328
|
interface MineRenderWorldOptions<SectionMeshing extends boolean = boolean> {
|
|
4326
4329
|
/** Render supported saved mobs at their position and yaw, including supported appearance fields. Defaults to false. */
|
|
4327
4330
|
renderEntities?: boolean;
|
|
4328
|
-
/** Merge
|
|
4331
|
+
/** Merge block models of any shape and fluid surfaces into per-section meshes; block entities keep individual objects. Merged blocks have no individual object. */
|
|
4329
4332
|
sectionMeshing?: SectionMeshing;
|
|
4330
4333
|
/** Shade blocks and fluids with saved sky/block light. Missing or invalid data keeps preview brightness. Defaults to false. Requires `sectionMeshing`. */
|
|
4331
4334
|
savedLighting?: boolean;
|
|
@@ -4335,7 +4338,7 @@ interface MineRenderWorldOptions<SectionMeshing extends boolean = boolean> {
|
|
|
4335
4338
|
ambientOcclusion?: boolean;
|
|
4336
4339
|
/** Average neighboring biome colors within this horizontal radius, from 0 to 7 blocks. Defaults to 0 (off). Requires `sectionMeshing`. */
|
|
4337
4340
|
biomeBlendRadius?: number;
|
|
4338
|
-
/** Maximum width and height of each section atlas page, in pixels. */
|
|
4341
|
+
/** Maximum width and height of each section atlas page, in pixels. Defaults to 2048. */
|
|
4339
4342
|
maxAtlasSize?: number;
|
|
4340
4343
|
}
|
|
4341
4344
|
|
package/dist/node/index.d.ts
CHANGED
|
@@ -4024,6 +4024,8 @@ declare class SectionModels {
|
|
|
4024
4024
|
pick(position?: Readonly<TripleArray>): SectionMeshTemplate[];
|
|
4025
4025
|
biomeTint?: boolean;
|
|
4026
4026
|
} | undefined>;
|
|
4027
|
+
/** Starts loading the state's models and atlases so a later `prepareState` with the same properties finds them loaded. */
|
|
4028
|
+
preload(blockState: BlockState, properties?: BlockStateProperties): Promise<void>;
|
|
4027
4029
|
private state;
|
|
4028
4030
|
/** Returns the shared still/flow atlas used by per-block fluid objects. */
|
|
4029
4031
|
fluidAtlas(kind: FluidKind, root?: string): Promise<TextureAtlas>;
|
|
@@ -4138,6 +4140,7 @@ declare class Chunk<SectionMeshing extends boolean = false> {
|
|
|
4138
4140
|
/** Replaces every cell from parsed section data. The caller refreshes neighbor culling. */
|
|
4139
4141
|
placeSection(data: ChunkData): Promise<void>;
|
|
4140
4142
|
private replaceSection;
|
|
4143
|
+
private createBlockObject;
|
|
4141
4144
|
private positionAt;
|
|
4142
4145
|
/** Refreshes saved lighting after adjacent columns load or unload, including columns with only light data. */
|
|
4143
4146
|
refreshLight(indices?: Iterable<number>): Promise<void>;
|
|
@@ -4325,7 +4328,7 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
4325
4328
|
interface MineRenderWorldOptions<SectionMeshing extends boolean = boolean> {
|
|
4326
4329
|
/** Render supported saved mobs at their position and yaw, including supported appearance fields. Defaults to false. */
|
|
4327
4330
|
renderEntities?: boolean;
|
|
4328
|
-
/** Merge
|
|
4331
|
+
/** Merge block models of any shape and fluid surfaces into per-section meshes; block entities keep individual objects. Merged blocks have no individual object. */
|
|
4329
4332
|
sectionMeshing?: SectionMeshing;
|
|
4330
4333
|
/** Shade blocks and fluids with saved sky/block light. Missing or invalid data keeps preview brightness. Defaults to false. Requires `sectionMeshing`. */
|
|
4331
4334
|
savedLighting?: boolean;
|
|
@@ -4335,7 +4338,7 @@ interface MineRenderWorldOptions<SectionMeshing extends boolean = boolean> {
|
|
|
4335
4338
|
ambientOcclusion?: boolean;
|
|
4336
4339
|
/** Average neighboring biome colors within this horizontal radius, from 0 to 7 blocks. Defaults to 0 (off). Requires `sectionMeshing`. */
|
|
4337
4340
|
biomeBlendRadius?: number;
|
|
4338
|
-
/** Maximum width and height of each section atlas page, in pixels. */
|
|
4341
|
+
/** Maximum width and height of each section atlas page, in pixels. Defaults to 2048. */
|
|
4339
4342
|
maxAtlasSize?: number;
|
|
4340
4343
|
}
|
|
4341
4344
|
|
package/dist/node/index.js
CHANGED
|
@@ -18090,6 +18090,7 @@ var AnvilWorldSource = class {
|
|
|
18090
18090
|
};
|
|
18091
18091
|
|
|
18092
18092
|
// src/world/Chunk.ts
|
|
18093
|
+
init_BlockObject();
|
|
18093
18094
|
var import_three47 = require("three");
|
|
18094
18095
|
init_BlockStates();
|
|
18095
18096
|
init_AssetKey();
|
|
@@ -18100,6 +18101,7 @@ init_Model();
|
|
|
18100
18101
|
init_util();
|
|
18101
18102
|
init_AssetKey();
|
|
18102
18103
|
init_BlockStates();
|
|
18104
|
+
init_BlockEntities();
|
|
18103
18105
|
init_CubeFace();
|
|
18104
18106
|
|
|
18105
18107
|
// src/world/SectionModels.ts
|
|
@@ -18197,6 +18199,10 @@ var SectionModels = class {
|
|
|
18197
18199
|
biomeTint: source ? [...templates.values()].some((template) => template.biomeTint?.some((value) => value === 1)) || void 0 : void 0
|
|
18198
18200
|
};
|
|
18199
18201
|
}
|
|
18202
|
+
/** Starts loading the state's models and atlases so a later `prepareState` with the same properties finds them loaded. */
|
|
18203
|
+
async preload(blockState3, properties = {}) {
|
|
18204
|
+
await this.state(blockState3, properties);
|
|
18205
|
+
}
|
|
18200
18206
|
async state(blockState3, properties) {
|
|
18201
18207
|
let states = this.states.get(blockState3);
|
|
18202
18208
|
if (!states) this.states.set(blockState3, states = /* @__PURE__ */ new Map());
|
|
@@ -18219,22 +18225,24 @@ var SectionModels = class {
|
|
|
18219
18225
|
async prepare(blockState3, properties) {
|
|
18220
18226
|
const state = { ...await BlockStateResolver.defaults(blockState3), ...properties };
|
|
18221
18227
|
const groups = BlockStateResolver.matching(blockState3, state);
|
|
18222
|
-
if (!groups.length) return void 0;
|
|
18228
|
+
if (!groups.length || groups.some((group) => Array.isArray(group) && !group.length)) return void 0;
|
|
18229
|
+
const variants = groups.flatMap((group) => Array.isArray(group) ? group : [group]);
|
|
18230
|
+
if (variants.some((variant) => !variant.model)) return void 0;
|
|
18231
|
+
const settled = await Promise.allSettled(variants.map(async (variant) => {
|
|
18232
|
+
const modelKey = AssetKey.parse("models", variant.model);
|
|
18233
|
+
modelKey.root = blockState3.key?.root;
|
|
18234
|
+
const model = await Models.getMerged(modelKey);
|
|
18235
|
+
if (!model?.elements?.length) return void 0;
|
|
18236
|
+
const atlas = await UVMapper.getAtlas(model);
|
|
18237
|
+
const rotation = BlockStateResolver.rotation(variant);
|
|
18238
|
+
if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
|
|
18239
|
+
return { model, atlas, rotation };
|
|
18240
|
+
}));
|
|
18223
18241
|
const prepared = /* @__PURE__ */ new Map();
|
|
18224
|
-
for (const
|
|
18225
|
-
|
|
18226
|
-
if (!
|
|
18227
|
-
|
|
18228
|
-
if (!variant.model) return void 0;
|
|
18229
|
-
const modelKey = AssetKey.parse("models", variant.model);
|
|
18230
|
-
modelKey.root = blockState3.key?.root;
|
|
18231
|
-
const model = await Models.getMerged(modelKey);
|
|
18232
|
-
if (!model?.elements?.length) return void 0;
|
|
18233
|
-
const atlas = await UVMapper.getAtlas(model);
|
|
18234
|
-
const rotation = BlockStateResolver.rotation(variant);
|
|
18235
|
-
if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
|
|
18236
|
-
prepared.set(variant, { model, atlas, rotation });
|
|
18237
|
-
}
|
|
18242
|
+
for (const [i, result] of settled.entries()) {
|
|
18243
|
+
if (result.status === "rejected") throw result.reason;
|
|
18244
|
+
if (!result.value) return void 0;
|
|
18245
|
+
prepared.set(variants[i], result.value);
|
|
18238
18246
|
}
|
|
18239
18247
|
return { state, groups, choices: prepared };
|
|
18240
18248
|
}
|
|
@@ -18909,15 +18917,18 @@ var MineRenderWorld = class {
|
|
|
18909
18917
|
const key = AssetKey.parse("blockstates", block.type);
|
|
18910
18918
|
keys.set(key.serialize(), key);
|
|
18911
18919
|
}
|
|
18912
|
-
await BlockStates.getAll(keys.values());
|
|
18920
|
+
const loaded = await BlockStates.getAll(keys.values());
|
|
18921
|
+
const states = new Map([...keys.keys()].map((key, i) => [key, loaded[i]]));
|
|
18913
18922
|
if (!useBatches) {
|
|
18914
18923
|
for (const block of multiblock.blocks) await place(block);
|
|
18915
18924
|
return;
|
|
18916
18925
|
}
|
|
18917
18926
|
if (!executor) {
|
|
18918
18927
|
const groups2 = /* @__PURE__ */ new Map();
|
|
18928
|
+
const distinct = /* @__PURE__ */ new Map();
|
|
18919
18929
|
const position = new import_three45.Vector3();
|
|
18920
18930
|
for (const block of multiblock.blocks) {
|
|
18931
|
+
if (this.sectionModels && !Chunk.isAir(block)) distinct.set(ChunkData.paletteKey(block), block);
|
|
18921
18932
|
const [x, y, z] = block.position;
|
|
18922
18933
|
this.validatePosBounds(position.set(x, y, z));
|
|
18923
18934
|
const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16);
|
|
@@ -18928,6 +18939,16 @@ var MineRenderWorld = class {
|
|
|
18928
18939
|
if (!group) groups2.set(chunk, group = []);
|
|
18929
18940
|
group.push({ index: (y - cy * 16) * 256 + (z - cz * 16) * 16 + x - cx * 16, block });
|
|
18930
18941
|
}
|
|
18942
|
+
if (this.sectionModels) {
|
|
18943
|
+
for (const block of distinct.values()) {
|
|
18944
|
+
const state = states.get(AssetKey.parse("blockstates", block.type).serialize());
|
|
18945
|
+
if (!state) continue;
|
|
18946
|
+
void (async () => {
|
|
18947
|
+
if (state.key && BlockEntities.entry(await BlockEntities.getIndex(state.key.root), state.key.toNamespacedString())) return;
|
|
18948
|
+
await this.sectionModels.preload(state, block.properties);
|
|
18949
|
+
})().catch(() => void 0);
|
|
18950
|
+
}
|
|
18951
|
+
}
|
|
18931
18952
|
await this.placeChunkGroups(groups2, changes);
|
|
18932
18953
|
return;
|
|
18933
18954
|
}
|
|
@@ -20255,8 +20276,10 @@ var Chunk = class _Chunk {
|
|
|
20255
20276
|
if (rejected?.status === "rejected") throw rejected.reason;
|
|
20256
20277
|
}
|
|
20257
20278
|
const positions = [];
|
|
20258
|
-
|
|
20259
|
-
|
|
20279
|
+
const jobs = /* @__PURE__ */ new Map();
|
|
20280
|
+
let failureOrder = Infinity, failure;
|
|
20281
|
+
for (const [order, { index, key, block }] of placements.entries()) {
|
|
20282
|
+
jobs.delete(index);
|
|
20260
20283
|
this.hiddenBlocks.delete(index);
|
|
20261
20284
|
this.data.assign(index, this.data.intern(block), block?.nbt);
|
|
20262
20285
|
const readBlock = this.data.snapshot(index);
|
|
@@ -20272,7 +20295,6 @@ var Chunk = class _Chunk {
|
|
|
20272
20295
|
this.z * 16 + Math.floor(index / 16) % 16
|
|
20273
20296
|
);
|
|
20274
20297
|
positions.push(worldPos);
|
|
20275
|
-
let object4;
|
|
20276
20298
|
try {
|
|
20277
20299
|
if (!readBlock) continue;
|
|
20278
20300
|
const resolved = resolutions.get(key);
|
|
@@ -20294,7 +20316,7 @@ var Chunk = class _Chunk {
|
|
|
20294
20316
|
this.sectionBlocks.set(index, templates.map((template) => ({ index, template, cullMask: 0, biomeTint: context?.tint })));
|
|
20295
20317
|
this.meshDirty = true;
|
|
20296
20318
|
} else {
|
|
20297
|
-
|
|
20319
|
+
jobs.set(index, { order, readBlock, blockState: blockState3, position: MineRenderWorld.worldToScenePosition(worldPos), options: {
|
|
20298
20320
|
mergeMeshes: true,
|
|
20299
20321
|
instanceMeshes: true,
|
|
20300
20322
|
maxInstanceCount: 2e3,
|
|
@@ -20302,13 +20324,12 @@ var Chunk = class _Chunk {
|
|
|
20302
20324
|
variantPosition,
|
|
20303
20325
|
biome: context?.biome,
|
|
20304
20326
|
biomePosition: this.biomePosition(index, blockState3, stored)
|
|
20305
|
-
});
|
|
20306
|
-
|
|
20327
|
+
} });
|
|
20328
|
+
continue;
|
|
20307
20329
|
}
|
|
20308
20330
|
this.renderedBlocks.set(index, { get block() {
|
|
20309
20331
|
return readBlock();
|
|
20310
|
-
}, object:
|
|
20311
|
-
if (object4) this.objectBlocks.add(index);
|
|
20332
|
+
}, object: void 0 });
|
|
20312
20333
|
} catch (error) {
|
|
20313
20334
|
if (preserveDataOnFailure && readBlock) {
|
|
20314
20335
|
this.renderedBlocks.set(index, { get block() {
|
|
@@ -20316,12 +20337,35 @@ var Chunk = class _Chunk {
|
|
|
20316
20337
|
}, object: void 0 });
|
|
20317
20338
|
} else this.data.assign(index, 0);
|
|
20318
20339
|
this.fluidCells[index] = 0;
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
20340
|
+
if (order < failureOrder) {
|
|
20341
|
+
failureOrder = order;
|
|
20342
|
+
failure = error;
|
|
20343
|
+
}
|
|
20322
20344
|
}
|
|
20323
20345
|
}
|
|
20324
|
-
|
|
20346
|
+
const pending = [...jobs];
|
|
20347
|
+
const objects = await Promise.allSettled(pending.map(([, job]) => this.createBlockObject(job.blockState, job.position, job.options)));
|
|
20348
|
+
for (const [i, [index, { order, readBlock }]] of pending.entries()) {
|
|
20349
|
+
const result = objects[i];
|
|
20350
|
+
if (result.status === "fulfilled") {
|
|
20351
|
+
this.renderedBlocks.set(index, { get block() {
|
|
20352
|
+
return readBlock();
|
|
20353
|
+
}, object: result.value });
|
|
20354
|
+
this.objectBlocks.add(index);
|
|
20355
|
+
} else {
|
|
20356
|
+
if (preserveDataOnFailure) {
|
|
20357
|
+
this.renderedBlocks.set(index, { get block() {
|
|
20358
|
+
return readBlock();
|
|
20359
|
+
}, object: void 0 });
|
|
20360
|
+
} else this.data.assign(index, 0);
|
|
20361
|
+
this.fluidCells[index] = 0;
|
|
20362
|
+
if (order < failureOrder) {
|
|
20363
|
+
failureOrder = order;
|
|
20364
|
+
failure = result.reason;
|
|
20365
|
+
}
|
|
20366
|
+
}
|
|
20367
|
+
}
|
|
20368
|
+
if (failureOrder < Infinity) throw failure;
|
|
20325
20369
|
return positions;
|
|
20326
20370
|
}
|
|
20327
20371
|
/** Replaces every cell from parsed section data. The caller refreshes neighbor culling. */
|
|
@@ -20392,37 +20436,42 @@ var Chunk = class _Chunk {
|
|
|
20392
20436
|
failed = true;
|
|
20393
20437
|
}
|
|
20394
20438
|
}
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20398
|
-
|
|
20399
|
-
|
|
20400
|
-
|
|
20401
|
-
|
|
20402
|
-
|
|
20403
|
-
|
|
20404
|
-
|
|
20405
|
-
|
|
20406
|
-
|
|
20407
|
-
|
|
20408
|
-
|
|
20409
|
-
|
|
20410
|
-
|
|
20411
|
-
)
|
|
20412
|
-
this.renderedBlocks.get(index).object = object4;
|
|
20439
|
+
const objects = await Promise.allSettled(perBlocks.map(({ index, blockState: blockState3, biome }) => this.createBlockObject(blockState3, new import_three47.Vector3(
|
|
20440
|
+
this.x * 256 + index % 16 * 16,
|
|
20441
|
+
this.y * 256 + Math.floor(index / 256) * 16,
|
|
20442
|
+
this.z * 256 + Math.floor(index / 16) % 16 * 16
|
|
20443
|
+
), {
|
|
20444
|
+
mergeMeshes: true,
|
|
20445
|
+
instanceMeshes: true,
|
|
20446
|
+
maxInstanceCount: 2e3,
|
|
20447
|
+
initialState: this.data.stateAt(this.data.idAt(index)).properties,
|
|
20448
|
+
variantPosition: this.positionAt(index),
|
|
20449
|
+
biome,
|
|
20450
|
+
biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
|
|
20451
|
+
})));
|
|
20452
|
+
for (const [i, { index }] of perBlocks.entries()) {
|
|
20453
|
+
const result = objects[i];
|
|
20454
|
+
if (result.status === "fulfilled") {
|
|
20455
|
+
this.renderedBlocks.get(index).object = result.value;
|
|
20413
20456
|
this.objectBlocks.add(index);
|
|
20414
|
-
}
|
|
20457
|
+
} else {
|
|
20415
20458
|
this.data.assign(index, 0);
|
|
20416
20459
|
this.fluidCells[index] = 0;
|
|
20417
20460
|
this.renderedBlocks.delete(index);
|
|
20418
20461
|
this.objectBlocks.delete(index);
|
|
20419
|
-
|
|
20420
|
-
if (!failed) failure = error;
|
|
20462
|
+
if (!failed) failure = result.reason;
|
|
20421
20463
|
failed = true;
|
|
20422
20464
|
}
|
|
20423
20465
|
}
|
|
20424
20466
|
if (failed) throw failure;
|
|
20425
20467
|
}
|
|
20468
|
+
createBlockObject(blockState3, position, options) {
|
|
20469
|
+
return this.scene.addSceneObject(blockState3, () => {
|
|
20470
|
+
const object4 = new BlockObject(blockState3, options);
|
|
20471
|
+
object4.position.copy(position);
|
|
20472
|
+
return object4;
|
|
20473
|
+
}, options);
|
|
20474
|
+
}
|
|
20426
20475
|
positionAt(index) {
|
|
20427
20476
|
return [this.x * 16 + index % 16, this.y * 16 + Math.floor(index / 256), this.z * 16 + Math.floor(index / 16) % 16];
|
|
20428
20477
|
}
|