minerender 2.1.0-alpha.114 → 2.1.0-alpha.116
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/dist/browser/index.d.mts +199 -13
- package/dist/browser/index.d.ts +199 -13
- package/dist/browser/index.js +939 -231
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +885 -177
- package/dist/browser/index.mjs.map +1 -1
- package/dist/browser/section.worker.js +6 -3
- package/dist/browser/section.worker.js.map +1 -1
- package/dist/browser/section.worker.mjs +6 -3
- package/dist/browser/section.worker.mjs.map +1 -1
- package/dist/bundle.js +903 -139
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +199 -13
- package/dist/node/index.d.ts +199 -13
- package/dist/node/index.js +944 -231
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +887 -177
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.js
CHANGED
|
@@ -324,6 +324,9 @@ var init_Caching = __esm({
|
|
|
324
324
|
static {
|
|
325
325
|
this.usernameUuidCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
|
|
326
326
|
}
|
|
327
|
+
static {
|
|
328
|
+
this.biomeCache = _Caching.createAssetCache();
|
|
329
|
+
}
|
|
327
330
|
static createAssetCache() {
|
|
328
331
|
return import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
|
|
329
332
|
}
|
|
@@ -353,7 +356,8 @@ var init_Caching = __esm({
|
|
|
353
356
|
this.fontCache,
|
|
354
357
|
this.bannerPatternCache,
|
|
355
358
|
this.mineRenderDataCache,
|
|
356
|
-
this.usernameUuidCache
|
|
359
|
+
this.usernameUuidCache,
|
|
360
|
+
this.biomeCache
|
|
357
361
|
];
|
|
358
362
|
}
|
|
359
363
|
/** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */
|
|
@@ -1731,7 +1735,7 @@ ${key}` : key, async () => {
|
|
|
1731
1735
|
case "blockStates":
|
|
1732
1736
|
return Object.values(value).every((property) => object(property) && "default" in property && Array.isArray(property.values));
|
|
1733
1737
|
case "blockTints":
|
|
1734
|
-
return ["constant", "grass", "stem", "redstone"].includes(value.source) && (value.source !== "constant" || Number.isInteger(value.color));
|
|
1738
|
+
return ["constant", "grass", "stem", "redstone"].includes(value.source) && (value.source !== "constant" || Number.isInteger(value.color)) && (value.biome === void 0 || ["grass", "foliage", "dry_foliage", "water"].includes(value.biome));
|
|
1735
1739
|
case "fluids":
|
|
1736
1740
|
return ["water", "lava"].includes(value.kind) && typeof value.renderModel === "boolean" && (value.levelProperty === void 0 || typeof value.levelProperty === "string");
|
|
1737
1741
|
case "dyes":
|
|
@@ -1875,15 +1879,19 @@ var init_Colormaps = __esm({
|
|
|
1875
1879
|
Colormaps = class {
|
|
1876
1880
|
/** Samples the selected resource pack's grass colormap using Minecraft's climate coordinates. */
|
|
1877
1881
|
static async grassColor(origin, temperature = 0.5, downfall = 1) {
|
|
1878
|
-
|
|
1882
|
+
return this.getColor("grass", origin, temperature, downfall);
|
|
1883
|
+
}
|
|
1884
|
+
/** Samples a resource-pack colormap at the supplied climate coordinates. */
|
|
1885
|
+
static async getColor(kind, origin, temperature = 0.5, downfall = 1) {
|
|
1886
|
+
const key = AssetKey.parse("textures", `minecraft:colormap/${kind}`, origin);
|
|
1879
1887
|
const temp = Math.fround(temperature);
|
|
1880
1888
|
const rain = Math.fround(downfall) * temp;
|
|
1881
1889
|
const x = Math.floor((1 - temp) * 255), y = Math.floor((1 - rain) * 255);
|
|
1882
1890
|
return await Caching.blockTintCache.get(`${key.serialize()}|${x},${y}`, async () => {
|
|
1883
1891
|
const image = await ModelTextures.get(key);
|
|
1884
|
-
if (!image) throw new MineRenderError(`Missing
|
|
1892
|
+
if (!image) throw new MineRenderError(`Missing ${kind} colormap: ${key.toNamespacedString()}`);
|
|
1885
1893
|
if (image.width !== 256 || image.height !== 256) {
|
|
1886
|
-
throw new MineRenderError(
|
|
1894
|
+
throw new MineRenderError(`${kind} colormaps must be 256 \xD7 256 pixels`);
|
|
1887
1895
|
}
|
|
1888
1896
|
const [red, green, blue] = image.data.getImageData(x, y, 1, 1).data;
|
|
1889
1897
|
return red << 16 | green << 8 | blue;
|
|
@@ -7614,6 +7622,7 @@ __export(index_node_exports, {
|
|
|
7614
7622
|
BannerPatterns: () => BannerPatterns,
|
|
7615
7623
|
BasicAssetKey: () => BasicAssetKey,
|
|
7616
7624
|
BatchedExecutor: () => BatchedExecutor,
|
|
7625
|
+
Biomes: () => Biomes,
|
|
7617
7626
|
BlockEntities: () => BlockEntities,
|
|
7618
7627
|
BlockObject: () => BlockObject,
|
|
7619
7628
|
BlockStateResolver: () => BlockStateResolver,
|
|
@@ -7645,6 +7654,7 @@ __export(index_node_exports, {
|
|
|
7645
7654
|
EntityObject: () => EntityObject,
|
|
7646
7655
|
Env: () => Env,
|
|
7647
7656
|
FluidModelObject: () => FluidModelObject,
|
|
7657
|
+
FlyControls: () => FlyControls,
|
|
7648
7658
|
Fonts: () => Fonts,
|
|
7649
7659
|
GUI_CONTAINER_LAYOUTS: () => GUI_CONTAINER_LAYOUTS,
|
|
7650
7660
|
Geometries: () => Geometries,
|
|
@@ -7750,6 +7760,7 @@ __export(index_node_exports, {
|
|
|
7750
7760
|
isDisposable: () => isDisposable,
|
|
7751
7761
|
isDoubleArray: () => isDoubleArray,
|
|
7752
7762
|
isEntityObject: () => isEntityObject,
|
|
7763
|
+
isFlyControls: () => isFlyControls,
|
|
7753
7764
|
isGuiObject: () => isGuiObject,
|
|
7754
7765
|
isInstanceManager: () => isInstanceManager,
|
|
7755
7766
|
isInstanceReference: () => isInstanceReference,
|
|
@@ -7954,6 +7965,116 @@ init_AssetLoader();
|
|
|
7954
7965
|
init_Assets();
|
|
7955
7966
|
init_BannerPatterns();
|
|
7956
7967
|
|
|
7968
|
+
// src/assets/Biomes.ts
|
|
7969
|
+
init_AssetKey();
|
|
7970
|
+
init_AssetLoader();
|
|
7971
|
+
init_AssetParsers();
|
|
7972
|
+
init_Caching();
|
|
7973
|
+
init_MineRenderError();
|
|
7974
|
+
init_Colormaps();
|
|
7975
|
+
|
|
7976
|
+
// src/assets/_biomes/SwampGrassColor.ts
|
|
7977
|
+
var permutation;
|
|
7978
|
+
var gradients = [[1, 1], [-1, 1], [1, -1], [-1, -1], [1, 0], [-1, 0], [1, 0], [-1, 0], [0, 1], [0, -1], [0, 1], [0, -1]];
|
|
7979
|
+
var skew = (Math.sqrt(3) - 1) / 2;
|
|
7980
|
+
var unskew = (3 - Math.sqrt(3)) / 6;
|
|
7981
|
+
function createPermutation() {
|
|
7982
|
+
const multiplier = 0x5deece66dn, mask = (1n << 48n) - 1n;
|
|
7983
|
+
let seed = 2345n ^ multiplier;
|
|
7984
|
+
const next = (bits) => {
|
|
7985
|
+
seed = seed * multiplier + 11n & mask;
|
|
7986
|
+
return Number(seed >> BigInt(48 - bits));
|
|
7987
|
+
};
|
|
7988
|
+
for (let i = 0; i < 3; i++) {
|
|
7989
|
+
next(26);
|
|
7990
|
+
next(27);
|
|
7991
|
+
}
|
|
7992
|
+
const values = Uint8Array.from({ length: 256 }, (_, i) => i);
|
|
7993
|
+
for (let i = 0; i < 256; i++) {
|
|
7994
|
+
const bound = 256 - i;
|
|
7995
|
+
let offset;
|
|
7996
|
+
if ((bound & bound - 1) === 0) offset = Math.floor(bound * next(31) / 2147483648);
|
|
7997
|
+
else {
|
|
7998
|
+
let bits;
|
|
7999
|
+
do {
|
|
8000
|
+
bits = next(31);
|
|
8001
|
+
offset = bits % bound;
|
|
8002
|
+
} while (bits - offset + bound - 1 > 2147483647);
|
|
8003
|
+
}
|
|
8004
|
+
const other = i + offset;
|
|
8005
|
+
[values[i], values[other]] = [values[other], values[i]];
|
|
8006
|
+
}
|
|
8007
|
+
return values;
|
|
8008
|
+
}
|
|
8009
|
+
function swampGrassColor(x, z) {
|
|
8010
|
+
const p10 = permutation ??= createPermutation();
|
|
8011
|
+
x *= 0.0225;
|
|
8012
|
+
z *= 0.0225;
|
|
8013
|
+
const s = (x + z) * skew;
|
|
8014
|
+
const i = Math.floor(x + s), j = Math.floor(z + s);
|
|
8015
|
+
const t = (i + j) * unskew;
|
|
8016
|
+
const dx = x - (i - t), dz = z - (j - t);
|
|
8017
|
+
const stepX = dx > dz ? 1 : 0, stepZ = 1 - stepX;
|
|
8018
|
+
const corner = (gx, gz, a, b) => {
|
|
8019
|
+
let falloff = 0.5 - a * a - b * b;
|
|
8020
|
+
if (falloff < 0) return 0;
|
|
8021
|
+
const gradient = gradients[p10[gx + p10[gz & 255] & 255] % 12];
|
|
8022
|
+
falloff *= falloff;
|
|
8023
|
+
return falloff * falloff * (gradient[0] * a + gradient[1] * b);
|
|
8024
|
+
};
|
|
8025
|
+
const noise = 70 * (corner(i, j, dx, dz) + corner(i + stepX, j + stepZ, dx - stepX + unskew, dz - stepZ + unskew) + corner(i + 1, j + 1, dx - 1 + 2 * unskew, dz - 1 + 2 * unskew));
|
|
8026
|
+
return noise < -0.1 ? 5011004 : 6975545;
|
|
8027
|
+
}
|
|
8028
|
+
|
|
8029
|
+
// src/assets/Biomes.ts
|
|
8030
|
+
var Biomes = class {
|
|
8031
|
+
/** Loads a biome registry entry, or returns `undefined` when no source provides it. */
|
|
8032
|
+
static async get(id, origin) {
|
|
8033
|
+
if (!/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(id)) throw new MineRenderError(`Invalid biome identifier: ${id}`);
|
|
8034
|
+
const [namespace, path] = id.includes(":") ? id.split(":") : ["minecraft", id];
|
|
8035
|
+
const key = new AssetKey(namespace, path, "worldgen", "biome", "data", ".json", origin?.root);
|
|
8036
|
+
return Caching.biomeCache.get(key.serialize(), async () => {
|
|
8037
|
+
const asset2 = await AssetLoader.get(key, "json" /* JSON */);
|
|
8038
|
+
if (asset2 === void 0) return void 0;
|
|
8039
|
+
if (!asset2 || typeof asset2 !== "object" || Array.isArray(asset2) || !asset2.effects || typeof asset2.effects !== "object" || Array.isArray(asset2.effects)) {
|
|
8040
|
+
throw new MineRenderError(`Invalid biome effects: ${id}`);
|
|
8041
|
+
}
|
|
8042
|
+
if (typeof asset2.temperature !== "number" || !Number.isFinite(asset2.temperature) || typeof asset2.downfall !== "number" || !Number.isFinite(asset2.downfall)) {
|
|
8043
|
+
throw new MineRenderError(`Invalid biome climate: ${id}`);
|
|
8044
|
+
}
|
|
8045
|
+
for (const kind of ["grass", "foliage", "dry_foliage", "water"]) {
|
|
8046
|
+
const color2 = asset2.effects[`${kind}_color`];
|
|
8047
|
+
if (color2 !== void 0) this.parseColor(color2, id, kind);
|
|
8048
|
+
}
|
|
8049
|
+
const modifier = asset2.effects.grass_color_modifier;
|
|
8050
|
+
if (modifier !== void 0 && modifier !== "none" && modifier !== "dark_forest" && modifier !== "swamp") {
|
|
8051
|
+
throw new MineRenderError(`Invalid biome grass color modifier: ${id}`);
|
|
8052
|
+
}
|
|
8053
|
+
return asset2;
|
|
8054
|
+
});
|
|
8055
|
+
}
|
|
8056
|
+
/** Returns packed sRGB, or `undefined` when the biome or requested water color is missing. */
|
|
8057
|
+
static async getColor(id, kind, origin, x = 0, z = 0) {
|
|
8058
|
+
const biome = await this.get(id, origin);
|
|
8059
|
+
if (!biome) return void 0;
|
|
8060
|
+
const rawColor = biome.effects[`${kind}_color`];
|
|
8061
|
+
let color2 = rawColor === void 0 ? void 0 : this.parseColor(rawColor, id, kind);
|
|
8062
|
+
if (kind === "water") return color2;
|
|
8063
|
+
const modifier = kind === "grass" ? biome.effects.grass_color_modifier : void 0;
|
|
8064
|
+
if (modifier === "swamp") return swampGrassColor(x, z);
|
|
8065
|
+
if (color2 === void 0) {
|
|
8066
|
+
const clamp = (value) => Math.max(0, Math.min(1, Math.fround(value)));
|
|
8067
|
+
color2 = await Colormaps.getColor(kind, origin, clamp(biome.temperature), clamp(biome.downfall));
|
|
8068
|
+
}
|
|
8069
|
+
return modifier === "dark_forest" ? (color2 & 16711422) + 2634762 >> 1 : color2;
|
|
8070
|
+
}
|
|
8071
|
+
static parseColor(value, id, kind) {
|
|
8072
|
+
if (typeof value === "string" && /^#[0-9a-fA-F]{6}$/.test(value)) return parseInt(value.slice(1), 16);
|
|
8073
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 16777215) return value;
|
|
8074
|
+
throw new MineRenderError(`Invalid biome ${kind} color: ${id}`);
|
|
8075
|
+
}
|
|
8076
|
+
};
|
|
8077
|
+
|
|
7957
8078
|
// src/assets/BlockEntities.ts
|
|
7958
8079
|
var import_three10 = require("three");
|
|
7959
8080
|
init_AssetKey();
|
|
@@ -12392,8 +12513,20 @@ var BlockStateResolver = class _BlockStateResolver {
|
|
|
12392
12513
|
init_Colormaps();
|
|
12393
12514
|
init_MineRenderData();
|
|
12394
12515
|
var BlockTints = class {
|
|
12395
|
-
/**
|
|
12396
|
-
static async
|
|
12516
|
+
/** Returns a block's versioned biome color source, leaving fixed-color blocks unchanged. */
|
|
12517
|
+
static async biomeSource(key) {
|
|
12518
|
+
const rule = key && (await MineRenderData.get("blockTints", key.root))[key.toNamespacedString()];
|
|
12519
|
+
return rule ? rule.biome ?? (rule.source === "grass" ? "grass" : void 0) : void 0;
|
|
12520
|
+
}
|
|
12521
|
+
/** Resolves one block's biome tint at world block coordinates, without biome blending. */
|
|
12522
|
+
static async getBiomeColor(key, biome, position) {
|
|
12523
|
+
if (!biome) return void 0;
|
|
12524
|
+
const x = position?.[0], z = position?.[2];
|
|
12525
|
+
const source = await this.biomeSource(key);
|
|
12526
|
+
return source ? Biomes.getColor(biome, source, key, x, z) : void 0;
|
|
12527
|
+
}
|
|
12528
|
+
/** Resolves used tint indices from biome or preview colors; explicit tints take precedence. */
|
|
12529
|
+
static async get(key, state, model, tints, biomeColor) {
|
|
12397
12530
|
if (!key) return tints;
|
|
12398
12531
|
const candidates = (model.elements ?? []).flatMap((element) => Object.values(element.faces)).some((face) => face?.tintindex !== void 0 && face.tintindex >= 0 && tints?.[face.tintindex] === void 0);
|
|
12399
12532
|
if (!candidates) return tints;
|
|
@@ -12409,8 +12542,12 @@ var BlockTints = class {
|
|
|
12409
12542
|
}
|
|
12410
12543
|
}
|
|
12411
12544
|
if (!indices.size) return tints;
|
|
12545
|
+
const source = rule.biome ?? (rule.source === "grass" ? "grass" : void 0);
|
|
12546
|
+
const biome = source ? typeof biomeColor === "function" ? await biomeColor() : biomeColor : void 0;
|
|
12412
12547
|
let color2;
|
|
12413
|
-
|
|
12548
|
+
if (biome !== void 0) {
|
|
12549
|
+
color2 = biome;
|
|
12550
|
+
} else switch (rule.source) {
|
|
12414
12551
|
case "constant":
|
|
12415
12552
|
color2 = rule.color;
|
|
12416
12553
|
break;
|
|
@@ -12469,6 +12606,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12469
12606
|
this._entityGeneration = 0;
|
|
12470
12607
|
this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
|
|
12471
12608
|
this.variantPosition = options?.variantPosition ? [...options.variantPosition] : void 0;
|
|
12609
|
+
this.biomePosition = options?.biomePosition ? [...options.biomePosition] : void 0;
|
|
12472
12610
|
}
|
|
12473
12611
|
static {
|
|
12474
12612
|
this.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, ModelObject.DEFAULT_OPTIONS, {
|
|
@@ -12666,11 +12804,16 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12666
12804
|
const { FluidModelObject: FluidModelObject2, sampleFluid: sampleFluid2 } = await Promise.resolve().then(() => (init_FluidModelObject(), FluidModelObject_exports));
|
|
12667
12805
|
this._fluidSampler = sample;
|
|
12668
12806
|
const surface = sampleFluid2(kind, (x, y, z) => x === 0 && y === 0 && z === 0 ? { fluid: kind, level: this.fluidLevel } : sample?.(x, y, z) ?? {});
|
|
12669
|
-
|
|
12807
|
+
const tint = this.options.tints?.[0] ?? this.waterTint;
|
|
12808
|
+
const fluidKey = `${surface.key}|${tint ?? "default"}`;
|
|
12809
|
+
if (this._fluidKey === fluidKey) return;
|
|
12670
12810
|
const key = new AssetKey("minecraft", `${kind}/${surface.key}`, "models", "fluid", "assets", ".json", this.blockState.key?.root);
|
|
12671
12811
|
const replacement = await this.scene.addSceneObject(
|
|
12672
12812
|
{ key },
|
|
12673
|
-
() => new FluidModelObject2(kind, surface.sample, this.blockState.key,
|
|
12813
|
+
() => new FluidModelObject2(kind, surface.sample, this.blockState.key, {
|
|
12814
|
+
...this.options,
|
|
12815
|
+
tints: tint === void 0 ? this.options.tints : { ...this.options.tints, 0: tint }
|
|
12816
|
+
})
|
|
12674
12817
|
);
|
|
12675
12818
|
const previous = this._fluidModel;
|
|
12676
12819
|
const matrix = previous ? this.getModelMatrix(previous) : new import_three34.Matrix4().makeTranslation(...this.position.toArray());
|
|
@@ -12679,7 +12822,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12679
12822
|
this._models = this._models.filter((model) => model !== previous);
|
|
12680
12823
|
this._models.push(replacement);
|
|
12681
12824
|
this._fluidModel = replacement;
|
|
12682
|
-
this._fluidKey =
|
|
12825
|
+
this._fluidKey = fluidKey;
|
|
12683
12826
|
this._isInstanced ||= isInstanceReference(replacement);
|
|
12684
12827
|
this._instanceCounter = this._isInstanced ? 1 : 0;
|
|
12685
12828
|
if (previous) this.removeModels([previous]);
|
|
@@ -12702,6 +12845,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12702
12845
|
}
|
|
12703
12846
|
async recreateModels() {
|
|
12704
12847
|
this.clearModels();
|
|
12848
|
+
this.waterTint = this.fluidKind === "water" && this.options.biome && this.options.tints?.[0] === void 0 ? await Biomes.getColor(this.options.biome, "water", this.blockState.key) : void 0;
|
|
12705
12849
|
if (resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.renderModel === false) {
|
|
12706
12850
|
await this.updateFluid(this._fluidSampler);
|
|
12707
12851
|
return;
|
|
@@ -12736,7 +12880,13 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12736
12880
|
const model = await Models.getMerged(modelKey);
|
|
12737
12881
|
const options = {
|
|
12738
12882
|
...this.options,
|
|
12739
|
-
tints: model ? await BlockTints.get(
|
|
12883
|
+
tints: model ? await BlockTints.get(
|
|
12884
|
+
this.blockState.key,
|
|
12885
|
+
this.state,
|
|
12886
|
+
model,
|
|
12887
|
+
this.options.tints,
|
|
12888
|
+
() => BlockTints.getBiomeColor(this.blockState.key, this.options.biome, this.biomePosition)
|
|
12889
|
+
) : this.options.tints,
|
|
12740
12890
|
uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0,
|
|
12741
12891
|
cullMask: this.options.displayPosition ? 0 : ModelCulling.toLocalMask(this._cullMask, rotation)
|
|
12742
12892
|
};
|
|
@@ -13319,8 +13469,323 @@ init_ModelObject();
|
|
|
13319
13469
|
// src/index.ts
|
|
13320
13470
|
init_nbt();
|
|
13321
13471
|
|
|
13322
|
-
// src/renderer/
|
|
13472
|
+
// src/renderer/FlyControls.ts
|
|
13323
13473
|
var import_three35 = require("three");
|
|
13474
|
+
var VANILLA_FLY_SPEED = 10.89;
|
|
13475
|
+
var PITCH_LIMIT = Math.PI / 2;
|
|
13476
|
+
var MOVE_EPSILON = 1e-6;
|
|
13477
|
+
var _euler = new import_three35.Euler(0, 0, 0, "YXZ");
|
|
13478
|
+
var _forward = new import_three35.Vector3();
|
|
13479
|
+
var _right = new import_three35.Vector3();
|
|
13480
|
+
var _targetVelocity = new import_three35.Vector3();
|
|
13481
|
+
var FlyControls = class extends import_three35.Controls {
|
|
13482
|
+
constructor(camera, domElement) {
|
|
13483
|
+
super(camera, domElement ?? null);
|
|
13484
|
+
this.isFlyControls = true;
|
|
13485
|
+
/** Horizontal and vertical speed in scene units per second; vanilla creative flight by default. */
|
|
13486
|
+
this.movementSpeed = 16 * VANILLA_FLY_SPEED;
|
|
13487
|
+
/** Speed multiplier while the sprint key is held. */
|
|
13488
|
+
this.sprintMultiplier = 2;
|
|
13489
|
+
/** Radians per pixel of pointer movement. */
|
|
13490
|
+
this.lookSpeed = 2e-3;
|
|
13491
|
+
/** Smooth acceleration and deceleration, approximating vanilla flight momentum. */
|
|
13492
|
+
this.enableDamping = true;
|
|
13493
|
+
/** Portion of the remaining velocity change applied per 60 Hz frame (0–1) when damping is enabled. */
|
|
13494
|
+
this.dampingFactor = 0.25;
|
|
13495
|
+
/** Capture the pointer on click so the mouse turns the camera without dragging; dragging works regardless. */
|
|
13496
|
+
this.pointerLock = true;
|
|
13497
|
+
/** Scroll the wheel to change `movementSpeed` within `speedRange`. */
|
|
13498
|
+
this.enableWheelSpeed = true;
|
|
13499
|
+
/** Minimum and maximum `movementSpeed` reachable with the wheel. */
|
|
13500
|
+
this.speedRange = [16, 16 * 500];
|
|
13501
|
+
/** Touch joystick travel in CSS pixels for full speed. */
|
|
13502
|
+
this.joystickRadius = 64;
|
|
13503
|
+
/** Key bindings by `KeyboardEvent.code`. */
|
|
13504
|
+
this.keys = {
|
|
13505
|
+
forward: ["KeyW", "ArrowUp"],
|
|
13506
|
+
back: ["KeyS", "ArrowDown"],
|
|
13507
|
+
left: ["KeyA", "ArrowLeft"],
|
|
13508
|
+
right: ["KeyD", "ArrowRight"],
|
|
13509
|
+
up: ["Space"],
|
|
13510
|
+
down: ["ShiftLeft", "ShiftRight"],
|
|
13511
|
+
sprint: ["ControlLeft", "ControlRight"]
|
|
13512
|
+
};
|
|
13513
|
+
this._pressed = /* @__PURE__ */ new Set();
|
|
13514
|
+
this._velocity = new import_three35.Vector3();
|
|
13515
|
+
this._lastPosition = new import_three35.Vector3();
|
|
13516
|
+
this._lastQuaternion = new import_three35.Quaternion();
|
|
13517
|
+
this._position0 = new import_three35.Vector3();
|
|
13518
|
+
this._quaternion0 = new import_three35.Quaternion();
|
|
13519
|
+
this._dragMoved = false;
|
|
13520
|
+
this._locked = false;
|
|
13521
|
+
this._onKeyDown = (event) => this.handleKey(event, true);
|
|
13522
|
+
this._onKeyUp = (event) => this.handleKey(event, false);
|
|
13523
|
+
this._onPointerDown = (event) => this.handlePointerDown(event);
|
|
13524
|
+
this._onPointerMove = (event) => this.handlePointerMove(event);
|
|
13525
|
+
this._onPointerUp = (event) => this.handlePointerUp(event);
|
|
13526
|
+
this._onPointerLockChange = () => this.handlePointerLockChange();
|
|
13527
|
+
this._onContextMenu = (event) => event.preventDefault();
|
|
13528
|
+
this._onWheel = (event) => this.handleWheel(event);
|
|
13529
|
+
this._onBlur = () => this.releaseKeys();
|
|
13530
|
+
this._lastPosition.copy(camera.position);
|
|
13531
|
+
this._lastQuaternion.copy(camera.quaternion);
|
|
13532
|
+
this.saveState();
|
|
13533
|
+
if (domElement) this.connect(domElement);
|
|
13534
|
+
}
|
|
13535
|
+
connect(element) {
|
|
13536
|
+
super.connect(element);
|
|
13537
|
+
const document2 = element.ownerDocument;
|
|
13538
|
+
document2.addEventListener("keydown", this._onKeyDown);
|
|
13539
|
+
document2.addEventListener("keyup", this._onKeyUp);
|
|
13540
|
+
document2.addEventListener("pointerlockchange", this._onPointerLockChange);
|
|
13541
|
+
document2.defaultView?.addEventListener("blur", this._onBlur);
|
|
13542
|
+
element.addEventListener("pointerdown", this._onPointerDown);
|
|
13543
|
+
element.addEventListener("pointermove", this._onPointerMove);
|
|
13544
|
+
element.addEventListener("pointerup", this._onPointerUp);
|
|
13545
|
+
element.addEventListener("pointercancel", this._onPointerUp);
|
|
13546
|
+
element.addEventListener("contextmenu", this._onContextMenu);
|
|
13547
|
+
element.addEventListener("wheel", this._onWheel, { passive: false });
|
|
13548
|
+
element.addEventListener("blur", this._onBlur);
|
|
13549
|
+
element.style.touchAction = "none";
|
|
13550
|
+
if (element.tabIndex < 0) element.tabIndex = 0;
|
|
13551
|
+
}
|
|
13552
|
+
disconnect() {
|
|
13553
|
+
const element = this.domElement;
|
|
13554
|
+
if (!element) return;
|
|
13555
|
+
const document2 = element.ownerDocument;
|
|
13556
|
+
document2.removeEventListener("keydown", this._onKeyDown);
|
|
13557
|
+
document2.removeEventListener("keyup", this._onKeyUp);
|
|
13558
|
+
document2.removeEventListener("pointerlockchange", this._onPointerLockChange);
|
|
13559
|
+
document2.defaultView?.removeEventListener("blur", this._onBlur);
|
|
13560
|
+
element.removeEventListener("pointerdown", this._onPointerDown);
|
|
13561
|
+
element.removeEventListener("pointermove", this._onPointerMove);
|
|
13562
|
+
element.removeEventListener("pointerup", this._onPointerUp);
|
|
13563
|
+
element.removeEventListener("pointercancel", this._onPointerUp);
|
|
13564
|
+
element.removeEventListener("contextmenu", this._onContextMenu);
|
|
13565
|
+
element.removeEventListener("wheel", this._onWheel);
|
|
13566
|
+
element.removeEventListener("blur", this._onBlur);
|
|
13567
|
+
element.style.touchAction = "auto";
|
|
13568
|
+
this.unlock();
|
|
13569
|
+
this._locked = false;
|
|
13570
|
+
this.releaseKeys();
|
|
13571
|
+
this._dragPointer = void 0;
|
|
13572
|
+
this._joystick = void 0;
|
|
13573
|
+
}
|
|
13574
|
+
dispose() {
|
|
13575
|
+
this.disconnect();
|
|
13576
|
+
}
|
|
13577
|
+
/** Whether mouse look currently owns the pointer. */
|
|
13578
|
+
get locked() {
|
|
13579
|
+
return this._locked;
|
|
13580
|
+
}
|
|
13581
|
+
/** Requests pointer capture; browsers only allow this from a user gesture. */
|
|
13582
|
+
lock() {
|
|
13583
|
+
const element = this.domElement;
|
|
13584
|
+
if (!element || this._locked || typeof element.requestPointerLock !== "function") return;
|
|
13585
|
+
try {
|
|
13586
|
+
const result = element.requestPointerLock();
|
|
13587
|
+
if (result instanceof Promise) result.catch(() => void 0);
|
|
13588
|
+
} catch {
|
|
13589
|
+
}
|
|
13590
|
+
}
|
|
13591
|
+
/** Releases a captured pointer. */
|
|
13592
|
+
unlock() {
|
|
13593
|
+
const document2 = this.domElement?.ownerDocument;
|
|
13594
|
+
if (document2?.pointerLockElement && document2.pointerLockElement === this.domElement) {
|
|
13595
|
+
document2.exitPointerLock();
|
|
13596
|
+
}
|
|
13597
|
+
}
|
|
13598
|
+
/** Stores the camera pose that {@link reset} restores. */
|
|
13599
|
+
saveState() {
|
|
13600
|
+
this._position0.copy(this.object.position);
|
|
13601
|
+
this._quaternion0.copy(this.object.quaternion);
|
|
13602
|
+
}
|
|
13603
|
+
/** Restores the saved camera pose and stops movement. */
|
|
13604
|
+
reset() {
|
|
13605
|
+
this.object.position.copy(this._position0);
|
|
13606
|
+
this.object.quaternion.copy(this._quaternion0);
|
|
13607
|
+
this._velocity.set(0, 0, 0);
|
|
13608
|
+
this.notifyChange();
|
|
13609
|
+
}
|
|
13610
|
+
/** Horizontal yaw in radians, where zero looks toward -Z. */
|
|
13611
|
+
get yaw() {
|
|
13612
|
+
return _euler.setFromQuaternion(this.object.quaternion).y;
|
|
13613
|
+
}
|
|
13614
|
+
/** Vertical pitch in radians, positive looking up. */
|
|
13615
|
+
get pitch() {
|
|
13616
|
+
return _euler.setFromQuaternion(this.object.quaternion).x;
|
|
13617
|
+
}
|
|
13618
|
+
/** Turns the camera; pitch is clamped to straight up and down. */
|
|
13619
|
+
setRotation(yaw, pitch) {
|
|
13620
|
+
_euler.set(import_three35.MathUtils.clamp(pitch, -PITCH_LIMIT, PITCH_LIMIT), yaw, 0);
|
|
13621
|
+
this.object.quaternion.setFromEuler(_euler);
|
|
13622
|
+
this.notifyChange();
|
|
13623
|
+
}
|
|
13624
|
+
/** Points the camera at a position without rolling it. */
|
|
13625
|
+
lookAt(target) {
|
|
13626
|
+
_forward.copy(target).sub(this.object.position);
|
|
13627
|
+
if (_forward.lengthSq() < MOVE_EPSILON) return;
|
|
13628
|
+
_forward.normalize();
|
|
13629
|
+
this.setRotation(Math.atan2(-_forward.x, -_forward.z), Math.asin(import_three35.MathUtils.clamp(_forward.y, -1, 1)));
|
|
13630
|
+
}
|
|
13631
|
+
/** Whether an action's key is held. */
|
|
13632
|
+
isPressed(action) {
|
|
13633
|
+
return this._pressed.has(action);
|
|
13634
|
+
}
|
|
13635
|
+
/**
|
|
13636
|
+
* Advances movement by `delta` seconds (measured since the previous call when omitted)
|
|
13637
|
+
* and dispatches `change` when the camera moved.
|
|
13638
|
+
*/
|
|
13639
|
+
update(delta) {
|
|
13640
|
+
if (delta === void 0) {
|
|
13641
|
+
const now = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
13642
|
+
delta = this._lastTime === void 0 ? 0 : (now - this._lastTime) / 1e3;
|
|
13643
|
+
this._lastTime = now;
|
|
13644
|
+
}
|
|
13645
|
+
if (!this.enabled) {
|
|
13646
|
+
this._velocity.set(0, 0, 0);
|
|
13647
|
+
return;
|
|
13648
|
+
}
|
|
13649
|
+
if (delta > 0) this.move(delta);
|
|
13650
|
+
this.notifyChange();
|
|
13651
|
+
}
|
|
13652
|
+
move(delta) {
|
|
13653
|
+
const camera = this.object;
|
|
13654
|
+
let forward = (this._pressed.has("forward") ? 1 : 0) - (this._pressed.has("back") ? 1 : 0);
|
|
13655
|
+
let strafe = (this._pressed.has("right") ? 1 : 0) - (this._pressed.has("left") ? 1 : 0);
|
|
13656
|
+
const climb = (this._pressed.has("up") ? 1 : 0) - (this._pressed.has("down") ? 1 : 0);
|
|
13657
|
+
const joystick = this._joystick;
|
|
13658
|
+
if (joystick) {
|
|
13659
|
+
const radius = Math.max(this.joystickRadius, 1);
|
|
13660
|
+
forward = import_three35.MathUtils.clamp(forward + (joystick.originY - joystick.y) / radius, -1, 1);
|
|
13661
|
+
strafe = import_three35.MathUtils.clamp(strafe + (joystick.x - joystick.originX) / radius, -1, 1);
|
|
13662
|
+
}
|
|
13663
|
+
_euler.setFromQuaternion(camera.quaternion);
|
|
13664
|
+
const yaw = _euler.y;
|
|
13665
|
+
_forward.set(-Math.sin(yaw), 0, -Math.cos(yaw));
|
|
13666
|
+
_right.set(Math.cos(yaw), 0, -Math.sin(yaw));
|
|
13667
|
+
_targetVelocity.set(0, 0, 0);
|
|
13668
|
+
if (forward || strafe || climb) {
|
|
13669
|
+
_targetVelocity.addScaledVector(_forward, forward).addScaledVector(_right, strafe);
|
|
13670
|
+
if (_targetVelocity.lengthSq() > 1) _targetVelocity.normalize();
|
|
13671
|
+
_targetVelocity.y = climb;
|
|
13672
|
+
const speed = this.movementSpeed * (this._pressed.has("sprint") ? this.sprintMultiplier : 1);
|
|
13673
|
+
_targetVelocity.multiplyScalar(speed);
|
|
13674
|
+
}
|
|
13675
|
+
if (this.enableDamping) {
|
|
13676
|
+
const blend = 1 - Math.pow(1 - import_three35.MathUtils.clamp(this.dampingFactor, 0, 1), delta * 60);
|
|
13677
|
+
this._velocity.lerp(_targetVelocity, blend);
|
|
13678
|
+
if (_targetVelocity.lengthSq() === 0 && this._velocity.lengthSq() < MOVE_EPSILON) this._velocity.set(0, 0, 0);
|
|
13679
|
+
} else {
|
|
13680
|
+
this._velocity.copy(_targetVelocity);
|
|
13681
|
+
}
|
|
13682
|
+
camera.position.addScaledVector(this._velocity, delta);
|
|
13683
|
+
}
|
|
13684
|
+
notifyChange() {
|
|
13685
|
+
const camera = this.object;
|
|
13686
|
+
if (this._lastPosition.distanceToSquared(camera.position) > MOVE_EPSILON || 8 * (1 - this._lastQuaternion.dot(camera.quaternion)) > MOVE_EPSILON) {
|
|
13687
|
+
this._lastPosition.copy(camera.position);
|
|
13688
|
+
this._lastQuaternion.copy(camera.quaternion);
|
|
13689
|
+
this.dispatchEvent({ type: "change" });
|
|
13690
|
+
}
|
|
13691
|
+
}
|
|
13692
|
+
releaseKeys() {
|
|
13693
|
+
this._pressed.clear();
|
|
13694
|
+
}
|
|
13695
|
+
handleKey(event, down) {
|
|
13696
|
+
const action = this.actionFor(event.code);
|
|
13697
|
+
if (!action) return;
|
|
13698
|
+
const ownsInput = this.enabled && (this._locked || event.target === this.domElement);
|
|
13699
|
+
if (down && !ownsInput) return;
|
|
13700
|
+
const pressed = this._pressed.has(action);
|
|
13701
|
+
if (down) this._pressed.add(action);
|
|
13702
|
+
else this._pressed.delete(action);
|
|
13703
|
+
if (ownsInput || this.enabled && pressed) event.preventDefault();
|
|
13704
|
+
}
|
|
13705
|
+
actionFor(code) {
|
|
13706
|
+
for (const action in this.keys) {
|
|
13707
|
+
if (this.keys[action].includes(code)) return action;
|
|
13708
|
+
}
|
|
13709
|
+
return void 0;
|
|
13710
|
+
}
|
|
13711
|
+
handlePointerDown(event) {
|
|
13712
|
+
const element = this.domElement;
|
|
13713
|
+
if (!this.enabled || !element) return;
|
|
13714
|
+
element.focus?.({ preventScroll: true });
|
|
13715
|
+
if (this._locked) return;
|
|
13716
|
+
if (event.pointerType === "touch" && !this._joystick && this.onJoystickSide(event)) {
|
|
13717
|
+
this._joystick = { id: event.pointerId, originX: event.clientX, originY: event.clientY, x: event.clientX, y: event.clientY };
|
|
13718
|
+
element.setPointerCapture?.(event.pointerId);
|
|
13719
|
+
return;
|
|
13720
|
+
}
|
|
13721
|
+
if (this._dragPointer !== void 0) return;
|
|
13722
|
+
if (event.pointerType === "mouse" && event.button !== 0 && event.button !== 2) return;
|
|
13723
|
+
this._dragPointer = event.pointerId;
|
|
13724
|
+
this._dragMoved = false;
|
|
13725
|
+
element.setPointerCapture?.(event.pointerId);
|
|
13726
|
+
}
|
|
13727
|
+
onJoystickSide(event) {
|
|
13728
|
+
const rect = this.domElement?.getBoundingClientRect?.();
|
|
13729
|
+
return !!rect && event.clientX < rect.left + rect.width / 2;
|
|
13730
|
+
}
|
|
13731
|
+
handlePointerMove(event) {
|
|
13732
|
+
if (!this.enabled) return;
|
|
13733
|
+
const joystick = this._joystick;
|
|
13734
|
+
if (joystick && event.pointerId === joystick.id) {
|
|
13735
|
+
joystick.x = event.clientX;
|
|
13736
|
+
joystick.y = event.clientY;
|
|
13737
|
+
return;
|
|
13738
|
+
}
|
|
13739
|
+
if (!this._locked && event.pointerId !== this._dragPointer) return;
|
|
13740
|
+
const dx = event.movementX ?? 0;
|
|
13741
|
+
const dy = event.movementY ?? 0;
|
|
13742
|
+
if (!dx && !dy) return;
|
|
13743
|
+
this._dragMoved = true;
|
|
13744
|
+
this.turn(dx, dy);
|
|
13745
|
+
}
|
|
13746
|
+
handlePointerUp(event) {
|
|
13747
|
+
if (this._joystick?.id === event.pointerId) {
|
|
13748
|
+
this._joystick = void 0;
|
|
13749
|
+
this.domElement?.releasePointerCapture?.(event.pointerId);
|
|
13750
|
+
return;
|
|
13751
|
+
}
|
|
13752
|
+
if (event.pointerId !== this._dragPointer) return;
|
|
13753
|
+
this._dragPointer = void 0;
|
|
13754
|
+
this.domElement?.releasePointerCapture?.(event.pointerId);
|
|
13755
|
+
if (this.enabled && this.pointerLock && !this._dragMoved && event.pointerType === "mouse" && event.button === 0) {
|
|
13756
|
+
this.lock();
|
|
13757
|
+
}
|
|
13758
|
+
}
|
|
13759
|
+
handleWheel(event) {
|
|
13760
|
+
if (!this.enabled || !this.enableWheelSpeed) return;
|
|
13761
|
+
event.preventDefault();
|
|
13762
|
+
const steps = event.deltaMode === 0 ? event.deltaY / 100 : event.deltaY;
|
|
13763
|
+
const [min, max] = this.speedRange;
|
|
13764
|
+
this.movementSpeed = import_three35.MathUtils.clamp(this.movementSpeed * Math.pow(1.15, -steps), Math.min(min, max), Math.max(min, max));
|
|
13765
|
+
}
|
|
13766
|
+
handlePointerLockChange() {
|
|
13767
|
+
const document2 = this.domElement?.ownerDocument;
|
|
13768
|
+
const locked = !!document2 && document2.pointerLockElement === this.domElement;
|
|
13769
|
+
if (locked === this._locked) return;
|
|
13770
|
+
this._locked = locked;
|
|
13771
|
+
if (!locked) this.releaseKeys();
|
|
13772
|
+
this.dispatchEvent({ type: locked ? "lock" : "unlock" });
|
|
13773
|
+
}
|
|
13774
|
+
turn(dx, dy) {
|
|
13775
|
+
_euler.setFromQuaternion(this.object.quaternion);
|
|
13776
|
+
_euler.y -= dx * this.lookSpeed;
|
|
13777
|
+
_euler.x = import_three35.MathUtils.clamp(_euler.x - dy * this.lookSpeed, -PITCH_LIMIT, PITCH_LIMIT);
|
|
13778
|
+
_euler.z = 0;
|
|
13779
|
+
this.object.quaternion.setFromEuler(_euler);
|
|
13780
|
+
this.notifyChange();
|
|
13781
|
+
}
|
|
13782
|
+
};
|
|
13783
|
+
function isFlyControls(obj) {
|
|
13784
|
+
return obj?.isFlyControls === true;
|
|
13785
|
+
}
|
|
13786
|
+
|
|
13787
|
+
// src/renderer/MineRenderScene.ts
|
|
13788
|
+
var import_three36 = require("three");
|
|
13324
13789
|
init_SceneObject();
|
|
13325
13790
|
var import_ts_deepmerge8 = __toESM(require_dist());
|
|
13326
13791
|
init_ModelObject();
|
|
@@ -14230,7 +14695,7 @@ var SkinObject = class extends SceneObject {
|
|
|
14230
14695
|
// src/renderer/MineRenderScene.ts
|
|
14231
14696
|
init_EntityObject();
|
|
14232
14697
|
init_ItemTints();
|
|
14233
|
-
var MineRenderScene = class _MineRenderScene extends
|
|
14698
|
+
var MineRenderScene = class _MineRenderScene extends import_three36.Scene {
|
|
14234
14699
|
constructor(options) {
|
|
14235
14700
|
super();
|
|
14236
14701
|
this.isMineRenderScene = true;
|
|
@@ -14386,7 +14851,7 @@ function isMineRenderScene(obj) {
|
|
|
14386
14851
|
}
|
|
14387
14852
|
|
|
14388
14853
|
// src/renderer/Renderer.ts
|
|
14389
|
-
var
|
|
14854
|
+
var import_three38 = require("three");
|
|
14390
14855
|
var import_ts_deepmerge9 = __toESM(require_dist());
|
|
14391
14856
|
var import_stats = __toESM(require("stats.js"));
|
|
14392
14857
|
var import_postprocessing = require("postprocessing");
|
|
@@ -14395,11 +14860,11 @@ init_Model();
|
|
|
14395
14860
|
init_three();
|
|
14396
14861
|
|
|
14397
14862
|
// src/three/OrbitControls.js
|
|
14398
|
-
var
|
|
14863
|
+
var import_three37 = require("three");
|
|
14399
14864
|
var _changeEvent = { type: "change" };
|
|
14400
14865
|
var _startEvent = { type: "start" };
|
|
14401
14866
|
var _endEvent = { type: "end" };
|
|
14402
|
-
var OrbitControls = class extends
|
|
14867
|
+
var OrbitControls = class extends import_three37.EventDispatcher {
|
|
14403
14868
|
constructor(object4, domElement) {
|
|
14404
14869
|
super();
|
|
14405
14870
|
if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
|
|
@@ -14408,7 +14873,7 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14408
14873
|
this.domElement = domElement;
|
|
14409
14874
|
this.domElement.style.touchAction = "none";
|
|
14410
14875
|
this.enabled = true;
|
|
14411
|
-
this.target = new
|
|
14876
|
+
this.target = new import_three37.Vector3();
|
|
14412
14877
|
this.minDistance = 0;
|
|
14413
14878
|
this.maxDistance = Infinity;
|
|
14414
14879
|
this.minZoom = 0;
|
|
@@ -14430,8 +14895,8 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14430
14895
|
this.autoRotate = false;
|
|
14431
14896
|
this.autoRotateSpeed = 2;
|
|
14432
14897
|
this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
|
|
14433
|
-
this.mouseButtons = { LEFT:
|
|
14434
|
-
this.touches = { ONE:
|
|
14898
|
+
this.mouseButtons = { LEFT: import_three37.MOUSE.ROTATE, MIDDLE: import_three37.MOUSE.DOLLY, RIGHT: import_three37.MOUSE.PAN };
|
|
14899
|
+
this.touches = { ONE: import_three37.TOUCH.ROTATE, TWO: import_three37.TOUCH.DOLLY_PAN };
|
|
14435
14900
|
this.target0 = this.target.clone();
|
|
14436
14901
|
this.position0 = this.object.position.clone();
|
|
14437
14902
|
this.zoom0 = this.object.zoom;
|
|
@@ -14460,11 +14925,11 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14460
14925
|
state = STATE.NONE;
|
|
14461
14926
|
};
|
|
14462
14927
|
this.update = function() {
|
|
14463
|
-
const offset = new
|
|
14464
|
-
const quat = new
|
|
14928
|
+
const offset = new import_three37.Vector3();
|
|
14929
|
+
const quat = new import_three37.Quaternion().setFromUnitVectors(object4.up, new import_three37.Vector3(0, 1, 0));
|
|
14465
14930
|
const quatInverse = quat.clone().invert();
|
|
14466
|
-
const lastPosition = new
|
|
14467
|
-
const lastQuaternion = new
|
|
14931
|
+
const lastPosition = new import_three37.Vector3();
|
|
14932
|
+
const lastQuaternion = new import_three37.Quaternion();
|
|
14468
14933
|
const twoPI = 2 * Math.PI;
|
|
14469
14934
|
return function update() {
|
|
14470
14935
|
const position = scope.object.position;
|
|
@@ -14550,20 +15015,20 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14550
15015
|
};
|
|
14551
15016
|
let state = STATE.NONE;
|
|
14552
15017
|
const EPS = 1e-6;
|
|
14553
|
-
const spherical = new
|
|
14554
|
-
const sphericalDelta = new
|
|
15018
|
+
const spherical = new import_three37.Spherical();
|
|
15019
|
+
const sphericalDelta = new import_three37.Spherical();
|
|
14555
15020
|
let scale = 1;
|
|
14556
|
-
const panOffset = new
|
|
15021
|
+
const panOffset = new import_three37.Vector3();
|
|
14557
15022
|
let zoomChanged = false;
|
|
14558
|
-
const rotateStart = new
|
|
14559
|
-
const rotateEnd = new
|
|
14560
|
-
const rotateDelta = new
|
|
14561
|
-
const panStart = new
|
|
14562
|
-
const panEnd = new
|
|
14563
|
-
const panDelta = new
|
|
14564
|
-
const dollyStart = new
|
|
14565
|
-
const dollyEnd = new
|
|
14566
|
-
const dollyDelta = new
|
|
15023
|
+
const rotateStart = new import_three37.Vector2();
|
|
15024
|
+
const rotateEnd = new import_three37.Vector2();
|
|
15025
|
+
const rotateDelta = new import_three37.Vector2();
|
|
15026
|
+
const panStart = new import_three37.Vector2();
|
|
15027
|
+
const panEnd = new import_three37.Vector2();
|
|
15028
|
+
const panDelta = new import_three37.Vector2();
|
|
15029
|
+
const dollyStart = new import_three37.Vector2();
|
|
15030
|
+
const dollyEnd = new import_three37.Vector2();
|
|
15031
|
+
const dollyDelta = new import_three37.Vector2();
|
|
14567
15032
|
const pointers = [];
|
|
14568
15033
|
const pointerPositions = {};
|
|
14569
15034
|
function getAutoRotationAngle() {
|
|
@@ -14579,7 +15044,7 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14579
15044
|
sphericalDelta.phi -= angle;
|
|
14580
15045
|
}
|
|
14581
15046
|
const panLeft = function() {
|
|
14582
|
-
const v = new
|
|
15047
|
+
const v = new import_three37.Vector3();
|
|
14583
15048
|
return function panLeft2(distance, objectMatrix) {
|
|
14584
15049
|
v.setFromMatrixColumn(objectMatrix, 0);
|
|
14585
15050
|
v.multiplyScalar(-distance);
|
|
@@ -14587,7 +15052,7 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14587
15052
|
};
|
|
14588
15053
|
}();
|
|
14589
15054
|
const panUp = function() {
|
|
14590
|
-
const v = new
|
|
15055
|
+
const v = new import_three37.Vector3();
|
|
14591
15056
|
return function panUp2(distance, objectMatrix) {
|
|
14592
15057
|
if (scope.screenSpacePanning === true) {
|
|
14593
15058
|
v.setFromMatrixColumn(objectMatrix, 1);
|
|
@@ -14600,7 +15065,7 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14600
15065
|
};
|
|
14601
15066
|
}();
|
|
14602
15067
|
const pan = function() {
|
|
14603
|
-
const offset = new
|
|
15068
|
+
const offset = new import_three37.Vector3();
|
|
14604
15069
|
return function pan2(deltaX, deltaY) {
|
|
14605
15070
|
const element = scope.domElement;
|
|
14606
15071
|
if (scope.object.isPerspectiveCamera) {
|
|
@@ -14849,12 +15314,12 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14849
15314
|
mouseAction = -1;
|
|
14850
15315
|
}
|
|
14851
15316
|
switch (mouseAction) {
|
|
14852
|
-
case
|
|
15317
|
+
case import_three37.MOUSE.DOLLY:
|
|
14853
15318
|
if (scope.enableZoom === false) return;
|
|
14854
15319
|
handleMouseDownDolly(event);
|
|
14855
15320
|
state = STATE.DOLLY;
|
|
14856
15321
|
break;
|
|
14857
|
-
case
|
|
15322
|
+
case import_three37.MOUSE.ROTATE:
|
|
14858
15323
|
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
14859
15324
|
if (scope.enablePan === false) return;
|
|
14860
15325
|
handleMouseDownPan(event);
|
|
@@ -14865,7 +15330,7 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14865
15330
|
state = STATE.ROTATE;
|
|
14866
15331
|
}
|
|
14867
15332
|
break;
|
|
14868
|
-
case
|
|
15333
|
+
case import_three37.MOUSE.PAN:
|
|
14869
15334
|
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
14870
15335
|
if (scope.enableRotate === false) return;
|
|
14871
15336
|
handleMouseDownRotate(event);
|
|
@@ -14921,12 +15386,12 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14921
15386
|
switch (pointers.length) {
|
|
14922
15387
|
case 1:
|
|
14923
15388
|
switch (scope.touches.ONE) {
|
|
14924
|
-
case
|
|
15389
|
+
case import_three37.TOUCH.ROTATE:
|
|
14925
15390
|
if (scope.enableRotate === false) return;
|
|
14926
15391
|
handleTouchStartRotate();
|
|
14927
15392
|
state = STATE.TOUCH_ROTATE;
|
|
14928
15393
|
break;
|
|
14929
|
-
case
|
|
15394
|
+
case import_three37.TOUCH.PAN:
|
|
14930
15395
|
if (scope.enablePan === false) return;
|
|
14931
15396
|
handleTouchStartPan();
|
|
14932
15397
|
state = STATE.TOUCH_PAN;
|
|
@@ -14937,12 +15402,12 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
14937
15402
|
break;
|
|
14938
15403
|
case 2:
|
|
14939
15404
|
switch (scope.touches.TWO) {
|
|
14940
|
-
case
|
|
15405
|
+
case import_three37.TOUCH.DOLLY_PAN:
|
|
14941
15406
|
if (scope.enableZoom === false && scope.enablePan === false) return;
|
|
14942
15407
|
handleTouchStartDollyPan();
|
|
14943
15408
|
state = STATE.TOUCH_DOLLY_PAN;
|
|
14944
15409
|
break;
|
|
14945
|
-
case
|
|
15410
|
+
case import_three37.TOUCH.DOLLY_ROTATE:
|
|
14946
15411
|
if (scope.enableZoom === false && scope.enableRotate === false) return;
|
|
14947
15412
|
handleTouchStartDollyRotate();
|
|
14948
15413
|
state = STATE.TOUCH_DOLLY_ROTATE;
|
|
@@ -15009,7 +15474,7 @@ var OrbitControls = class extends import_three36.EventDispatcher {
|
|
|
15009
15474
|
function trackPointer(event) {
|
|
15010
15475
|
let position = pointerPositions[event.pointerId];
|
|
15011
15476
|
if (position === void 0) {
|
|
15012
|
-
position = new
|
|
15477
|
+
position = new import_three37.Vector2();
|
|
15013
15478
|
pointerPositions[event.pointerId] = position;
|
|
15014
15479
|
}
|
|
15015
15480
|
position.set(event.pageX, event.pageY);
|
|
@@ -15029,10 +15494,10 @@ var MapControls = class extends OrbitControls {
|
|
|
15029
15494
|
constructor(object4, domElement) {
|
|
15030
15495
|
super(object4, domElement);
|
|
15031
15496
|
this.screenSpacePanning = false;
|
|
15032
|
-
this.mouseButtons.LEFT =
|
|
15033
|
-
this.mouseButtons.RIGHT =
|
|
15034
|
-
this.touches.ONE =
|
|
15035
|
-
this.touches.TWO =
|
|
15497
|
+
this.mouseButtons.LEFT = import_three37.MOUSE.PAN;
|
|
15498
|
+
this.mouseButtons.RIGHT = import_three37.MOUSE.ROTATE;
|
|
15499
|
+
this.touches.ONE = import_three37.TOUCH.PAN;
|
|
15500
|
+
this.touches.TWO = import_three37.TOUCH.DOLLY_ROTATE;
|
|
15036
15501
|
}
|
|
15037
15502
|
};
|
|
15038
15503
|
|
|
@@ -15111,8 +15576,8 @@ var Renderer = class _Renderer {
|
|
|
15111
15576
|
top: void 0,
|
|
15112
15577
|
bottom: void 0
|
|
15113
15578
|
},
|
|
15114
|
-
position: new
|
|
15115
|
-
lookingAt: new
|
|
15579
|
+
position: new import_three38.Vector3(50, 50, 50),
|
|
15580
|
+
lookingAt: new import_three38.Vector3(0, 0, 0)
|
|
15116
15581
|
},
|
|
15117
15582
|
render: {
|
|
15118
15583
|
fpsLimit: 60,
|
|
@@ -15127,7 +15592,8 @@ var Renderer = class _Renderer {
|
|
|
15127
15592
|
enabled: true
|
|
15128
15593
|
},
|
|
15129
15594
|
controls: {
|
|
15130
|
-
enabled: false
|
|
15595
|
+
enabled: false,
|
|
15596
|
+
mode: "orbit"
|
|
15131
15597
|
},
|
|
15132
15598
|
debug: {
|
|
15133
15599
|
grid: false,
|
|
@@ -15143,14 +15609,14 @@ var Renderer = class _Renderer {
|
|
|
15143
15609
|
switch (this.options.camera.type) {
|
|
15144
15610
|
case "perspective":
|
|
15145
15611
|
default:
|
|
15146
|
-
return new
|
|
15612
|
+
return new import_three38.PerspectiveCamera(
|
|
15147
15613
|
this.options.camera.perspective.fov,
|
|
15148
15614
|
this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
|
|
15149
15615
|
this.options.camera.near,
|
|
15150
15616
|
this.options.camera.far
|
|
15151
15617
|
);
|
|
15152
15618
|
case "orthographic":
|
|
15153
|
-
return new
|
|
15619
|
+
return new import_three38.OrthographicCamera(
|
|
15154
15620
|
this.options.camera.orthographic.left ?? this.viewWidth / -2,
|
|
15155
15621
|
this.options.camera.orthographic.right ?? this.viewWidth / 2,
|
|
15156
15622
|
this.options.camera.orthographic.top ?? this.viewHeight / 2,
|
|
@@ -15166,7 +15632,7 @@ var Renderer = class _Renderer {
|
|
|
15166
15632
|
}
|
|
15167
15633
|
const pixelRatio = this.options.render.pixelRatio ?? 1;
|
|
15168
15634
|
this._surface?.resize?.(Math.floor(this.viewWidth * pixelRatio), Math.floor(this.viewHeight * pixelRatio));
|
|
15169
|
-
const renderer = new
|
|
15635
|
+
const renderer = new import_three38.WebGLRenderer({
|
|
15170
15636
|
canvas: this._surface?.canvas,
|
|
15171
15637
|
context: this._surface?.context,
|
|
15172
15638
|
antialias: this.options.render.antialias,
|
|
@@ -15176,8 +15642,8 @@ var Renderer = class _Renderer {
|
|
|
15176
15642
|
});
|
|
15177
15643
|
renderer.setClearColor(0, 0);
|
|
15178
15644
|
renderer.shadowMap.enabled = true;
|
|
15179
|
-
renderer.shadowMap.type =
|
|
15180
|
-
renderer.outputColorSpace =
|
|
15645
|
+
renderer.shadowMap.type = import_three38.PCFShadowMap;
|
|
15646
|
+
renderer.outputColorSpace = import_three38.SRGBColorSpace;
|
|
15181
15647
|
if (this._surface) {
|
|
15182
15648
|
renderer.setDrawingBufferSize(this.viewWidth, this.viewHeight, pixelRatio);
|
|
15183
15649
|
} else {
|
|
@@ -15195,20 +15661,77 @@ var Renderer = class _Renderer {
|
|
|
15195
15661
|
}
|
|
15196
15662
|
createControls() {
|
|
15197
15663
|
if (!this.options.controls?.enabled) return void 0;
|
|
15198
|
-
|
|
15199
|
-
|
|
15200
|
-
|
|
15664
|
+
return this.createControlsFor(this.options.controls.mode ?? "orbit", this.initialTarget());
|
|
15665
|
+
}
|
|
15666
|
+
initialTarget() {
|
|
15201
15667
|
const target = this.options.camera.lookingAt;
|
|
15202
|
-
if (isVector3(target))
|
|
15668
|
+
if (isVector3(target)) return target.clone();
|
|
15669
|
+
if (isTripleArray(target)) return new import_three38.Vector3(target[0], target[1], target[2]);
|
|
15670
|
+
return new import_three38.Vector3();
|
|
15671
|
+
}
|
|
15672
|
+
createControlsFor(mode, target) {
|
|
15673
|
+
let controls;
|
|
15674
|
+
if (mode === "fly") {
|
|
15675
|
+
controls = new FlyControls(this.camera, this.renderer.domElement);
|
|
15676
|
+
controls.lookAt(target);
|
|
15677
|
+
controls.saveState();
|
|
15678
|
+
} else {
|
|
15679
|
+
const position = this.camera.position.clone();
|
|
15680
|
+
controls = new OrbitControls(this.camera, this.renderer.domElement);
|
|
15681
|
+
this.camera.position.copy(position);
|
|
15203
15682
|
controls.target.copy(target);
|
|
15204
|
-
|
|
15205
|
-
controls.
|
|
15683
|
+
controls.update();
|
|
15684
|
+
controls.saveState();
|
|
15206
15685
|
}
|
|
15207
|
-
|
|
15208
|
-
controls.saveState();
|
|
15686
|
+
this._controlsTime = void 0;
|
|
15209
15687
|
this.registerEventDispatcher(controls);
|
|
15210
15688
|
return controls;
|
|
15211
15689
|
}
|
|
15690
|
+
/**
|
|
15691
|
+
* Replaces renderer-owned controls with the selected mode, keeping the camera where it is.
|
|
15692
|
+
* Switching to orbit controls targets the point the camera looks at, at the previous orbit distance.
|
|
15693
|
+
* Returns the new controls, or undefined when controls were disabled at construction or after disposal.
|
|
15694
|
+
*/
|
|
15695
|
+
setControlsMode(mode) {
|
|
15696
|
+
const current = this._controls;
|
|
15697
|
+
if (this._disposed || !current) return void 0;
|
|
15698
|
+
if (this.controlsMode === mode) return current;
|
|
15699
|
+
let target;
|
|
15700
|
+
if (isFlyControls(current)) {
|
|
15701
|
+
const distance = this._orbitDistance ?? (this.camera.position.distanceTo(this.initialTarget()) || 1);
|
|
15702
|
+
target = new import_three38.Vector3(0, 0, -distance).applyQuaternion(this.camera.quaternion).add(this.camera.position);
|
|
15703
|
+
} else {
|
|
15704
|
+
target = current.target.clone();
|
|
15705
|
+
this._orbitDistance = this.camera.position.distanceTo(target);
|
|
15706
|
+
}
|
|
15707
|
+
const enabled = current.enabled;
|
|
15708
|
+
this.disposeControls(current);
|
|
15709
|
+
this._controls = this.createControlsFor(mode, target);
|
|
15710
|
+
this._controls.enabled = enabled;
|
|
15711
|
+
this.dirty = true;
|
|
15712
|
+
return this._controls;
|
|
15713
|
+
}
|
|
15714
|
+
disposeControls(controls) {
|
|
15715
|
+
this._controls = void 0;
|
|
15716
|
+
this.unregisterEventDispatcher(controls);
|
|
15717
|
+
controls.enabled = false;
|
|
15718
|
+
controls.dispose();
|
|
15719
|
+
}
|
|
15720
|
+
/** Advances owned controls; without a frame time, flight movement does not progress. */
|
|
15721
|
+
updateControls(time) {
|
|
15722
|
+
const controls = this._controls;
|
|
15723
|
+
if (!controls?.enabled) {
|
|
15724
|
+
this._controlsTime = void 0;
|
|
15725
|
+
return;
|
|
15726
|
+
}
|
|
15727
|
+
if (!isFlyControls(controls)) {
|
|
15728
|
+
controls.update();
|
|
15729
|
+
return;
|
|
15730
|
+
}
|
|
15731
|
+
const previous = this._controlsTime;
|
|
15732
|
+
if (time !== void 0) this._controlsTime = time;
|
|
15733
|
+
controls.update(time === void 0 || previous === void 0 ? 0 : (time - previous) / 1e3);
|
|
15734
|
+
}
|
|
15212
15735
|
//</editor-fold>
|
|
15213
15736
|
init() {
|
|
15214
15737
|
if (this._disposed) return;
|
|
@@ -15216,20 +15739,20 @@ var Renderer = class _Renderer {
|
|
|
15216
15739
|
window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
|
|
15217
15740
|
}
|
|
15218
15741
|
if (this.options.debug.grid) {
|
|
15219
|
-
const gridHelper = new
|
|
15742
|
+
const gridHelper = new import_three38.GridHelper(128, 16);
|
|
15220
15743
|
this._debugHelpers.push(gridHelper);
|
|
15221
15744
|
this.scene.add(gridHelper);
|
|
15222
|
-
const gridHelper2 = new
|
|
15745
|
+
const gridHelper2 = new import_three38.GridHelper(128, 16);
|
|
15223
15746
|
this._debugHelpers.push(gridHelper2);
|
|
15224
15747
|
gridHelper2.rotation.x = 90 * (Math.PI / 180);
|
|
15225
15748
|
this.scene.add(gridHelper2);
|
|
15226
|
-
const gridHelper3 = new
|
|
15749
|
+
const gridHelper3 = new import_three38.GridHelper(128, 16);
|
|
15227
15750
|
this._debugHelpers.push(gridHelper3);
|
|
15228
15751
|
gridHelper3.rotation.z = 90 * (Math.PI / 180);
|
|
15229
15752
|
this.scene.add(gridHelper3);
|
|
15230
15753
|
}
|
|
15231
15754
|
if (this.options.debug.axes) {
|
|
15232
|
-
const axesHelper = new
|
|
15755
|
+
const axesHelper = new import_three38.AxesHelper(64);
|
|
15233
15756
|
this._debugHelpers.push(axesHelper);
|
|
15234
15757
|
this.scene.add(axesHelper);
|
|
15235
15758
|
}
|
|
@@ -15285,6 +15808,12 @@ var Renderer = class _Renderer {
|
|
|
15285
15808
|
events.add(changeEvent2);
|
|
15286
15809
|
dispatcher.addEventListener(changeEvent2, this._changeListener);
|
|
15287
15810
|
}
|
|
15811
|
+
unregisterEventDispatcher(dispatcher) {
|
|
15812
|
+
const events = this._eventDispatchers.get(dispatcher);
|
|
15813
|
+
if (!events) return;
|
|
15814
|
+
for (const event of events) dispatcher.removeEventListener(event, this._changeListener);
|
|
15815
|
+
this._eventDispatchers.delete(dispatcher);
|
|
15816
|
+
}
|
|
15288
15817
|
/** Updates the camera and canvas size. Width and height are in CSS pixels. */
|
|
15289
15818
|
resize(width, height) {
|
|
15290
15819
|
if (this._disposed) return;
|
|
@@ -15361,6 +15890,7 @@ var Renderer = class _Renderer {
|
|
|
15361
15890
|
this.renderer.setAnimationLoop(null);
|
|
15362
15891
|
}
|
|
15363
15892
|
this._nextFrameTime = void 0;
|
|
15893
|
+
this._controlsTime = void 0;
|
|
15364
15894
|
for (const subscription of this._frameCallbacks.values()) subscription.previous = void 0;
|
|
15365
15895
|
}
|
|
15366
15896
|
/**
|
|
@@ -15390,10 +15920,7 @@ var Renderer = class _Renderer {
|
|
|
15390
15920
|
}
|
|
15391
15921
|
this._element = void 0;
|
|
15392
15922
|
if (this._controls) {
|
|
15393
|
-
|
|
15394
|
-
this._controls = void 0;
|
|
15395
|
-
controls.enabled = false;
|
|
15396
|
-
controls.dispose();
|
|
15923
|
+
this.disposeControls(this._controls);
|
|
15397
15924
|
}
|
|
15398
15925
|
this.scene.clear();
|
|
15399
15926
|
for (const helper of this._debugHelpers) {
|
|
@@ -15410,9 +15937,7 @@ var Renderer = class _Renderer {
|
|
|
15410
15937
|
}
|
|
15411
15938
|
animate(t = performance.now()) {
|
|
15412
15939
|
if (!this._running) return;
|
|
15413
|
-
|
|
15414
|
-
this._controls.update();
|
|
15415
|
-
}
|
|
15940
|
+
this.updateControls(t);
|
|
15416
15941
|
if (!this._running) return;
|
|
15417
15942
|
if (!this.dirty && !this.options.render.renderAlways && !this._frameCallbacks.size && !this._videoExporter) return;
|
|
15418
15943
|
const interval = this._frameInterval;
|
|
@@ -15449,7 +15974,7 @@ var Renderer = class _Renderer {
|
|
|
15449
15974
|
/** Draws a fresh frame without starting the animation loop or invoking frame callbacks. */
|
|
15450
15975
|
renderOnce() {
|
|
15451
15976
|
if (this._disposed) throw new Error("Cannot render a disposed renderer");
|
|
15452
|
-
|
|
15977
|
+
this.updateControls();
|
|
15453
15978
|
this.drawFrame();
|
|
15454
15979
|
}
|
|
15455
15980
|
/**
|
|
@@ -15479,7 +16004,7 @@ var Renderer = class _Renderer {
|
|
|
15479
16004
|
try {
|
|
15480
16005
|
if (!wasRunning) this.start();
|
|
15481
16006
|
this._videoExporter = exporter;
|
|
15482
|
-
|
|
16007
|
+
this.updateControls();
|
|
15483
16008
|
this.drawFrame();
|
|
15484
16009
|
} catch (error) {
|
|
15485
16010
|
exporter.cancel(error);
|
|
@@ -15530,6 +16055,19 @@ var Renderer = class _Renderer {
|
|
|
15530
16055
|
get controls() {
|
|
15531
16056
|
return this._controls;
|
|
15532
16057
|
}
|
|
16058
|
+
/** Renderer-owned OrbitControls, or undefined in fly mode or without controls. */
|
|
16059
|
+
get orbitControls() {
|
|
16060
|
+
return this._controls && !isFlyControls(this._controls) ? this._controls : void 0;
|
|
16061
|
+
}
|
|
16062
|
+
/** Renderer-owned {@link FlyControls}, or undefined in orbit mode or without controls. */
|
|
16063
|
+
get flyControls() {
|
|
16064
|
+
return isFlyControls(this._controls) ? this._controls : void 0;
|
|
16065
|
+
}
|
|
16066
|
+
/** The active renderer-owned controls mode, or undefined without controls. */
|
|
16067
|
+
get controlsMode() {
|
|
16068
|
+
if (!this._controls) return void 0;
|
|
16069
|
+
return isFlyControls(this._controls) ? "fly" : "orbit";
|
|
16070
|
+
}
|
|
15533
16071
|
///
|
|
15534
16072
|
};
|
|
15535
16073
|
|
|
@@ -15778,7 +16316,7 @@ function parseSceneDocument(value) {
|
|
|
15778
16316
|
}
|
|
15779
16317
|
|
|
15780
16318
|
// src/scene/SceneDocumentLoader.ts
|
|
15781
|
-
var
|
|
16319
|
+
var import_three40 = require("three");
|
|
15782
16320
|
init_AssetKey();
|
|
15783
16321
|
init_AssetLoader();
|
|
15784
16322
|
init_BlockStates();
|
|
@@ -15839,7 +16377,7 @@ var SceneDocumentLoader = class {
|
|
|
15839
16377
|
if (definition.minecraftVersion !== void 0 && definition.minecraftVersion !== AssetLoader.version) {
|
|
15840
16378
|
throw new Error(`Scene requires Minecraft ${definition.minecraftVersion}; call AssetLoader.setVersion("${definition.minecraftVersion}") before loading it`);
|
|
15841
16379
|
}
|
|
15842
|
-
const root = new
|
|
16380
|
+
const root = new import_three40.Group();
|
|
15843
16381
|
root.name = "MineRender scene document";
|
|
15844
16382
|
const objects = [];
|
|
15845
16383
|
let disposed = false;
|
|
@@ -15879,7 +16417,7 @@ var SceneDocumentLoader = class {
|
|
|
15879
16417
|
return this.loadValidatedObject(scene, definition, parent);
|
|
15880
16418
|
}
|
|
15881
16419
|
static async loadValidatedObject(scene, definition, parent) {
|
|
15882
|
-
const root = new
|
|
16420
|
+
const root = new import_three40.Group();
|
|
15883
16421
|
root.name = definition.name ?? definition.id;
|
|
15884
16422
|
root.userData.sceneObjectId = definition.id;
|
|
15885
16423
|
root.position.fromArray(definition.position ?? [0, 0, 0]);
|
|
@@ -16757,12 +17295,12 @@ var AnvilWorldSource = class {
|
|
|
16757
17295
|
};
|
|
16758
17296
|
|
|
16759
17297
|
// src/world/Chunk.ts
|
|
16760
|
-
var
|
|
17298
|
+
var import_three44 = require("three");
|
|
16761
17299
|
init_BlockStates();
|
|
16762
17300
|
init_AssetKey();
|
|
16763
17301
|
|
|
16764
17302
|
// src/world/MineRenderWorld.ts
|
|
16765
|
-
var
|
|
17303
|
+
var import_three42 = require("three");
|
|
16766
17304
|
init_Model();
|
|
16767
17305
|
init_util();
|
|
16768
17306
|
init_AssetKey();
|
|
@@ -16770,7 +17308,7 @@ init_BlockStates();
|
|
|
16770
17308
|
init_CubeFace();
|
|
16771
17309
|
|
|
16772
17310
|
// src/world/SectionModels.ts
|
|
16773
|
-
var
|
|
17311
|
+
var import_three41 = require("three");
|
|
16774
17312
|
init_AssetKey();
|
|
16775
17313
|
init_Models();
|
|
16776
17314
|
init_CubeFace();
|
|
@@ -16794,7 +17332,7 @@ function cached(map, key, load) {
|
|
|
16794
17332
|
}
|
|
16795
17333
|
function compactQuads(geometry, keep) {
|
|
16796
17334
|
const quads = keep.flatMap((kept, index) => kept ? [index] : []);
|
|
16797
|
-
const compact = new
|
|
17335
|
+
const compact = new import_three41.BufferGeometry();
|
|
16798
17336
|
for (const [name, size] of Object.entries({ position: 3, normal: 3, uv: 2, uvBounds: 4, color: 3 })) {
|
|
16799
17337
|
const source2 = geometry.getAttribute(name);
|
|
16800
17338
|
const defaults = name === "uvBounds" ? [0, 0, 1, 1] : name === "color" ? [1, 1, 1] : void 0;
|
|
@@ -16806,7 +17344,7 @@ function compactQuads(geometry, keep) {
|
|
|
16806
17344
|
}
|
|
16807
17345
|
}
|
|
16808
17346
|
}
|
|
16809
|
-
compact.setAttribute(name, new
|
|
17347
|
+
compact.setAttribute(name, new import_three41.BufferAttribute(values, size));
|
|
16810
17348
|
}
|
|
16811
17349
|
const source = geometry.getIndex();
|
|
16812
17350
|
const indices = [];
|
|
@@ -16827,24 +17365,48 @@ var SectionModels = class {
|
|
|
16827
17365
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("maxAtlasSize must be a positive integer");
|
|
16828
17366
|
}
|
|
16829
17367
|
/** Returns templates for the matched parts, or `undefined` when the block needs an individual render object. */
|
|
16830
|
-
async get(blockState3, properties = {}, position) {
|
|
16831
|
-
const
|
|
16832
|
-
|
|
17368
|
+
async get(blockState3, properties = {}, position, biome) {
|
|
17369
|
+
const biomePosition = position ? [...position] : void 0;
|
|
17370
|
+
const prepared = await this.state(blockState3, properties);
|
|
17371
|
+
if (!prepared) return void 0;
|
|
17372
|
+
return Promise.all(prepared.groups.map(async (group) => {
|
|
17373
|
+
const variant = BlockStateResolver.choose(group, biomePosition);
|
|
17374
|
+
const choice = prepared.choices.get(variant);
|
|
17375
|
+
const tints = await BlockTints.get(
|
|
17376
|
+
blockState3.key,
|
|
17377
|
+
prepared.state,
|
|
17378
|
+
choice.model,
|
|
17379
|
+
void 0,
|
|
17380
|
+
() => BlockTints.getBiomeColor(blockState3.key, biome, biomePosition)
|
|
17381
|
+
);
|
|
17382
|
+
return this.template(variant, choice, tints);
|
|
17383
|
+
}));
|
|
16833
17384
|
}
|
|
16834
|
-
/** Resolves section templates
|
|
16835
|
-
async prepareState(blockState3, properties = {}) {
|
|
17385
|
+
/** Resolves section templates for one tint palette, with a synchronous weighted choice for each cell. */
|
|
17386
|
+
async prepareState(blockState3, properties = {}, biomeColor) {
|
|
17387
|
+
const prepared = await this.state(blockState3, properties);
|
|
17388
|
+
if (!prepared) return void 0;
|
|
17389
|
+
let color2;
|
|
17390
|
+
const resolveColor = typeof biomeColor === "function" ? () => color2 ??= biomeColor() : biomeColor;
|
|
17391
|
+
const templates = /* @__PURE__ */ new Map();
|
|
17392
|
+
await Promise.all([...prepared.choices].map(async ([variant, choice]) => {
|
|
17393
|
+
const tints = await BlockTints.get(blockState3.key, prepared.state, choice.model, void 0, resolveColor);
|
|
17394
|
+
templates.set(variant, await this.template(variant, choice, tints));
|
|
17395
|
+
}));
|
|
17396
|
+
return { pick: (position) => prepared.groups.map((group) => templates.get(BlockStateResolver.choose(group, position))) };
|
|
17397
|
+
}
|
|
17398
|
+
async state(blockState3, properties) {
|
|
16836
17399
|
let states = this.states.get(blockState3);
|
|
16837
17400
|
if (!states) this.states.set(blockState3, states = /* @__PURE__ */ new Map());
|
|
16838
17401
|
const key = JSON.stringify(Object.entries(properties).sort(([a], [b]) => a.localeCompare(b)));
|
|
16839
|
-
|
|
16840
|
-
if (!prepared) return void 0;
|
|
16841
|
-
return { pick: (position) => prepared.groups.map((group) => prepared.templates.get(BlockStateResolver.choose(group, position))) };
|
|
17402
|
+
return cached(states, key, () => this.prepare(blockState3, properties));
|
|
16842
17403
|
}
|
|
16843
17404
|
/** Returns the shared still/flow atlas used by per-block fluid objects. */
|
|
16844
17405
|
fluidAtlas(kind, root) {
|
|
16845
|
-
|
|
17406
|
+
const key = new AssetKey("minecraft", kind, "models", "fluid", "assets", ".json", root);
|
|
17407
|
+
return cached(this.fluidAtlases, key.serialize(), async () => {
|
|
16846
17408
|
const atlas = await UVMapper.getAtlas({
|
|
16847
|
-
key
|
|
17409
|
+
key,
|
|
16848
17410
|
textures: { still: `minecraft:block/${kind}_still`, flow: `minecraft:block/${kind}_flow` },
|
|
16849
17411
|
elements: []
|
|
16850
17412
|
});
|
|
@@ -16856,64 +17418,67 @@ var SectionModels = class {
|
|
|
16856
17418
|
const state = { ...await BlockStateResolver.defaults(blockState3), ...properties };
|
|
16857
17419
|
const groups = BlockStateResolver.matching(blockState3, state);
|
|
16858
17420
|
if (!groups.length) return void 0;
|
|
16859
|
-
const
|
|
17421
|
+
const prepared = /* @__PURE__ */ new Map();
|
|
16860
17422
|
for (const group of groups) {
|
|
16861
17423
|
const choices = Array.isArray(group) ? group : [group];
|
|
16862
17424
|
if (!choices.length) return void 0;
|
|
16863
17425
|
for (const variant of choices) {
|
|
16864
17426
|
if (!variant.model) return void 0;
|
|
16865
|
-
const
|
|
17427
|
+
const modelKey = AssetKey.parse("models", variant.model);
|
|
17428
|
+
modelKey.root = blockState3.key?.root;
|
|
17429
|
+
const model = await Models.getMerged(modelKey);
|
|
16866
17430
|
if (!model?.elements?.length) return void 0;
|
|
16867
17431
|
const atlas = await UVMapper.getAtlas(model);
|
|
16868
17432
|
const rotation = BlockStateResolver.rotation(variant);
|
|
16869
17433
|
if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
|
|
16870
|
-
|
|
16871
|
-
let models = this.models.get(model);
|
|
16872
|
-
if (!models) this.models.set(model, models = /* @__PURE__ */ new Map());
|
|
16873
|
-
const key = JSON.stringify([rotation.x, rotation.y, rotation.z, variant.uvlock, tints]);
|
|
16874
|
-
const template = await cached(models, key, async () => {
|
|
16875
|
-
const object4 = new SectionModel(model, {
|
|
16876
|
-
instanceMeshes: false,
|
|
16877
|
-
mergeMeshes: true,
|
|
16878
|
-
tints,
|
|
16879
|
-
uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0
|
|
16880
|
-
});
|
|
16881
|
-
await object4.init();
|
|
16882
|
-
let geometry = object4.children[0].geometry;
|
|
16883
|
-
geometry.applyMatrix4(new import_three40.Matrix4().makeRotationFromEuler(rotation));
|
|
16884
|
-
object4.clear();
|
|
16885
|
-
const keep = [];
|
|
16886
|
-
const cullFaces = [];
|
|
16887
|
-
for (const element of atlas.model.elements) {
|
|
16888
|
-
for (const face of CUBE_FACES) {
|
|
16889
|
-
const data = element.faces[face];
|
|
16890
|
-
keep.push(data !== void 0);
|
|
16891
|
-
if (!data) continue;
|
|
16892
|
-
const local = CUBE_FACES.findIndex((name) => name === data.cullface);
|
|
16893
|
-
if (local < 0) {
|
|
16894
|
-
cullFaces.push(0);
|
|
16895
|
-
continue;
|
|
16896
|
-
}
|
|
16897
|
-
const normal = new import_three40.Vector3(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
|
|
16898
|
-
const world = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
|
|
16899
|
-
cullFaces.push(world < 0 ? 0 : 1 << world);
|
|
16900
|
-
}
|
|
16901
|
-
}
|
|
16902
|
-
geometry = compactQuads(geometry, keep);
|
|
16903
|
-
const template2 = {
|
|
16904
|
-
geometry,
|
|
16905
|
-
atlas,
|
|
16906
|
-
cullFaces: new Uint8Array(cullFaces),
|
|
16907
|
-
occludes: ModelCulling.isOpaqueFullCube(atlas) && ModelCulling.toLocalMask(63, rotation) === 63,
|
|
16908
|
-
layer: atlas.hasTranslucency ? 1 : 0
|
|
16909
|
-
};
|
|
16910
|
-
this.templates.add(template2);
|
|
16911
|
-
return template2;
|
|
16912
|
-
});
|
|
16913
|
-
templates.set(variant, template);
|
|
17434
|
+
prepared.set(variant, { model, atlas, rotation });
|
|
16914
17435
|
}
|
|
16915
17436
|
}
|
|
16916
|
-
return { groups,
|
|
17437
|
+
return { state, groups, choices: prepared };
|
|
17438
|
+
}
|
|
17439
|
+
async template(variant, { model, atlas, rotation }, tints) {
|
|
17440
|
+
let models = this.models.get(model);
|
|
17441
|
+
if (!models) this.models.set(model, models = /* @__PURE__ */ new Map());
|
|
17442
|
+
const key = JSON.stringify([rotation.x, rotation.y, rotation.z, variant.uvlock, tints]);
|
|
17443
|
+
return cached(models, key, async () => {
|
|
17444
|
+
const object4 = new SectionModel(model, {
|
|
17445
|
+
instanceMeshes: false,
|
|
17446
|
+
mergeMeshes: true,
|
|
17447
|
+
tints,
|
|
17448
|
+
uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0
|
|
17449
|
+
});
|
|
17450
|
+
await object4.init();
|
|
17451
|
+
let geometry = object4.children[0].geometry;
|
|
17452
|
+
geometry.applyMatrix4(new import_three41.Matrix4().makeRotationFromEuler(rotation));
|
|
17453
|
+
object4.clear();
|
|
17454
|
+
const keep = [];
|
|
17455
|
+
const cullFaces = [];
|
|
17456
|
+
for (const element of atlas.model.elements) {
|
|
17457
|
+
for (const face of CUBE_FACES) {
|
|
17458
|
+
const data = element.faces[face];
|
|
17459
|
+
keep.push(data !== void 0);
|
|
17460
|
+
if (!data) continue;
|
|
17461
|
+
const local = CUBE_FACES.findIndex((name) => name === data.cullface);
|
|
17462
|
+
if (local < 0) {
|
|
17463
|
+
cullFaces.push(0);
|
|
17464
|
+
continue;
|
|
17465
|
+
}
|
|
17466
|
+
const normal = new import_three41.Vector3(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
|
|
17467
|
+
const world = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
|
|
17468
|
+
cullFaces.push(world < 0 ? 0 : 1 << world);
|
|
17469
|
+
}
|
|
17470
|
+
}
|
|
17471
|
+
geometry = compactQuads(geometry, keep);
|
|
17472
|
+
const template = {
|
|
17473
|
+
geometry,
|
|
17474
|
+
atlas,
|
|
17475
|
+
cullFaces: new Uint8Array(cullFaces),
|
|
17476
|
+
occludes: ModelCulling.isOpaqueFullCube(atlas) && ModelCulling.toLocalMask(63, rotation) === 63,
|
|
17477
|
+
layer: atlas.hasTranslucency ? 1 : 0
|
|
17478
|
+
};
|
|
17479
|
+
this.templates.add(template);
|
|
17480
|
+
return template;
|
|
17481
|
+
});
|
|
16917
17482
|
}
|
|
16918
17483
|
/** Disposes prepared geometry and clears this world's template caches. */
|
|
16919
17484
|
clear() {
|
|
@@ -17090,17 +17655,17 @@ var MineRenderWorld = class {
|
|
|
17090
17655
|
}
|
|
17091
17656
|
getBlockAt(posOrX, y, z) {
|
|
17092
17657
|
if (typeof posOrX == "number") {
|
|
17093
|
-
return this.getBlockAt(new
|
|
17658
|
+
return this.getBlockAt(new import_three42.Vector3(posOrX, y, z));
|
|
17094
17659
|
}
|
|
17095
17660
|
if (isTripleArray(posOrX)) {
|
|
17096
|
-
return this.getBlockAt(new
|
|
17661
|
+
return this.getBlockAt(new import_three42.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
17097
17662
|
}
|
|
17098
17663
|
this.validatePosBounds(posOrX);
|
|
17099
17664
|
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
17100
17665
|
}
|
|
17101
17666
|
getBiomeAt(posOrX, y, z) {
|
|
17102
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
17103
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
17667
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new import_three42.Vector3(posOrX, y, z));
|
|
17668
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new import_three42.Vector3(...posOrX));
|
|
17104
17669
|
this.validatePosBounds(posOrX);
|
|
17105
17670
|
const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);
|
|
17106
17671
|
const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;
|
|
@@ -17108,10 +17673,10 @@ var MineRenderWorld = class {
|
|
|
17108
17673
|
}
|
|
17109
17674
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
17110
17675
|
if (typeof posOrX == "number") {
|
|
17111
|
-
return this.setBlockAt(new
|
|
17676
|
+
return this.setBlockAt(new import_three42.Vector3(posOrX, yOrBlock, z), block);
|
|
17112
17677
|
}
|
|
17113
17678
|
if (isTripleArray(posOrX)) {
|
|
17114
|
-
return this.setBlockAt(new
|
|
17679
|
+
return this.setBlockAt(new import_three42.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
17115
17680
|
}
|
|
17116
17681
|
return this.placeBlock(posOrX, yOrBlock);
|
|
17117
17682
|
}
|
|
@@ -17122,10 +17687,10 @@ var MineRenderWorld = class {
|
|
|
17122
17687
|
}
|
|
17123
17688
|
async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
|
|
17124
17689
|
if (typeof posOrX === "number") {
|
|
17125
|
-
return this.setBlockVisibleAt(new
|
|
17690
|
+
return this.setBlockVisibleAt(new import_three42.Vector3(posOrX, yOrVisible, z), visible);
|
|
17126
17691
|
}
|
|
17127
17692
|
if (isTripleArray(posOrX)) {
|
|
17128
|
-
return this.setBlockVisibleAt(new
|
|
17693
|
+
return this.setBlockVisibleAt(new import_three42.Vector3(...posOrX), yOrVisible);
|
|
17129
17694
|
}
|
|
17130
17695
|
this.validatePosBounds(posOrX);
|
|
17131
17696
|
await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
|
|
@@ -17151,7 +17716,7 @@ var MineRenderWorld = class {
|
|
|
17151
17716
|
const collect = async (positions2) => {
|
|
17152
17717
|
for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
|
|
17153
17718
|
};
|
|
17154
|
-
const place = (block) => this.placeBlock(new
|
|
17719
|
+
const place = (block) => this.placeBlock(new import_three42.Vector3(...block.position), block, collect);
|
|
17155
17720
|
const keys = /* @__PURE__ */ new Map();
|
|
17156
17721
|
const types = /* @__PURE__ */ new Set();
|
|
17157
17722
|
for (const block of multiblock.blocks) {
|
|
@@ -17167,7 +17732,7 @@ var MineRenderWorld = class {
|
|
|
17167
17732
|
}
|
|
17168
17733
|
if (!executor) {
|
|
17169
17734
|
const groups2 = /* @__PURE__ */ new Map();
|
|
17170
|
-
const position = new
|
|
17735
|
+
const position = new import_three42.Vector3();
|
|
17171
17736
|
for (const block of multiblock.blocks) {
|
|
17172
17737
|
const [x, y, z] = block.position;
|
|
17173
17738
|
this.validatePosBounds(position.set(x, y, z));
|
|
@@ -17207,7 +17772,7 @@ var MineRenderWorld = class {
|
|
|
17207
17772
|
try {
|
|
17208
17773
|
positions = await chunk.placeBlocks(blocks);
|
|
17209
17774
|
} finally {
|
|
17210
|
-
positions ??= blocks.map(({ index }) => new
|
|
17775
|
+
positions ??= blocks.map(({ index }) => new import_three42.Vector3(
|
|
17211
17776
|
chunk.x * 16 + index % 16,
|
|
17212
17777
|
chunk.y * 16 + Math.floor(index / 256),
|
|
17213
17778
|
chunk.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -17243,10 +17808,9 @@ var MineRenderWorld = class {
|
|
|
17243
17808
|
}
|
|
17244
17809
|
try {
|
|
17245
17810
|
await this.clearChunkColumn(chunk.x, chunk.z);
|
|
17246
|
-
let sliceStart = performance.now();
|
|
17247
17811
|
for (const section of chunk.sections) {
|
|
17248
17812
|
if (section.biomes) {
|
|
17249
|
-
const position = new
|
|
17813
|
+
const position = new import_three42.Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17250
17814
|
this.validatePosBounds(position);
|
|
17251
17815
|
const copy = [...section.biomes];
|
|
17252
17816
|
if (copy.length !== 64 || !copy.every((id) => typeof id === "string" && id.length > 0)) {
|
|
@@ -17257,9 +17821,12 @@ var MineRenderWorld = class {
|
|
|
17257
17821
|
if (!column) this.biomes.set(key, column = /* @__PURE__ */ new Map());
|
|
17258
17822
|
column.set(section.y, copy);
|
|
17259
17823
|
}
|
|
17824
|
+
}
|
|
17825
|
+
let sliceStart = performance.now();
|
|
17826
|
+
for (const section of chunk.sections) {
|
|
17260
17827
|
if (!executor) {
|
|
17261
17828
|
if (!occupiedSections.has(section.y)) continue;
|
|
17262
|
-
const position = new
|
|
17829
|
+
const position = new import_three42.Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17263
17830
|
this.validatePosBounds(position);
|
|
17264
17831
|
const target = this.getOrCreateChunkAt(position);
|
|
17265
17832
|
try {
|
|
@@ -17353,7 +17920,7 @@ var MineRenderWorld = class {
|
|
|
17353
17920
|
this.sectionModels?.clear();
|
|
17354
17921
|
}
|
|
17355
17922
|
updateCulling(positions) {
|
|
17356
|
-
const neighbor = new
|
|
17923
|
+
const neighbor = new import_three42.Vector3();
|
|
17357
17924
|
for (const pos of positions) {
|
|
17358
17925
|
const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);
|
|
17359
17926
|
const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);
|
|
@@ -17421,18 +17988,34 @@ var MineRenderWorld = class {
|
|
|
17421
17988
|
const key = this.worldPosToChunkKey(pos);
|
|
17422
17989
|
let chunk = this._chunks.get(key);
|
|
17423
17990
|
if (typeof chunk === "undefined") {
|
|
17991
|
+
const x = Math.floor(pos.x / 16), y = Math.floor(pos.y / 16), z = Math.floor(pos.z / 16);
|
|
17424
17992
|
chunk = new Chunk(
|
|
17425
17993
|
this.scene,
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17994
|
+
x,
|
|
17995
|
+
y,
|
|
17996
|
+
z,
|
|
17429
17997
|
(positions) => this.updateCulling(positions),
|
|
17430
17998
|
this.sectionModels,
|
|
17431
|
-
(
|
|
17432
|
-
const cx = Math.floor(
|
|
17999
|
+
(x2, y2, z2) => {
|
|
18000
|
+
const cx = Math.floor(x2 / 16), cy = Math.floor(y2 / 16), cz = Math.floor(z2 / 16);
|
|
17433
18001
|
const section = this._chunks.get(`${cx}_${cy}_${cz}`);
|
|
17434
|
-
const index = (
|
|
18002
|
+
const index = (y2 - cy * 16) * 256 + (z2 - cz * 16) * 16 + x2 - cx * 16;
|
|
17435
18003
|
return (section?.fluidByteIndex(index) ?? 0) | (section?.isOccludingIndex(index) ? 64 : 0);
|
|
18004
|
+
},
|
|
18005
|
+
(x2, y2, z2) => this.getBiomeAt(x2, y2, z2),
|
|
18006
|
+
async (biomes) => {
|
|
18007
|
+
if (this._chunks.get(key) !== chunk) return;
|
|
18008
|
+
const columnKey = `${x}_${z}`;
|
|
18009
|
+
let column = this.biomes.get(columnKey);
|
|
18010
|
+
if (biomes) {
|
|
18011
|
+
if (!column) this.biomes.set(columnKey, column = /* @__PURE__ */ new Map());
|
|
18012
|
+
column.set(y, biomes);
|
|
18013
|
+
} else {
|
|
18014
|
+
column?.delete(y);
|
|
18015
|
+
if (!column?.size) this.biomes.delete(columnKey);
|
|
18016
|
+
}
|
|
18017
|
+
await chunk.refreshBiomes();
|
|
18018
|
+
await this._chunks.get(`${x}_${y + 1}_${z}`)?.refreshBiomes();
|
|
17436
18019
|
}
|
|
17437
18020
|
);
|
|
17438
18021
|
this._chunks.set(key, chunk);
|
|
@@ -17445,7 +18028,7 @@ var MineRenderWorld = class {
|
|
|
17445
18028
|
}
|
|
17446
18029
|
/** Converts block coordinates to scene units by multiplying each component by 16. */
|
|
17447
18030
|
static worldToScenePosition(pos) {
|
|
17448
|
-
return new
|
|
18031
|
+
return new import_three42.Vector3(
|
|
17449
18032
|
pos.x * 16,
|
|
17450
18033
|
pos.y * 16,
|
|
17451
18034
|
pos.z * 16
|
|
@@ -17453,7 +18036,7 @@ var MineRenderWorld = class {
|
|
|
17453
18036
|
}
|
|
17454
18037
|
/** Converts scene units to block coordinates without rounding to an integer block. */
|
|
17455
18038
|
static sceneToWorldPosition(pos) {
|
|
17456
|
-
return new
|
|
18039
|
+
return new import_three42.Vector3(
|
|
17457
18040
|
pos.x / 16,
|
|
17458
18041
|
pos.y / 16,
|
|
17459
18042
|
pos.z / 16
|
|
@@ -17476,7 +18059,7 @@ var MineRenderWorld = class {
|
|
|
17476
18059
|
init_Model();
|
|
17477
18060
|
|
|
17478
18061
|
// src/world/SectionMesh.ts
|
|
17479
|
-
var
|
|
18062
|
+
var import_three43 = require("three");
|
|
17480
18063
|
init_CanvasCompat();
|
|
17481
18064
|
init_Materials();
|
|
17482
18065
|
|
|
@@ -17487,6 +18070,7 @@ function buildSectionGeometry(input) {
|
|
|
17487
18070
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
17488
18071
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
17489
18072
|
if (fluids && fluids.cells.length !== 5832) throw new RangeError("Section fluid cells must cover an 18\xD718\xD718 neighborhood");
|
|
18073
|
+
if (fluids?.waterTints && fluids.waterTints.length !== 4096 * 3) throw new RangeError("Section water tints must contain RGB for 4096 cells");
|
|
17490
18074
|
for (const template of templateData) {
|
|
17491
18075
|
const { quads } = template;
|
|
17492
18076
|
if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 || template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 || template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads) {
|
|
@@ -17564,7 +18148,9 @@ function buildSectionGeometry(input) {
|
|
|
17564
18148
|
height
|
|
17565
18149
|
});
|
|
17566
18150
|
}
|
|
17567
|
-
|
|
18151
|
+
const tintIndex = (x + z * 16 + y * 256) * 3;
|
|
18152
|
+
const tint = fluid === "water" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;
|
|
18153
|
+
fluidPages.get(fluid).fluids.push({ quads, x, y, z, data, tint });
|
|
17568
18154
|
}
|
|
17569
18155
|
pages.push(...[...fluidPages.values()].sort((a, b) => Number(atlases[a.placements[0].atlas].animated) - Number(atlases[b.placements[0].atlas].animated) || a.placements[0].atlas - b.placements[0].atlas));
|
|
17570
18156
|
}
|
|
@@ -17613,7 +18199,7 @@ function buildSectionGeometry(input) {
|
|
|
17613
18199
|
for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[quad * 6 + corner];
|
|
17614
18200
|
}
|
|
17615
18201
|
}
|
|
17616
|
-
for (const { quads, x, y, z, data } of page.fluids) {
|
|
18202
|
+
for (const { quads, x, y, z, data, tint } of page.fluids) {
|
|
17617
18203
|
const atlas = atlases[data.atlas];
|
|
17618
18204
|
const placement = page.placements[0];
|
|
17619
18205
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
@@ -17637,7 +18223,7 @@ function buildSectionGeometry(input) {
|
|
|
17637
18223
|
mapU((rect[0] + rect[2]) / atlas.width),
|
|
17638
18224
|
mapV(1 - rect[1] / atlas.height)
|
|
17639
18225
|
], vertex * 4);
|
|
17640
|
-
colors.set(
|
|
18226
|
+
colors.set(tint, vertex * 3);
|
|
17641
18227
|
}
|
|
17642
18228
|
outputIndices.set([start, start + 1, start + 2, start, start + 2, start + 3], indexOffset);
|
|
17643
18229
|
indexOffset += 6;
|
|
@@ -17705,7 +18291,7 @@ var SectionWorker = class _SectionWorker {
|
|
|
17705
18291
|
|
|
17706
18292
|
// src/world/SectionMesh.ts
|
|
17707
18293
|
var templateCache = /* @__PURE__ */ new WeakMap();
|
|
17708
|
-
var WATER_TINT = new
|
|
18294
|
+
var WATER_TINT = new import_three43.Color(4159204).toArray();
|
|
17709
18295
|
function toInput(entries, maxAtlasSize, fluids) {
|
|
17710
18296
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
17711
18297
|
const atlases = [];
|
|
@@ -17779,7 +18365,7 @@ function toInput(entries, maxAtlasSize, fluids) {
|
|
|
17779
18365
|
input.cullMasks[i] = cullMask;
|
|
17780
18366
|
}
|
|
17781
18367
|
if (fluids) {
|
|
17782
|
-
input.fluids = { cells: fluids.cells };
|
|
18368
|
+
input.fluids = { cells: fluids.cells, waterTints: fluids.waterTints };
|
|
17783
18369
|
for (const kind of ["water", "lava"]) {
|
|
17784
18370
|
const atlas = fluids[kind];
|
|
17785
18371
|
if (!atlas) continue;
|
|
@@ -17800,7 +18386,7 @@ function toInput(entries, maxAtlasSize, fluids) {
|
|
|
17800
18386
|
}
|
|
17801
18387
|
return { input, atlases };
|
|
17802
18388
|
}
|
|
17803
|
-
var SectionMesh = class _SectionMesh extends
|
|
18389
|
+
var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
17804
18390
|
constructor() {
|
|
17805
18391
|
super(...arguments);
|
|
17806
18392
|
this.ownedMeshes = [];
|
|
@@ -17825,26 +18411,26 @@ var SectionMesh = class _SectionMesh extends import_three42.Group {
|
|
|
17825
18411
|
for (const { atlas, x, y } of page.placements) {
|
|
17826
18412
|
context.drawImage(atlases[atlas].image.canvas, x, y);
|
|
17827
18413
|
}
|
|
17828
|
-
const geometry = new
|
|
17829
|
-
geometry.setAttribute("position", new
|
|
17830
|
-
geometry.setAttribute("normal", new
|
|
17831
|
-
geometry.setAttribute("uv", new
|
|
17832
|
-
geometry.setAttribute("uvBounds", new
|
|
17833
|
-
geometry.setAttribute("color", new
|
|
17834
|
-
geometry.setIndex(new
|
|
18414
|
+
const geometry = new import_three43.BufferGeometry();
|
|
18415
|
+
geometry.setAttribute("position", new import_three43.Float32BufferAttribute(page.positions.buffer, 3));
|
|
18416
|
+
geometry.setAttribute("normal", new import_three43.Float32BufferAttribute(page.normals.buffer, 3));
|
|
18417
|
+
geometry.setAttribute("uv", new import_three43.Float32BufferAttribute(page.uvs.buffer, 2));
|
|
18418
|
+
geometry.setAttribute("uvBounds", new import_three43.Float32BufferAttribute(page.uvBounds.buffer, 4));
|
|
18419
|
+
geometry.setAttribute("color", new import_three43.Float32BufferAttribute(page.colors.buffer, 3));
|
|
18420
|
+
geometry.setIndex(new import_three43.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
17835
18421
|
geometry.computeBoundingBox();
|
|
17836
18422
|
geometry.computeBoundingSphere();
|
|
17837
18423
|
const transparent = page.layer === 2 ? atlases[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
17838
18424
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
17839
|
-
material.side =
|
|
18425
|
+
material.side = import_three43.FrontSide;
|
|
17840
18426
|
if (page.layer === 2) {
|
|
17841
|
-
material.side =
|
|
18427
|
+
material.side = import_three43.DoubleSide;
|
|
17842
18428
|
material.forceSinglePass = true;
|
|
17843
18429
|
material.depthWrite = !material.transparent;
|
|
17844
18430
|
}
|
|
17845
18431
|
material.vertexColors = true;
|
|
17846
18432
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
17847
|
-
const mesh = new
|
|
18433
|
+
const mesh = new import_three43.Mesh(geometry, material);
|
|
17848
18434
|
section.add(mesh);
|
|
17849
18435
|
const unsubscribe = [];
|
|
17850
18436
|
for (const { atlas: id, x, y } of page.placements) {
|
|
@@ -17880,17 +18466,20 @@ var SectionMesh = class _SectionMesh extends import_three42.Group {
|
|
|
17880
18466
|
init_FluidGeometry();
|
|
17881
18467
|
init_FluidQuads();
|
|
17882
18468
|
init_CubeFace();
|
|
18469
|
+
var WATER_TINT2 = new import_three44.Color(4159204).toArray();
|
|
17883
18470
|
var Chunk = class _Chunk {
|
|
17884
|
-
constructor(scene, x, y, z, onBlocksChanged, sectionModels, neighborCell) {
|
|
18471
|
+
constructor(scene, x, y, z, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged) {
|
|
17885
18472
|
this.onBlocksChanged = onBlocksChanged;
|
|
17886
18473
|
this.sectionModels = sectionModels;
|
|
17887
18474
|
this.neighborCell = neighborCell;
|
|
18475
|
+
this.biomeAt = biomeAt;
|
|
18476
|
+
this.onBiomesChanged = onBiomesChanged;
|
|
17888
18477
|
this.data = new ChunkData();
|
|
17889
18478
|
this.renderedBlocks = /* @__PURE__ */ new Map();
|
|
17890
18479
|
this.sectionBlocks = /* @__PURE__ */ new Map();
|
|
17891
18480
|
this.hiddenBlocks = /* @__PURE__ */ new Set();
|
|
17892
18481
|
this.fluidCells = new Uint8Array(4096);
|
|
17893
|
-
this.blockPosition = new
|
|
18482
|
+
this.blockPosition = new import_three44.Vector3();
|
|
17894
18483
|
this.meshDirty = false;
|
|
17895
18484
|
this.meshGeneration = 0;
|
|
17896
18485
|
this.scene = scene;
|
|
@@ -17900,21 +18489,71 @@ var Chunk = class _Chunk {
|
|
|
17900
18489
|
}
|
|
17901
18490
|
getBlockAt(posOrX, y, z) {
|
|
17902
18491
|
if (typeof posOrX == "number") {
|
|
17903
|
-
return this.getBlockAt(new
|
|
18492
|
+
return this.getBlockAt(new import_three44.Vector3(posOrX, y, z));
|
|
17904
18493
|
}
|
|
17905
18494
|
if (isTripleArray(posOrX)) {
|
|
17906
|
-
return this.getBlockAt(new
|
|
18495
|
+
return this.getBlockAt(new import_three44.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
17907
18496
|
}
|
|
17908
18497
|
const pos = this.blockPosition.set(posOrX.x - this.x * 16, posOrX.y - this.y * 16, posOrX.z - this.z * 16);
|
|
17909
18498
|
const index = _Chunk.chunkPosToBlockIndex(pos);
|
|
17910
18499
|
return this.renderedBlocks.get(index);
|
|
17911
18500
|
}
|
|
18501
|
+
getBiomeAt(posOrX, y, z) {
|
|
18502
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new import_three44.Vector3(posOrX, y, z));
|
|
18503
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new import_three44.Vector3(...posOrX));
|
|
18504
|
+
const pos = this.worldPosToChunkPos(posOrX);
|
|
18505
|
+
_Chunk.chunkPosToBlockIndex(pos);
|
|
18506
|
+
return this.biomeAt ? this.biomeAt(posOrX.x, posOrX.y, posOrX.z) : this.biomes?.[Math.floor(pos.x / 4) + Math.floor(pos.z / 4) * 4 + Math.floor(pos.y / 4) * 16];
|
|
18507
|
+
}
|
|
18508
|
+
/** Copies 64 biome IDs in x + z * 4 + y * 16 order and refreshes placed blocks. Omit the array to clear biome data. */
|
|
18509
|
+
setBiomes(biomes) {
|
|
18510
|
+
const copy = biomes ? [...biomes] : void 0;
|
|
18511
|
+
if (copy && (copy.length !== 64 || !copy.every((id) => typeof id === "string" && id.length > 0))) {
|
|
18512
|
+
throw new RangeError("Section biomes must contain 64 nonempty biome IDs");
|
|
18513
|
+
}
|
|
18514
|
+
if (this.onBiomesChanged) return this.onBiomesChanged(copy);
|
|
18515
|
+
this.biomes = copy;
|
|
18516
|
+
return this.refreshBiomes();
|
|
18517
|
+
}
|
|
18518
|
+
/** Rebuilds biome-tinted blocks while preserving hidden blocks and unrelated render objects. */
|
|
18519
|
+
async refreshBiomes() {
|
|
18520
|
+
const affected = /* @__PURE__ */ new Map();
|
|
18521
|
+
const blocks = [];
|
|
18522
|
+
for (const index of this.renderedBlocks.keys()) {
|
|
18523
|
+
const block = this.data.get(index);
|
|
18524
|
+
const stateKey = ChunkData.paletteKey(block);
|
|
18525
|
+
let matches = affected.get(stateKey);
|
|
18526
|
+
if (!matches) {
|
|
18527
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
18528
|
+
matches = BlockStates.get(key).then(async (state) => {
|
|
18529
|
+
const origin = state?.key ?? key;
|
|
18530
|
+
const [source, fluid] = await Promise.all([BlockTints.biomeSource(origin), getBlockFluidState(origin, block.properties)]);
|
|
18531
|
+
return !!source || fluid?.kind === "water";
|
|
18532
|
+
});
|
|
18533
|
+
affected.set(stateKey, matches);
|
|
18534
|
+
}
|
|
18535
|
+
if (await matches) blocks.push({ index, block });
|
|
18536
|
+
}
|
|
18537
|
+
if (!blocks.length) return;
|
|
18538
|
+
const hidden = new Set(this.hiddenBlocks);
|
|
18539
|
+
try {
|
|
18540
|
+
await this.placeBlocks(blocks);
|
|
18541
|
+
} finally {
|
|
18542
|
+
for (const index of hidden) {
|
|
18543
|
+
this.hiddenBlocks.add(index);
|
|
18544
|
+
this.renderedBlocks.get(index)?.object?.setVisible(false);
|
|
18545
|
+
}
|
|
18546
|
+
const positions = blocks.map(({ index }) => new import_three44.Vector3(...this.positionAt(index)));
|
|
18547
|
+
if (this.onBlocksChanged) await this.onBlocksChanged(positions);
|
|
18548
|
+
else await this.rebuildSectionMesh();
|
|
18549
|
+
}
|
|
18550
|
+
}
|
|
17912
18551
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
17913
18552
|
if (typeof posOrX == "number") {
|
|
17914
|
-
return this.setBlockAt(new
|
|
18553
|
+
return this.setBlockAt(new import_three44.Vector3(posOrX, yOrBlock, z), block);
|
|
17915
18554
|
}
|
|
17916
18555
|
if (isTripleArray(posOrX)) {
|
|
17917
|
-
return this.setBlockAt(new
|
|
18556
|
+
return this.setBlockAt(new import_three44.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
17918
18557
|
}
|
|
17919
18558
|
const worldPos = posOrX;
|
|
17920
18559
|
const pos = this.worldPosToChunkPos(worldPos);
|
|
@@ -17947,14 +18586,15 @@ var Chunk = class _Chunk {
|
|
|
17947
18586
|
nbt: block.nbt === void 0 ? void 0 : structuredClone(block.nbt)
|
|
17948
18587
|
} : void 0
|
|
17949
18588
|
}));
|
|
17950
|
-
const states =
|
|
17951
|
-
const
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
18589
|
+
const states = /* @__PURE__ */ new Map();
|
|
18590
|
+
for (const { index, key, block } of placements) {
|
|
18591
|
+
if (key === void 0) continue;
|
|
18592
|
+
let state = states.get(key);
|
|
18593
|
+
if (!state) states.set(key, state = { stored: block, indices: [] });
|
|
18594
|
+
state.indices.push(index);
|
|
18595
|
+
}
|
|
18596
|
+
const biomes = /* @__PURE__ */ new Map();
|
|
18597
|
+
const settled = await Promise.allSettled([...states.values()].map(({ stored, indices }) => this.resolveState(stored, indices, biomes)));
|
|
17958
18598
|
const resolutions = new Map([...states.keys()].map((key, i) => [key, settled[i]]));
|
|
17959
18599
|
const positions = [];
|
|
17960
18600
|
let failed = false, failure;
|
|
@@ -17967,7 +18607,7 @@ var Chunk = class _Chunk {
|
|
|
17967
18607
|
if (this.fluidCells[index]) this.meshDirty = true;
|
|
17968
18608
|
this.fluidCells[index] = 0;
|
|
17969
18609
|
this.renderedBlocks.delete(index);
|
|
17970
|
-
const worldPos = new
|
|
18610
|
+
const worldPos = new import_three44.Vector3(
|
|
17971
18611
|
this.x * 16 + index % 16,
|
|
17972
18612
|
this.y * 16 + Math.floor(index / 256),
|
|
17973
18613
|
this.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -17978,7 +18618,8 @@ var Chunk = class _Chunk {
|
|
|
17978
18618
|
if (!readBlock) continue;
|
|
17979
18619
|
const resolved = resolutions.get(key);
|
|
17980
18620
|
if (resolved.status === "rejected") throw resolved.reason;
|
|
17981
|
-
const { blockState: blockState3, perBlock, fluid, prepared, stored } = resolved.value;
|
|
18621
|
+
const { blockState: blockState3, perBlock, fluid, prepared, contexts, stored } = resolved.value;
|
|
18622
|
+
const context = contexts.get(index);
|
|
17982
18623
|
if (!blockState3) {
|
|
17983
18624
|
this.data.assign(index, 0);
|
|
17984
18625
|
continue;
|
|
@@ -17986,9 +18627,10 @@ var Chunk = class _Chunk {
|
|
|
17986
18627
|
const variantPosition = worldPos.toArray();
|
|
17987
18628
|
if (fluid) {
|
|
17988
18629
|
this.fluidCells[index] = (fluid.kind === "water" ? 16 : 32) | Math.min(fluid.level, 8);
|
|
18630
|
+
if (fluid.kind === "water") this.setWaterTint(index, context?.waterTint);
|
|
17989
18631
|
this.meshDirty = true;
|
|
17990
18632
|
}
|
|
17991
|
-
const templates = perBlock ? void 0 : fluid?.renderModel === false ? [] : prepared?.pick(variantPosition);
|
|
18633
|
+
const templates = perBlock ? void 0 : fluid?.renderModel === false ? [] : (context?.prepared ?? prepared)?.pick(variantPosition);
|
|
17992
18634
|
if (templates) {
|
|
17993
18635
|
this.sectionBlocks.set(index, templates.map((template) => ({ index, template, cullMask: 0 })));
|
|
17994
18636
|
this.meshDirty = true;
|
|
@@ -17998,7 +18640,9 @@ var Chunk = class _Chunk {
|
|
|
17998
18640
|
instanceMeshes: true,
|
|
17999
18641
|
maxInstanceCount: 2e3,
|
|
18000
18642
|
initialState: stored.properties,
|
|
18001
|
-
variantPosition
|
|
18643
|
+
variantPosition,
|
|
18644
|
+
biome: context?.biome,
|
|
18645
|
+
biomePosition: this.biomePosition(index, blockState3, stored)
|
|
18002
18646
|
});
|
|
18003
18647
|
object4.setPosition(MineRenderWorld.worldToScenePosition(worldPos));
|
|
18004
18648
|
}
|
|
@@ -18021,24 +18665,21 @@ var Chunk = class _Chunk {
|
|
|
18021
18665
|
for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
|
|
18022
18666
|
this.sectionBlocks.clear();
|
|
18023
18667
|
this.fluidCells.fill(0);
|
|
18668
|
+
this.waterTints = void 0;
|
|
18024
18669
|
this.renderedBlocks.clear();
|
|
18025
18670
|
this.hiddenBlocks.clear();
|
|
18026
18671
|
this.meshDirty = true;
|
|
18027
18672
|
this.data.copyFrom(data);
|
|
18028
|
-
const ids = /* @__PURE__ */ new
|
|
18673
|
+
const ids = /* @__PURE__ */ new Map();
|
|
18029
18674
|
for (let index = 0; index < 4096; index++) {
|
|
18030
18675
|
const id = this.data.idAt(index);
|
|
18031
|
-
if (id)
|
|
18032
|
-
|
|
18033
|
-
|
|
18034
|
-
|
|
18035
|
-
|
|
18036
|
-
|
|
18037
|
-
|
|
18038
|
-
const fluid = await getBlockFluidState(blockState3?.key, state.properties);
|
|
18039
|
-
const prepared = perBlock || fluid?.renderModel === false ? void 0 : await this.sectionModels.prepareState(blockState3, state.properties);
|
|
18040
|
-
return { blockState: blockState3, perBlock, fluid, prepared };
|
|
18041
|
-
}));
|
|
18676
|
+
if (!id) continue;
|
|
18677
|
+
let indices = ids.get(id);
|
|
18678
|
+
if (!indices) ids.set(id, indices = []);
|
|
18679
|
+
indices.push(index);
|
|
18680
|
+
}
|
|
18681
|
+
const palette = [...ids.keys()], biomes = /* @__PURE__ */ new Map();
|
|
18682
|
+
const settled = await Promise.allSettled(palette.map((id) => this.resolveState(this.data.stateAt(id), ids.get(id), biomes)));
|
|
18042
18683
|
const resolutions = new Map(palette.map((id, i) => [id, settled[i]]));
|
|
18043
18684
|
const perBlocks = [];
|
|
18044
18685
|
let failed = false, failure;
|
|
@@ -18048,24 +18689,28 @@ var Chunk = class _Chunk {
|
|
|
18048
18689
|
try {
|
|
18049
18690
|
const resolved = resolutions.get(id);
|
|
18050
18691
|
if (resolved.status === "rejected") throw resolved.reason;
|
|
18051
|
-
const { blockState: blockState3, perBlock, fluid, prepared } = resolved.value;
|
|
18692
|
+
const { blockState: blockState3, perBlock, fluid, prepared, contexts } = resolved.value;
|
|
18693
|
+
const context = contexts.get(index);
|
|
18052
18694
|
if (!blockState3) {
|
|
18053
18695
|
this.data.assign(index, 0);
|
|
18054
18696
|
this.fluidCells[index] = 0;
|
|
18055
18697
|
continue;
|
|
18056
18698
|
}
|
|
18057
|
-
if (fluid)
|
|
18699
|
+
if (fluid) {
|
|
18700
|
+
this.fluidCells[index] = (fluid.kind === "water" ? 16 : 32) | Math.min(fluid.level, 8);
|
|
18701
|
+
if (fluid.kind === "water") this.setWaterTint(index, context?.waterTint);
|
|
18702
|
+
}
|
|
18058
18703
|
const variantPosition = [
|
|
18059
18704
|
this.x * 16 + index % 16,
|
|
18060
18705
|
this.y * 16 + Math.floor(index / 256),
|
|
18061
18706
|
this.z * 16 + Math.floor(index / 16) % 16
|
|
18062
18707
|
];
|
|
18063
|
-
const templates = perBlock ? void 0 : fluid?.renderModel === false ? [] : prepared?.pick(variantPosition);
|
|
18708
|
+
const templates = perBlock ? void 0 : fluid?.renderModel === false ? [] : (context?.prepared ?? prepared)?.pick(variantPosition);
|
|
18064
18709
|
if (templates) {
|
|
18065
18710
|
this.sectionBlocks.set(index, templates.map((template) => ({ index, template, cullMask: 0 })));
|
|
18066
18711
|
this.meshDirty = true;
|
|
18067
18712
|
} else {
|
|
18068
|
-
perBlocks.push({ index, blockState: blockState3 });
|
|
18713
|
+
perBlocks.push({ index, blockState: blockState3, biome: context?.biome });
|
|
18069
18714
|
}
|
|
18070
18715
|
const readBlock = this.data.snapshot(index);
|
|
18071
18716
|
this.renderedBlocks.set(index, { get block() {
|
|
@@ -18078,7 +18723,7 @@ var Chunk = class _Chunk {
|
|
|
18078
18723
|
failed = true;
|
|
18079
18724
|
}
|
|
18080
18725
|
}
|
|
18081
|
-
for (const { index, blockState: blockState3 } of perBlocks) {
|
|
18726
|
+
for (const { index, blockState: blockState3, biome } of perBlocks) {
|
|
18082
18727
|
let object4;
|
|
18083
18728
|
try {
|
|
18084
18729
|
object4 = await this.scene.addBlock(blockState3, {
|
|
@@ -18086,13 +18731,11 @@ var Chunk = class _Chunk {
|
|
|
18086
18731
|
instanceMeshes: true,
|
|
18087
18732
|
maxInstanceCount: 2e3,
|
|
18088
18733
|
initialState: this.data.stateAt(this.data.idAt(index)).properties,
|
|
18089
|
-
variantPosition:
|
|
18090
|
-
|
|
18091
|
-
|
|
18092
|
-
this.z * 16 + Math.floor(index / 16) % 16
|
|
18093
|
-
]
|
|
18734
|
+
variantPosition: this.positionAt(index),
|
|
18735
|
+
biome,
|
|
18736
|
+
biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
|
|
18094
18737
|
});
|
|
18095
|
-
object4.setPosition(new
|
|
18738
|
+
object4.setPosition(new import_three44.Vector3(
|
|
18096
18739
|
this.x * 256 + index % 16 * 16,
|
|
18097
18740
|
this.y * 256 + Math.floor(index / 256) * 16,
|
|
18098
18741
|
this.z * 256 + Math.floor(index / 16) % 16 * 16
|
|
@@ -18109,6 +18752,68 @@ var Chunk = class _Chunk {
|
|
|
18109
18752
|
}
|
|
18110
18753
|
if (failed) throw failure;
|
|
18111
18754
|
}
|
|
18755
|
+
positionAt(index) {
|
|
18756
|
+
return [this.x * 16 + index % 16, this.y * 16 + Math.floor(index / 256), this.z * 16 + Math.floor(index / 16) % 16];
|
|
18757
|
+
}
|
|
18758
|
+
biomePosition(index, blockState3, stored) {
|
|
18759
|
+
const position = this.positionAt(index), name = blockState3.key?.toNamespacedString();
|
|
18760
|
+
if (stored.properties?.half === "upper" && (name === "minecraft:tall_grass" || name === "minecraft:large_fern")) position[1]--;
|
|
18761
|
+
return position;
|
|
18762
|
+
}
|
|
18763
|
+
async resolveState(stored, indices, biomes) {
|
|
18764
|
+
const blockState3 = await BlockStates.get(AssetKey.parse("blockstates", stored.type));
|
|
18765
|
+
const perBlock = !blockState3 || !this.sectionModels || !!(blockState3.key && BlockEntities.entry(await BlockEntities.getIndex(blockState3.key.root), blockState3.key.toNamespacedString()));
|
|
18766
|
+
const fluid = await getBlockFluidState(blockState3?.key, stored.properties);
|
|
18767
|
+
const hasBiomes = this.getBiomeAt(this.x * 16, this.y * 16, this.z * 16) !== void 0 || this.biomeAt?.(this.x * 16, this.y * 16 - 1, this.z * 16) !== void 0;
|
|
18768
|
+
const source = hasBiomes && blockState3 ? await BlockTints.biomeSource(blockState3.key) : void 0;
|
|
18769
|
+
const prepare = (color2) => perBlock || fluid?.renderModel === false ? void 0 : this.sectionModels.prepareState(blockState3, stored.properties, color2);
|
|
18770
|
+
const contexts = /* @__PURE__ */ new Map();
|
|
18771
|
+
const groups = /* @__PURE__ */ new Map();
|
|
18772
|
+
if (blockState3 && (source || fluid?.kind === "water")) {
|
|
18773
|
+
for (const index of indices) {
|
|
18774
|
+
const position = this.biomePosition(index, blockState3, stored);
|
|
18775
|
+
const biome = this.biomeAt ? this.biomeAt(...position) : position[1] >= this.y * 16 ? this.getBiomeAt(position) : void 0;
|
|
18776
|
+
if (!biome) continue;
|
|
18777
|
+
const key = JSON.stringify(source === "grass" ? [biome, position[0], position[2]] : [biome]);
|
|
18778
|
+
let group = groups.get(key);
|
|
18779
|
+
if (!group) groups.set(key, group = { biome, position, indices: [] });
|
|
18780
|
+
group.indices.push(index);
|
|
18781
|
+
}
|
|
18782
|
+
}
|
|
18783
|
+
const groupedCount = [...groups.values()].reduce((sum, group) => sum + group.indices.length, 0);
|
|
18784
|
+
const prepared = groupedCount < indices.length ? await prepare() : void 0;
|
|
18785
|
+
await Promise.all([...groups.values()].map(async ({ biome, position, indices: indices2 }) => {
|
|
18786
|
+
const available = () => {
|
|
18787
|
+
const key = JSON.stringify([biome, blockState3?.key?.root]);
|
|
18788
|
+
let found = biomes.get(key);
|
|
18789
|
+
if (!found) {
|
|
18790
|
+
found = Biomes.get(biome, blockState3?.key).then((value) => value !== void 0);
|
|
18791
|
+
biomes.set(key, found);
|
|
18792
|
+
}
|
|
18793
|
+
return found;
|
|
18794
|
+
};
|
|
18795
|
+
const context = { biome };
|
|
18796
|
+
if (perBlock) {
|
|
18797
|
+
if (!await available()) context.biome = void 0;
|
|
18798
|
+
} else {
|
|
18799
|
+
context.prepared = await prepare(async () => await available() ? BlockTints.getBiomeColor(blockState3?.key, biome, position) : void 0);
|
|
18800
|
+
if (fluid?.kind === "water" && await available()) {
|
|
18801
|
+
const color2 = await Biomes.getColor(biome, "water", blockState3?.key);
|
|
18802
|
+
if (color2 !== void 0 && color2 !== 4159204) context.waterTint = new import_three44.Color(color2).toArray();
|
|
18803
|
+
}
|
|
18804
|
+
}
|
|
18805
|
+
for (const index of indices2) contexts.set(index, context);
|
|
18806
|
+
}));
|
|
18807
|
+
return { blockState: blockState3, perBlock, fluid, prepared, contexts, stored };
|
|
18808
|
+
}
|
|
18809
|
+
setWaterTint(index, tint) {
|
|
18810
|
+
if (!this.sectionModels || !this.waterTints && tint === void 0) return;
|
|
18811
|
+
if (!this.waterTints) {
|
|
18812
|
+
this.waterTints = new Float32Array(4096 * 3);
|
|
18813
|
+
for (let cell = 0; cell < 4096; cell++) this.waterTints.set(WATER_TINT2, cell * 3);
|
|
18814
|
+
}
|
|
18815
|
+
this.waterTints.set(tint ?? WATER_TINT2, index * 3);
|
|
18816
|
+
}
|
|
18112
18817
|
/** Changes visibility at world block coordinates while preserving the block's data. */
|
|
18113
18818
|
async setBlockVisibleAt(pos, visible) {
|
|
18114
18819
|
const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
|
|
@@ -18212,7 +18917,7 @@ var Chunk = class _Chunk {
|
|
|
18212
18917
|
if (block && !block.object) origins.set(kind, block.block.type);
|
|
18213
18918
|
}
|
|
18214
18919
|
if (origins.size) {
|
|
18215
|
-
fluids = { cells: new Uint8Array(18 * 18 * 18) };
|
|
18920
|
+
fluids = { cells: new Uint8Array(18 * 18 * 18), waterTints: this.waterTints?.slice() };
|
|
18216
18921
|
for (let y = -1; y <= 16; y++) {
|
|
18217
18922
|
for (let z = -1; z <= 16; z++) {
|
|
18218
18923
|
for (let x = -1; x <= 16; x++) {
|
|
@@ -18243,7 +18948,7 @@ var Chunk = class _Chunk {
|
|
|
18243
18948
|
/** Removes stored blocks and render objects. Set `notify` to false to skip the owning world's update. */
|
|
18244
18949
|
async clear(notify = true) {
|
|
18245
18950
|
const positions = notify && this.onBlocksChanged ? [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
|
|
18246
|
-
new
|
|
18951
|
+
new import_three44.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
|
|
18247
18952
|
)) : [];
|
|
18248
18953
|
for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
|
|
18249
18954
|
this.sectionBlocks.clear();
|
|
@@ -18254,8 +18959,13 @@ var Chunk = class _Chunk {
|
|
|
18254
18959
|
this.renderedBlocks.clear();
|
|
18255
18960
|
this.hiddenBlocks.clear();
|
|
18256
18961
|
this.fluidCells.fill(0);
|
|
18962
|
+
this.waterTints = void 0;
|
|
18257
18963
|
this.data.clear();
|
|
18258
|
-
|
|
18964
|
+
this.biomes = void 0;
|
|
18965
|
+
if (notify) {
|
|
18966
|
+
await this.onBiomesChanged?.(void 0);
|
|
18967
|
+
await this.onBlocksChanged?.(positions);
|
|
18968
|
+
}
|
|
18259
18969
|
}
|
|
18260
18970
|
async dispose() {
|
|
18261
18971
|
await this.clear();
|
|
@@ -18271,14 +18981,14 @@ var Chunk = class _Chunk {
|
|
|
18271
18981
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
18272
18982
|
}
|
|
18273
18983
|
worldPosToChunkPos(pos) {
|
|
18274
|
-
return new
|
|
18984
|
+
return new import_three44.Vector3(
|
|
18275
18985
|
pos.x - this.x * 16,
|
|
18276
18986
|
pos.y - this.y * 16,
|
|
18277
18987
|
pos.z - this.z * 16
|
|
18278
18988
|
);
|
|
18279
18989
|
}
|
|
18280
18990
|
chunkPosToWorldPos(pos) {
|
|
18281
|
-
return new
|
|
18991
|
+
return new import_three44.Vector3(
|
|
18282
18992
|
this.x * 16 + pos.x,
|
|
18283
18993
|
this.y * 16 + pos.y,
|
|
18284
18994
|
this.z * 16 + pos.z
|
|
@@ -18641,6 +19351,7 @@ var NodeRenderer = class _NodeRenderer extends Renderer {
|
|
|
18641
19351
|
BannerPatterns,
|
|
18642
19352
|
BasicAssetKey,
|
|
18643
19353
|
BatchedExecutor,
|
|
19354
|
+
Biomes,
|
|
18644
19355
|
BlockEntities,
|
|
18645
19356
|
BlockObject,
|
|
18646
19357
|
BlockStateResolver,
|
|
@@ -18672,6 +19383,7 @@ var NodeRenderer = class _NodeRenderer extends Renderer {
|
|
|
18672
19383
|
EntityObject,
|
|
18673
19384
|
Env,
|
|
18674
19385
|
FluidModelObject,
|
|
19386
|
+
FlyControls,
|
|
18675
19387
|
Fonts,
|
|
18676
19388
|
GUI_CONTAINER_LAYOUTS,
|
|
18677
19389
|
Geometries,
|
|
@@ -18777,6 +19489,7 @@ var NodeRenderer = class _NodeRenderer extends Renderer {
|
|
|
18777
19489
|
isDisposable,
|
|
18778
19490
|
isDoubleArray,
|
|
18779
19491
|
isEntityObject,
|
|
19492
|
+
isFlyControls,
|
|
18780
19493
|
isGuiObject,
|
|
18781
19494
|
isInstanceManager,
|
|
18782
19495
|
isInstanceReference,
|