minerender 2.1.0-alpha.59 → 2.1.0-alpha.60
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 +28 -1
- package/dist/browser/index.d.ts +28 -1
- package/dist/browser/index.js +926 -705
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +810 -589
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +817 -595
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +28 -1
- package/dist/node/index.d.ts +28 -1
- package/dist/node/index.js +928 -706
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +811 -590
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -1133,6 +1133,26 @@ var init_Materials = __esm({
|
|
|
1133
1133
|
}
|
|
1134
1134
|
});
|
|
1135
1135
|
|
|
1136
|
+
// src/model/Model.ts
|
|
1137
|
+
function isDoubleArray(obj) {
|
|
1138
|
+
return Array.isArray(obj) && obj.length === 2;
|
|
1139
|
+
}
|
|
1140
|
+
function isTripleArray(obj) {
|
|
1141
|
+
return Array.isArray(obj) && obj.length === 3;
|
|
1142
|
+
}
|
|
1143
|
+
function isQuadArray(obj) {
|
|
1144
|
+
return Array.isArray(obj) && obj.length === 4;
|
|
1145
|
+
}
|
|
1146
|
+
var ITEM_GENERATED, BUILTIN_GENERATED, BUILTIN_ENTITY, DEFAULT_ELEMENTS;
|
|
1147
|
+
var init_Model = __esm({
|
|
1148
|
+
"src/model/Model.ts"() {
|
|
1149
|
+
ITEM_GENERATED = "item/generated";
|
|
1150
|
+
BUILTIN_GENERATED = "builtin/generated";
|
|
1151
|
+
BUILTIN_ENTITY = "builtin/entity";
|
|
1152
|
+
DEFAULT_ELEMENTS = [];
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1136
1156
|
// ../../node_modules/ts-deepmerge/dist/index.js
|
|
1137
1157
|
var require_dist = __commonJS({
|
|
1138
1158
|
"../../node_modules/ts-deepmerge/dist/index.js"(exports) {
|
|
@@ -1391,6 +1411,7 @@ var init_DisplayTransforms = __esm({
|
|
|
1391
1411
|
var import_ts_deepmerge, ModelMerger;
|
|
1392
1412
|
var init_ModelMerger = __esm({
|
|
1393
1413
|
"src/model/ModelMerger.ts"() {
|
|
1414
|
+
init_Model();
|
|
1394
1415
|
init_Models();
|
|
1395
1416
|
import_ts_deepmerge = __toESM(require_dist());
|
|
1396
1417
|
init_AssetKey();
|
|
@@ -1416,6 +1437,7 @@ var init_ModelMerger = __esm({
|
|
|
1416
1437
|
}
|
|
1417
1438
|
const models = [];
|
|
1418
1439
|
const parentKey = AssetKey.parse("models", model.parent);
|
|
1440
|
+
if (parentKey.namespace === "minecraft" && parentKey.getFullPath() === BUILTIN_ENTITY) return models;
|
|
1419
1441
|
parentKey.root = model.key?.root;
|
|
1420
1442
|
const parentModel = await Models.getRaw(parentKey);
|
|
1421
1443
|
if (parentModel) {
|
|
@@ -1482,12 +1504,12 @@ var init_Models = __esm({
|
|
|
1482
1504
|
const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
|
|
1483
1505
|
if (!result) return void 0;
|
|
1484
1506
|
if (result.key.assetType !== "items") return { ...result.asset, key };
|
|
1485
|
-
const
|
|
1486
|
-
const modelKey = AssetKey.parse("models",
|
|
1507
|
+
const selected = this.defaultItemModel(result.asset.model, key);
|
|
1508
|
+
const modelKey = AssetKey.parse("models", selected.model);
|
|
1487
1509
|
modelKey.root = key.root;
|
|
1488
1510
|
const model2 = await this.getRaw(modelKey);
|
|
1489
|
-
if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${
|
|
1490
|
-
return model2;
|
|
1511
|
+
if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
|
|
1512
|
+
return selected.special ? { ...model2, special: selected.special } : model2;
|
|
1491
1513
|
});
|
|
1492
1514
|
return model ? { ...model, key: Object.assign(new AssetKey("", ""), model.key) } : void 0;
|
|
1493
1515
|
}
|
|
@@ -1498,8 +1520,25 @@ var init_Models = __esm({
|
|
|
1498
1520
|
}
|
|
1499
1521
|
switch (node.type.replace(/^minecraft:/, "")) {
|
|
1500
1522
|
case "model":
|
|
1501
|
-
if (typeof node.model === "string" && node.model) return node.model;
|
|
1523
|
+
if (typeof node.model === "string" && node.model) return { model: node.model };
|
|
1502
1524
|
break;
|
|
1525
|
+
case "special": {
|
|
1526
|
+
if (!node.base || !node.model || typeof node.model !== "object") break;
|
|
1527
|
+
const special = node.model;
|
|
1528
|
+
switch (special.type) {
|
|
1529
|
+
case "chest":
|
|
1530
|
+
case "minecraft:chest":
|
|
1531
|
+
case "bed":
|
|
1532
|
+
case "minecraft:bed":
|
|
1533
|
+
if (typeof special.texture === "string" && special.texture) return { model: node.base, special };
|
|
1534
|
+
break;
|
|
1535
|
+
case "head":
|
|
1536
|
+
case "minecraft:head":
|
|
1537
|
+
if (typeof special.kind === "string" && special.kind) return { model: node.base, special };
|
|
1538
|
+
break;
|
|
1539
|
+
}
|
|
1540
|
+
throw new Error(`Unsupported special item renderer ${special.type} for ${key.toNamespacedString()}`);
|
|
1541
|
+
}
|
|
1503
1542
|
case "condition":
|
|
1504
1543
|
return this.defaultItemModel(node.on_false, key);
|
|
1505
1544
|
case "select": {
|
|
@@ -3098,6 +3137,102 @@ var init_UVMapper = __esm({
|
|
|
3098
3137
|
}
|
|
3099
3138
|
});
|
|
3100
3139
|
|
|
3140
|
+
// src/MinecraftCubeTexture.ts
|
|
3141
|
+
var MinecraftCubeTexture;
|
|
3142
|
+
var init_MinecraftCubeTexture = __esm({
|
|
3143
|
+
"src/MinecraftCubeTexture.ts"() {
|
|
3144
|
+
init_UVMapper();
|
|
3145
|
+
init_CubeFace();
|
|
3146
|
+
MinecraftCubeTexture = class {
|
|
3147
|
+
constructor(u, v, width, height) {
|
|
3148
|
+
this.u = u;
|
|
3149
|
+
this.v = v;
|
|
3150
|
+
this.width = width;
|
|
3151
|
+
this.height = height;
|
|
3152
|
+
}
|
|
3153
|
+
mapW(x) {
|
|
3154
|
+
return x / this.width;
|
|
3155
|
+
}
|
|
3156
|
+
mapH(x) {
|
|
3157
|
+
return 1 - x / this.height;
|
|
3158
|
+
}
|
|
3159
|
+
getUvEast(w, h, l) {
|
|
3160
|
+
return [
|
|
3161
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
3162
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
3163
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)],
|
|
3164
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
3165
|
+
];
|
|
3166
|
+
}
|
|
3167
|
+
getUvWest(w, h, l) {
|
|
3168
|
+
return [
|
|
3169
|
+
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
3170
|
+
[this.mapW(this.u), this.mapH(this.v + l + h)],
|
|
3171
|
+
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
3172
|
+
[this.mapW(this.u), this.mapH(this.v + l)]
|
|
3173
|
+
];
|
|
3174
|
+
}
|
|
3175
|
+
getUvUp(w, h, l) {
|
|
3176
|
+
return [
|
|
3177
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
3178
|
+
[this.mapW(this.u + l + w + w), this.mapH(this.v + l)],
|
|
3179
|
+
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
3180
|
+
[this.mapW(this.u + l + w + w), this.mapH(this.v)]
|
|
3181
|
+
];
|
|
3182
|
+
}
|
|
3183
|
+
getUvDown(w, h, l) {
|
|
3184
|
+
return [
|
|
3185
|
+
[this.mapW(this.u + l), this.mapH(this.v)],
|
|
3186
|
+
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
3187
|
+
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
3188
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
3189
|
+
];
|
|
3190
|
+
}
|
|
3191
|
+
getUvSouth(w, h, l) {
|
|
3192
|
+
return [
|
|
3193
|
+
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l + h)],
|
|
3194
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
3195
|
+
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l)],
|
|
3196
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)]
|
|
3197
|
+
];
|
|
3198
|
+
}
|
|
3199
|
+
getUvNorth(w, h, l) {
|
|
3200
|
+
return [
|
|
3201
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
3202
|
+
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
3203
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
3204
|
+
[this.mapW(this.u + l), this.mapH(this.v + l)]
|
|
3205
|
+
];
|
|
3206
|
+
}
|
|
3207
|
+
getFaceUv(face, w, h, l) {
|
|
3208
|
+
switch (face) {
|
|
3209
|
+
case "east" /* EAST */:
|
|
3210
|
+
return this.getUvEast(w, h, l);
|
|
3211
|
+
case "west" /* WEST */:
|
|
3212
|
+
return this.getUvWest(w, h, l);
|
|
3213
|
+
case "up" /* UP */:
|
|
3214
|
+
return this.getUvUp(w, h, l);
|
|
3215
|
+
case "down" /* DOWN */:
|
|
3216
|
+
return this.getUvDown(w, h, l);
|
|
3217
|
+
case "south" /* SOUTH */:
|
|
3218
|
+
return this.getUvSouth(w, h, l);
|
|
3219
|
+
case "north" /* NORTH */:
|
|
3220
|
+
return this.getUvNorth(w, h, l);
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
toUvArray(w, h, l, mirror = false) {
|
|
3224
|
+
const uv = [];
|
|
3225
|
+
for (let i = 0; i < CUBE_FACES.length; i++) {
|
|
3226
|
+
const face = mirror && i < 2 ? CUBE_FACES[1 - i] : CUBE_FACES[i];
|
|
3227
|
+
const corners = this.getFaceUv(face, w, h, l);
|
|
3228
|
+
UVMapper.setFaceUvInArray(uv, i * 4, mirror ? [corners[1], corners[0], corners[3], corners[2]] : corners);
|
|
3229
|
+
}
|
|
3230
|
+
return uv;
|
|
3231
|
+
}
|
|
3232
|
+
};
|
|
3233
|
+
}
|
|
3234
|
+
});
|
|
3235
|
+
|
|
3101
3236
|
// src/error/MineRenderError.ts
|
|
3102
3237
|
var MineRenderError;
|
|
3103
3238
|
var init_MineRenderError = __esm({
|
|
@@ -3114,6 +3249,248 @@ var init_MineRenderError = __esm({
|
|
|
3114
3249
|
}
|
|
3115
3250
|
});
|
|
3116
3251
|
|
|
3252
|
+
// src/assets/Entities.ts
|
|
3253
|
+
var Entities;
|
|
3254
|
+
var init_Entities = __esm({
|
|
3255
|
+
"src/assets/Entities.ts"() {
|
|
3256
|
+
init_AssetKey();
|
|
3257
|
+
init_AssetLoader();
|
|
3258
|
+
init_source();
|
|
3259
|
+
init_Caching();
|
|
3260
|
+
init_Assets();
|
|
3261
|
+
init_MineRenderError();
|
|
3262
|
+
init_ModelTextures();
|
|
3263
|
+
Entities = class {
|
|
3264
|
+
static async getEntityList() {
|
|
3265
|
+
const collect = async (path) => {
|
|
3266
|
+
const prefix2 = path ? `${path}/` : "";
|
|
3267
|
+
const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
|
|
3268
|
+
const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
|
|
3269
|
+
if (!list) return [];
|
|
3270
|
+
const files = list.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
|
|
3271
|
+
const children = await Promise.all(list.directories.map((directory) => collect(`${prefix2}${directory}`)));
|
|
3272
|
+
return [...files, ...children.flat()];
|
|
3273
|
+
};
|
|
3274
|
+
return collect("");
|
|
3275
|
+
}
|
|
3276
|
+
static async getModelFile(modelKey) {
|
|
3277
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3278
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
|
|
3279
|
+
return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
3280
|
+
}
|
|
3281
|
+
static async getLayerList(modelKey) {
|
|
3282
|
+
return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
|
|
3283
|
+
}
|
|
3284
|
+
/** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
|
|
3285
|
+
static async getPassList(modelKey) {
|
|
3286
|
+
return (await this.getModelFile(modelKey))?.passes ?? [];
|
|
3287
|
+
}
|
|
3288
|
+
static async getEntity(modelKey, textureKey, options) {
|
|
3289
|
+
const model = await this.getModelFile(modelKey);
|
|
3290
|
+
if (!model) return void 0;
|
|
3291
|
+
const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
|
|
3292
|
+
const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
|
|
3293
|
+
if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
|
|
3294
|
+
draws.push(...passes);
|
|
3295
|
+
const names = [];
|
|
3296
|
+
const selected = draws.map((pass) => {
|
|
3297
|
+
const layer = model.layers[pass.layer];
|
|
3298
|
+
if (!layer) {
|
|
3299
|
+
throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
|
|
3300
|
+
}
|
|
3301
|
+
let name = pass.layer;
|
|
3302
|
+
for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
|
|
3303
|
+
names.push(name);
|
|
3304
|
+
return { name, layer, pass };
|
|
3305
|
+
});
|
|
3306
|
+
const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
|
|
3307
|
+
const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
|
|
3308
|
+
const textureLocation = pass.textureLocation ?? layer.textureLocation;
|
|
3309
|
+
let texture;
|
|
3310
|
+
if (override) {
|
|
3311
|
+
const path = isAssetKey(override) ? override.getFullPath() : override.path;
|
|
3312
|
+
texture = isAssetKey(override) && override.assetType === "textures" && path.startsWith("entity/") ? override : new AssetKey(override.namespace, path, "textures", "entity", "assets", ".png", isAssetKey(override) ? override.root : void 0);
|
|
3313
|
+
} else if (textureLocation !== void 0) {
|
|
3314
|
+
texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
|
|
3315
|
+
if (isAssetKey(modelKey)) texture.root = modelKey.root;
|
|
3316
|
+
} else {
|
|
3317
|
+
texture = await this.resolveTexture(modelKey);
|
|
3318
|
+
}
|
|
3319
|
+
const render = pass.render ?? layer.render;
|
|
3320
|
+
return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
|
|
3321
|
+
})));
|
|
3322
|
+
return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
|
|
3323
|
+
}
|
|
3324
|
+
/**
|
|
3325
|
+
* Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
|
|
3326
|
+
*/
|
|
3327
|
+
static async getAnimations(modelKey) {
|
|
3328
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3329
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
|
|
3330
|
+
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
3331
|
+
return file?.animations;
|
|
3332
|
+
}
|
|
3333
|
+
static async resolveTexture(modelKey) {
|
|
3334
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3335
|
+
const root = isAssetKey(modelKey) ? modelKey.root : void 0;
|
|
3336
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", root);
|
|
3337
|
+
return Caching.entityTextureCache.get(key.serialize(), async () => {
|
|
3338
|
+
const name = path.split("/").pop();
|
|
3339
|
+
for (const candidate of [path, `${path}/${name}`]) {
|
|
3340
|
+
const texture2 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
|
|
3341
|
+
if (await ModelTextures.get(texture2)) return texture2;
|
|
3342
|
+
}
|
|
3343
|
+
const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json", root);
|
|
3344
|
+
const list = await AssetLoader.get(listKey, "list" /* LIST */);
|
|
3345
|
+
const files = list?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
|
|
3346
|
+
const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
|
|
3347
|
+
if (!file) return void 0;
|
|
3348
|
+
const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json", root);
|
|
3349
|
+
const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
|
|
3350
|
+
const assets = variant?.assets;
|
|
3351
|
+
const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
|
|
3352
|
+
if (typeof textureId !== "string") return void 0;
|
|
3353
|
+
const texture = AssetKey.parse("textures", textureId);
|
|
3354
|
+
texture.root = root;
|
|
3355
|
+
return texture;
|
|
3356
|
+
});
|
|
3357
|
+
}
|
|
3358
|
+
/** @deprecated Use getEntityList(); block entities share the entity dataset. */
|
|
3359
|
+
static getBlockList() {
|
|
3360
|
+
return this.getEntityList();
|
|
3361
|
+
}
|
|
3362
|
+
/** @deprecated Use getEntity(); block entities share the entity dataset. */
|
|
3363
|
+
static getBlock(modelKey, textureKey, options) {
|
|
3364
|
+
return this.getEntity(modelKey, textureKey, options);
|
|
3365
|
+
}
|
|
3366
|
+
};
|
|
3367
|
+
}
|
|
3368
|
+
});
|
|
3369
|
+
|
|
3370
|
+
// src/entity/EntityAnimation.ts
|
|
3371
|
+
function catmullRom(delta, p0, p1, p22, p32) {
|
|
3372
|
+
return 0.5 * (2 * p1 + (p22 - p0) * delta + (2 * p0 - 5 * p1 + 4 * p22 - p32) * delta * delta + (3 * p1 - p0 - 3 * p22 + p32) * delta * delta * delta);
|
|
3373
|
+
}
|
|
3374
|
+
function sampleEntityKeyframes(keyframes, time) {
|
|
3375
|
+
if (keyframes.length === 0) return [0, 0, 0];
|
|
3376
|
+
let low = 0, high = keyframes.length;
|
|
3377
|
+
while (low < high) {
|
|
3378
|
+
const middle = low + high >>> 1;
|
|
3379
|
+
if (time <= keyframes[middle].time) high = middle;
|
|
3380
|
+
else low = middle + 1;
|
|
3381
|
+
}
|
|
3382
|
+
const a = Math.max(0, low - 1);
|
|
3383
|
+
const b = Math.min(keyframes.length - 1, a + 1);
|
|
3384
|
+
const from = keyframes[a];
|
|
3385
|
+
const to = keyframes[b];
|
|
3386
|
+
const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
|
|
3387
|
+
if (to.interpolation === "catmullrom") {
|
|
3388
|
+
const before = keyframes[Math.max(0, a - 1)].value;
|
|
3389
|
+
const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
|
|
3390
|
+
return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
|
|
3391
|
+
}
|
|
3392
|
+
const target = to.pre ?? to.value;
|
|
3393
|
+
return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
|
|
3394
|
+
}
|
|
3395
|
+
function entityAnimationTime(animation, time, loop = animation.loop) {
|
|
3396
|
+
return loop && animation.length > 0 ? time % animation.length : time;
|
|
3397
|
+
}
|
|
3398
|
+
function sampleEntityAnimation(animation, time, loop = animation.loop) {
|
|
3399
|
+
const elapsed = entityAnimationTime(animation, time, loop);
|
|
3400
|
+
const pose = {};
|
|
3401
|
+
for (const [name, bone] of Object.entries(animation.bones)) {
|
|
3402
|
+
const sampled = pose[name] = {};
|
|
3403
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
3404
|
+
const keyframes = bone[channel];
|
|
3405
|
+
if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
return pose;
|
|
3409
|
+
}
|
|
3410
|
+
var ENTITY_ANIMATION_CHANNELS;
|
|
3411
|
+
var init_EntityAnimation = __esm({
|
|
3412
|
+
"src/entity/EntityAnimation.ts"() {
|
|
3413
|
+
ENTITY_ANIMATION_CHANNELS = ["position", "rotation", "scale"];
|
|
3414
|
+
}
|
|
3415
|
+
});
|
|
3416
|
+
|
|
3417
|
+
// src/entity/scene/EntityAnimationPlayer.ts
|
|
3418
|
+
var ZERO, EntityAnimationPlayer;
|
|
3419
|
+
var init_EntityAnimationPlayer = __esm({
|
|
3420
|
+
"src/entity/scene/EntityAnimationPlayer.ts"() {
|
|
3421
|
+
init_EntityAnimation();
|
|
3422
|
+
ZERO = [0, 0, 0];
|
|
3423
|
+
EntityAnimationPlayer = class {
|
|
3424
|
+
constructor() {
|
|
3425
|
+
this.parts = [];
|
|
3426
|
+
this._time = 0;
|
|
3427
|
+
this.loop = false;
|
|
3428
|
+
this.speed = 1;
|
|
3429
|
+
}
|
|
3430
|
+
get animation() {
|
|
3431
|
+
return this._animation;
|
|
3432
|
+
}
|
|
3433
|
+
get time() {
|
|
3434
|
+
return this._time;
|
|
3435
|
+
}
|
|
3436
|
+
/**
|
|
3437
|
+
* Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
|
|
3438
|
+
* bones without a matching part are skipped.
|
|
3439
|
+
*/
|
|
3440
|
+
play(layers, animation, options = {}) {
|
|
3441
|
+
this.stop();
|
|
3442
|
+
this._animation = animation;
|
|
3443
|
+
this._time = options.time ?? 0;
|
|
3444
|
+
this.loop = options.loop ?? animation.loop;
|
|
3445
|
+
this.speed = options.speed ?? 1;
|
|
3446
|
+
for (const layer of layers) {
|
|
3447
|
+
for (const bone of Object.keys(animation.bones)) {
|
|
3448
|
+
const object = layer.getObjectByName(`group:${bone}`);
|
|
3449
|
+
if (!object) continue;
|
|
3450
|
+
this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
this.apply();
|
|
3454
|
+
}
|
|
3455
|
+
/** Restores the default poses. Returns whether an animation was active. */
|
|
3456
|
+
stop() {
|
|
3457
|
+
if (!this._animation) return false;
|
|
3458
|
+
for (const part of this.parts) {
|
|
3459
|
+
part.object.position.copy(part.position);
|
|
3460
|
+
part.object.rotation.copy(part.rotation);
|
|
3461
|
+
part.object.scale.copy(part.scale);
|
|
3462
|
+
}
|
|
3463
|
+
this.clear();
|
|
3464
|
+
return true;
|
|
3465
|
+
}
|
|
3466
|
+
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
3467
|
+
clear() {
|
|
3468
|
+
this.parts = [];
|
|
3469
|
+
this._animation = void 0;
|
|
3470
|
+
this._time = 0;
|
|
3471
|
+
}
|
|
3472
|
+
setTime(seconds) {
|
|
3473
|
+
if (!this._animation) return false;
|
|
3474
|
+
this._time = seconds;
|
|
3475
|
+
this.apply();
|
|
3476
|
+
return true;
|
|
3477
|
+
}
|
|
3478
|
+
advance(deltaSeconds) {
|
|
3479
|
+
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
3480
|
+
}
|
|
3481
|
+
apply() {
|
|
3482
|
+
const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
|
|
3483
|
+
for (const part of this.parts) {
|
|
3484
|
+
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
|
|
3485
|
+
part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
|
|
3486
|
+
part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
|
|
3487
|
+
part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
3490
|
+
};
|
|
3491
|
+
}
|
|
3492
|
+
});
|
|
3493
|
+
|
|
3117
3494
|
// src/instance/InstanceReference.ts
|
|
3118
3495
|
function isInstanceReference(obj) {
|
|
3119
3496
|
return obj.isInstanceReference;
|
|
@@ -3611,6 +3988,242 @@ var init_SceneObject = __esm({
|
|
|
3611
3988
|
}
|
|
3612
3989
|
});
|
|
3613
3990
|
|
|
3991
|
+
// src/entity/scene/EntityObject.ts
|
|
3992
|
+
import { Color as Color3, Euler as Euler4, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
|
|
3993
|
+
function isEntityObject(obj) {
|
|
3994
|
+
return obj.isEntityObject;
|
|
3995
|
+
}
|
|
3996
|
+
var import_ts_deepmerge4, EntityObject;
|
|
3997
|
+
var init_EntityObject = __esm({
|
|
3998
|
+
"src/entity/scene/EntityObject.ts"() {
|
|
3999
|
+
init_SceneObject();
|
|
4000
|
+
init_Caching();
|
|
4001
|
+
import_ts_deepmerge4 = __toESM(require_dist());
|
|
4002
|
+
init_Ticker();
|
|
4003
|
+
init_model();
|
|
4004
|
+
init_ModelTextures();
|
|
4005
|
+
init_AssetKey();
|
|
4006
|
+
init_Materials();
|
|
4007
|
+
init_MinecraftCubeTexture();
|
|
4008
|
+
init_three();
|
|
4009
|
+
init_EntityAnimationPlayer();
|
|
4010
|
+
EntityObject = class _EntityObject extends SceneObject {
|
|
4011
|
+
constructor(entity, options) {
|
|
4012
|
+
super();
|
|
4013
|
+
this.entity = entity;
|
|
4014
|
+
this.isEntityObject = true;
|
|
4015
|
+
this.meshesCreated = false;
|
|
4016
|
+
this.geometries = /* @__PURE__ */ new Set();
|
|
4017
|
+
this.disposeWireframes = [];
|
|
4018
|
+
/** Scrolling materials are owned: their texture offset follows this entity's age. */
|
|
4019
|
+
this.scrollMaterials = [];
|
|
4020
|
+
/** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
|
|
4021
|
+
this.age = 0;
|
|
4022
|
+
this.animationPlayer = new EntityAnimationPlayer();
|
|
4023
|
+
this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
|
|
4024
|
+
this.addEventListener("added", () => this.updateScrollSubscription());
|
|
4025
|
+
this.addEventListener("removed", () => this.updateScrollSubscription());
|
|
4026
|
+
}
|
|
4027
|
+
static {
|
|
4028
|
+
this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
|
|
4029
|
+
}
|
|
4030
|
+
async init() {
|
|
4031
|
+
this.createMeshes();
|
|
4032
|
+
await this.applyTextures();
|
|
4033
|
+
}
|
|
4034
|
+
dispose() {
|
|
4035
|
+
super.dispose();
|
|
4036
|
+
}
|
|
4037
|
+
disposeAndRemoveAllChildren() {
|
|
4038
|
+
this.clearScrollMaterials();
|
|
4039
|
+
for (const geometry of this.geometries) geometry.dispose();
|
|
4040
|
+
this.geometries.clear();
|
|
4041
|
+
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
4042
|
+
this.animationPlayer.clear();
|
|
4043
|
+
super.disposeAndRemoveAllChildren();
|
|
4044
|
+
}
|
|
4045
|
+
clearScrollMaterials() {
|
|
4046
|
+
Ticker.remove(this.scrollTicker);
|
|
4047
|
+
this.scrollTicker = void 0;
|
|
4048
|
+
for (const { material } of this.scrollMaterials.splice(0)) {
|
|
4049
|
+
material.map?.dispose();
|
|
4050
|
+
material.dispose();
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
updateScrollSubscription() {
|
|
4054
|
+
if (this.parent && this.scrollMaterials.length) {
|
|
4055
|
+
if (this.scrollTicker === void 0) {
|
|
4056
|
+
this.scrollTicker = Ticker.add(() => {
|
|
4057
|
+
this.age++;
|
|
4058
|
+
this.updateScroll();
|
|
4059
|
+
});
|
|
4060
|
+
}
|
|
4061
|
+
} else {
|
|
4062
|
+
Ticker.remove(this.scrollTicker);
|
|
4063
|
+
this.scrollTicker = void 0;
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
/** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
|
|
4067
|
+
updateScroll() {
|
|
4068
|
+
for (const { offset, speed } of this.scrollMaterials) {
|
|
4069
|
+
offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
|
|
4070
|
+
}
|
|
4071
|
+
this.notifyDirty();
|
|
4072
|
+
}
|
|
4073
|
+
//<editor-fold desc="ANIMATION">
|
|
4074
|
+
/** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
|
|
4075
|
+
get animation() {
|
|
4076
|
+
return this.animationPlayer.animation;
|
|
4077
|
+
}
|
|
4078
|
+
/** Seconds since the animation started, before looping. */
|
|
4079
|
+
get animationTime() {
|
|
4080
|
+
return this.animationPlayer.time;
|
|
4081
|
+
}
|
|
4082
|
+
/**
|
|
4083
|
+
* Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
|
|
4084
|
+
* Parts of every layer are matched by name and their current pose is the default the offsets add to.
|
|
4085
|
+
* The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
|
|
4086
|
+
*/
|
|
4087
|
+
playAnimation(animation, options) {
|
|
4088
|
+
this.createMeshes();
|
|
4089
|
+
const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
|
|
4090
|
+
this.animationPlayer.play(layers, animation, options);
|
|
4091
|
+
this.notifyDirty();
|
|
4092
|
+
}
|
|
4093
|
+
/** Stops the animation and restores the default pose. */
|
|
4094
|
+
stopAnimation() {
|
|
4095
|
+
if (this.animationPlayer.stop()) this.notifyDirty();
|
|
4096
|
+
}
|
|
4097
|
+
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
4098
|
+
setAnimationTime(seconds) {
|
|
4099
|
+
if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
|
|
4100
|
+
}
|
|
4101
|
+
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
4102
|
+
advanceAnimation(deltaSeconds) {
|
|
4103
|
+
if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
|
|
4104
|
+
}
|
|
4105
|
+
//</editor-fold>
|
|
4106
|
+
getLayerGroup(name) {
|
|
4107
|
+
return super.getGroupByName(`layer:${name}`);
|
|
4108
|
+
}
|
|
4109
|
+
getGroupByName(name, layerName) {
|
|
4110
|
+
return layerName === void 0 ? super.getGroupByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);
|
|
4111
|
+
}
|
|
4112
|
+
getMeshByName(name, layerName) {
|
|
4113
|
+
return layerName === void 0 ? super.getMeshByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`);
|
|
4114
|
+
}
|
|
4115
|
+
get entityLayers() {
|
|
4116
|
+
return this.entity.layers ?? { main: this.entity };
|
|
4117
|
+
}
|
|
4118
|
+
getTextureKey(layer) {
|
|
4119
|
+
if (layer.texture) return layer.texture;
|
|
4120
|
+
const key = layer.key;
|
|
4121
|
+
return new AssetKey(
|
|
4122
|
+
key.namespace,
|
|
4123
|
+
isAssetKey(key) ? key.getFullPath() : key.path,
|
|
4124
|
+
"textures",
|
|
4125
|
+
"entity",
|
|
4126
|
+
"assets",
|
|
4127
|
+
".png"
|
|
4128
|
+
);
|
|
4129
|
+
}
|
|
4130
|
+
async loadTextures(layer = this.entity) {
|
|
4131
|
+
return ModelTextures.get(this.getTextureKey(layer));
|
|
4132
|
+
}
|
|
4133
|
+
createMeshes(force = false) {
|
|
4134
|
+
if (this.meshesCreated && !force) return;
|
|
4135
|
+
const modelRoot = new Object3D3();
|
|
4136
|
+
const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
|
|
4137
|
+
if (transform) {
|
|
4138
|
+
for (const op of transform) {
|
|
4139
|
+
const matrix = new Matrix45();
|
|
4140
|
+
if ("scale" in op) matrix.makeScale(...op.scale);
|
|
4141
|
+
else if ("translate" in op) matrix.makeTranslation(...op.translate);
|
|
4142
|
+
else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
|
|
4143
|
+
modelRoot.matrix.multiply(matrix);
|
|
4144
|
+
}
|
|
4145
|
+
modelRoot.matrixAutoUpdate = false;
|
|
4146
|
+
} else if (this.options.flip ?? true) {
|
|
4147
|
+
modelRoot.scale.set(-1, -1, 1);
|
|
4148
|
+
}
|
|
4149
|
+
this.add(modelRoot);
|
|
4150
|
+
Object.entries(this.entityLayers).forEach(([name, layer], index) => {
|
|
4151
|
+
const group = this.createGroup(`layer:${name}`);
|
|
4152
|
+
modelRoot.add(group);
|
|
4153
|
+
const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
|
|
4154
|
+
this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
|
|
4155
|
+
});
|
|
4156
|
+
this.meshesCreated = true;
|
|
4157
|
+
}
|
|
4158
|
+
createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
|
|
4159
|
+
const anchor = this.createGroup(name);
|
|
4160
|
+
anchor.position.fromArray(part.pose.offset);
|
|
4161
|
+
anchor.rotation.set(...part.pose.rotation, "ZYX");
|
|
4162
|
+
anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
|
|
4163
|
+
parent.add(anchor);
|
|
4164
|
+
const size = part.texture ?? textureSize;
|
|
4165
|
+
for (const cube of part.cubes) {
|
|
4166
|
+
const [width, height, depth] = cube.size;
|
|
4167
|
+
const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];
|
|
4168
|
+
const texture = new MinecraftCubeTexture(...cube.uv, ...size);
|
|
4169
|
+
const uv = size[0] === 0 || size[1] === 0 ? new Array(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);
|
|
4170
|
+
const geometry = this._getBoxGeometryForDimensionsAndUv(
|
|
4171
|
+
width + growX * 2,
|
|
4172
|
+
height + growY * 2,
|
|
4173
|
+
depth + growZ * 2,
|
|
4174
|
+
uv
|
|
4175
|
+
).clone();
|
|
4176
|
+
this.geometries.add(geometry);
|
|
4177
|
+
geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
|
|
4178
|
+
if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
|
|
4179
|
+
const index = Array.from(geometry.getIndex().array);
|
|
4180
|
+
geometry.setIndex(index.concat(index.slice().reverse()));
|
|
4181
|
+
}
|
|
4182
|
+
const mesh = this.createMesh(name, geometry, material);
|
|
4183
|
+
mesh.renderOrder = renderOrder;
|
|
4184
|
+
anchor.add(mesh);
|
|
4185
|
+
if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));
|
|
4186
|
+
}
|
|
4187
|
+
for (const [childName, child] of Object.entries(part.children)) {
|
|
4188
|
+
this.createPart(childName, child, anchor, size, material, renderOrder, inward);
|
|
4189
|
+
}
|
|
4190
|
+
}
|
|
4191
|
+
async applyTextures() {
|
|
4192
|
+
this.clearScrollMaterials();
|
|
4193
|
+
await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
|
|
4194
|
+
const mode = layer.render ?? layer.layer.render ?? "cutout";
|
|
4195
|
+
const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
|
|
4196
|
+
const scroll = Materials.entityModeScroll(mode);
|
|
4197
|
+
const assetKeyStr = this.getTextureKey(layer).serialize();
|
|
4198
|
+
const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color3(tint).getHexString()}:${assetKeyStr}`;
|
|
4199
|
+
let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
|
|
4200
|
+
if (!mat) {
|
|
4201
|
+
const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
|
|
4202
|
+
const imageData = await this.loadTextures(layer);
|
|
4203
|
+
if (!imageData) return;
|
|
4204
|
+
const canvas = imageData.data.canvas;
|
|
4205
|
+
const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
|
|
4206
|
+
mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
|
|
4207
|
+
if (scroll) {
|
|
4208
|
+
this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
this.getLayerGroup(name)?.traverse((object) => {
|
|
4212
|
+
if (isMesh(object)) object.material = mat;
|
|
4213
|
+
});
|
|
4214
|
+
}));
|
|
4215
|
+
if (!this.children.length) {
|
|
4216
|
+
this.clearScrollMaterials();
|
|
4217
|
+
} else if (this.scrollMaterials.length) {
|
|
4218
|
+
this.updateScroll();
|
|
4219
|
+
}
|
|
4220
|
+
this.updateScrollSubscription();
|
|
4221
|
+
this.notifyDirty();
|
|
4222
|
+
}
|
|
4223
|
+
};
|
|
4224
|
+
}
|
|
4225
|
+
});
|
|
4226
|
+
|
|
3614
4227
|
// src/three/BufferGeometryUtils.js
|
|
3615
4228
|
import {
|
|
3616
4229
|
BufferAttribute as BufferAttribute4,
|
|
@@ -4199,8 +4812,121 @@ var init_ModelCulling = __esm({
|
|
|
4199
4812
|
}
|
|
4200
4813
|
});
|
|
4201
4814
|
|
|
4815
|
+
// src/model/SpecialItems.ts
|
|
4816
|
+
import { Matrix4 as Matrix48 } from "three";
|
|
4817
|
+
var SpecialItems;
|
|
4818
|
+
var init_SpecialItems = __esm({
|
|
4819
|
+
"src/model/SpecialItems.ts"() {
|
|
4820
|
+
init_AssetKey();
|
|
4821
|
+
init_Entities();
|
|
4822
|
+
SpecialItems = class {
|
|
4823
|
+
/** Resolves the static entity parts drawn by a special item renderer, in model units. */
|
|
4824
|
+
static async getParts(special, root) {
|
|
4825
|
+
const texture = (id, directory) => {
|
|
4826
|
+
const key = AssetKey.parse("textures", id);
|
|
4827
|
+
return new AssetKey(
|
|
4828
|
+
key.namespace,
|
|
4829
|
+
[directory, key.getFullPath()].filter(Boolean).join("/"),
|
|
4830
|
+
"textures",
|
|
4831
|
+
"entity",
|
|
4832
|
+
"assets",
|
|
4833
|
+
".png",
|
|
4834
|
+
root
|
|
4835
|
+
);
|
|
4836
|
+
};
|
|
4837
|
+
const load = async (id, textureKey, transform, rotations = {}) => {
|
|
4838
|
+
const key = new AssetKey("minecraft", id, void 0, void 0, "entity-models", ".json", root);
|
|
4839
|
+
const model = await Entities.getEntity(key, textureKey, { layer: "main" });
|
|
4840
|
+
if (!model) throw new Error(`Missing entity model minecraft:${id} for special item ${special.type}`);
|
|
4841
|
+
return { model, transform, rotations };
|
|
4842
|
+
};
|
|
4843
|
+
switch (special.type) {
|
|
4844
|
+
case "minecraft:chest":
|
|
4845
|
+
case "chest": {
|
|
4846
|
+
const angle = -(special.openness ?? 0) * Math.PI / 2;
|
|
4847
|
+
const chest = await load("chest", texture(special.texture, "chest"), new Matrix48(), {
|
|
4848
|
+
lid: [angle, 0, 0],
|
|
4849
|
+
lock: [angle, 0, 0]
|
|
4850
|
+
});
|
|
4851
|
+
chest.model = { ...chest.model, render: "solid", layers: void 0 };
|
|
4852
|
+
return [chest];
|
|
4853
|
+
}
|
|
4854
|
+
case "minecraft:bed":
|
|
4855
|
+
case "bed": {
|
|
4856
|
+
const transform = new Matrix48().makeTranslation(0, 9, 0).multiply(new Matrix48().makeRotationX(Math.PI / 2)).multiply(new Matrix48().makeTranslation(8, 8, 8)).multiply(new Matrix48().makeRotationZ(Math.PI)).multiply(new Matrix48().makeTranslation(-8, -8, -8));
|
|
4857
|
+
const key = texture(special.texture, "bed");
|
|
4858
|
+
return Promise.all([
|
|
4859
|
+
load("bed_head", key, transform),
|
|
4860
|
+
load("bed_foot", key, new Matrix48().makeTranslation(0, 0, -16).multiply(transform))
|
|
4861
|
+
]);
|
|
4862
|
+
}
|
|
4863
|
+
case "minecraft:head":
|
|
4864
|
+
case "head": {
|
|
4865
|
+
const models = {
|
|
4866
|
+
skeleton: "skeleton_skull",
|
|
4867
|
+
wither_skeleton: "wither_skeleton_skull",
|
|
4868
|
+
zombie: "zombie_head",
|
|
4869
|
+
creeper: "creeper_head",
|
|
4870
|
+
dragon: "dragon_skull",
|
|
4871
|
+
piglin: "piglin_head"
|
|
4872
|
+
};
|
|
4873
|
+
const id = Object.prototype.hasOwnProperty.call(models, special.kind) ? models[special.kind] : void 0;
|
|
4874
|
+
if (!id) throw new Error(`Unsupported special item head kind ${special.kind}`);
|
|
4875
|
+
const animation = (special.animation ?? 0) * Math.PI * 0.2;
|
|
4876
|
+
const rotations = { head: [0, Math.PI, 0] };
|
|
4877
|
+
if (special.kind === "dragon") rotations.jaw = [(Math.sin(animation) + 1) * 0.2, 0, 0];
|
|
4878
|
+
if (special.kind === "piglin") {
|
|
4879
|
+
rotations.left_ear = [0, 0, -(Math.cos(animation * 1.2) + 2.5) * 0.2];
|
|
4880
|
+
rotations.right_ear = [0, 0, (Math.cos(animation) + 2.5) * 0.2];
|
|
4881
|
+
}
|
|
4882
|
+
return [await load(
|
|
4883
|
+
id,
|
|
4884
|
+
special.texture ? texture(special.texture, "") : void 0,
|
|
4885
|
+
new Matrix48().makeTranslation(8, 0, 8).multiply(new Matrix48().makeScale(-1, -1, 1)),
|
|
4886
|
+
rotations
|
|
4887
|
+
)];
|
|
4888
|
+
}
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
/** An owned material with model-preview shading; its entity texture remains shared. */
|
|
4892
|
+
static createMaterial(source, shade) {
|
|
4893
|
+
const material = source.clone();
|
|
4894
|
+
if (shade) {
|
|
4895
|
+
material.onBeforeCompile = (shader) => {
|
|
4896
|
+
shader.vertexShader = `varying float itemLight;
|
|
4897
|
+
${shader.vertexShader}`.replace("#include <begin_vertex>", `
|
|
4898
|
+
#include <begin_vertex>
|
|
4899
|
+
vec3 N = inverseTransformDirection(normalMatrix * normal, viewMatrix);
|
|
4900
|
+
itemLight = (1.0 + N.y) * 0.25 - N.x * N.x * 0.15 + N.z * N.z * 0.05 + 0.5;
|
|
4901
|
+
`);
|
|
4902
|
+
shader.fragmentShader = `varying float itemLight;
|
|
4903
|
+
${shader.fragmentShader}`.replace(
|
|
4904
|
+
"#include <color_fragment>",
|
|
4905
|
+
"#include <color_fragment>\ndiffuseColor.rgb *= itemLight;"
|
|
4906
|
+
);
|
|
4907
|
+
};
|
|
4908
|
+
material.customProgramCacheKey = () => "special-item-side";
|
|
4909
|
+
}
|
|
4910
|
+
return material;
|
|
4911
|
+
}
|
|
4912
|
+
};
|
|
4913
|
+
}
|
|
4914
|
+
});
|
|
4915
|
+
|
|
4916
|
+
// src/model/GuiLight.ts
|
|
4917
|
+
var GuiLight;
|
|
4918
|
+
var init_GuiLight = __esm({
|
|
4919
|
+
"src/model/GuiLight.ts"() {
|
|
4920
|
+
GuiLight = /* @__PURE__ */ ((GuiLight2) => {
|
|
4921
|
+
GuiLight2["FRONT"] = "front";
|
|
4922
|
+
GuiLight2["SIDE"] = "side";
|
|
4923
|
+
return GuiLight2;
|
|
4924
|
+
})(GuiLight || {});
|
|
4925
|
+
}
|
|
4926
|
+
});
|
|
4927
|
+
|
|
4202
4928
|
// src/model/scene/ModelObject.ts
|
|
4203
|
-
import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as
|
|
4929
|
+
import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as Matrix49 } from "three";
|
|
4204
4930
|
function isModelObject(obj) {
|
|
4205
4931
|
return obj.isModelObject;
|
|
4206
4932
|
}
|
|
@@ -4215,16 +4941,22 @@ var init_ModelObject = __esm({
|
|
|
4215
4941
|
import_ts_deepmerge5 = __toESM(require_dist());
|
|
4216
4942
|
init_log();
|
|
4217
4943
|
init_CubeFace();
|
|
4944
|
+
init_DisplayPosition();
|
|
4218
4945
|
init_DisplayTransforms();
|
|
4219
4946
|
init_ModelCulling();
|
|
4947
|
+
init_SpecialItems();
|
|
4948
|
+
init_EntityObject();
|
|
4949
|
+
init_GuiLight();
|
|
4220
4950
|
p7 = prefix("ModelObject");
|
|
4221
4951
|
ModelObject = class _ModelObject extends SceneObject {
|
|
4222
4952
|
constructor(originalModel, options) {
|
|
4223
4953
|
super(options);
|
|
4224
4954
|
this.originalModel = originalModel;
|
|
4225
4955
|
this.isModelObject = true;
|
|
4956
|
+
this.specialMaterials = /* @__PURE__ */ new Map();
|
|
4226
4957
|
this.meshesCreated = false;
|
|
4227
4958
|
this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
|
|
4959
|
+
if (originalModel.special) this.options.instanceMeshes = false;
|
|
4228
4960
|
if (this.options.tints) this.options.tints = { ...this.options.tints };
|
|
4229
4961
|
this.addEventListener("added", () => this.updateAnimationSubscription());
|
|
4230
4962
|
this.addEventListener("removed", () => this.updateAnimationSubscription());
|
|
@@ -4233,6 +4965,39 @@ var init_ModelObject = __esm({
|
|
|
4233
4965
|
this.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
|
|
4234
4966
|
}
|
|
4235
4967
|
async init() {
|
|
4968
|
+
const special = this.originalModel.special;
|
|
4969
|
+
if (special) {
|
|
4970
|
+
const parts = await SpecialItems.getParts(special, this.originalModel.key?.root);
|
|
4971
|
+
const transform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : new Matrix49();
|
|
4972
|
+
transform.multiply(new Matrix49().makeTranslation(-8, -8, -8));
|
|
4973
|
+
try {
|
|
4974
|
+
for (const part of parts) {
|
|
4975
|
+
const object = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe });
|
|
4976
|
+
object.matrix.copy(transform).multiply(part.transform);
|
|
4977
|
+
object.matrixAutoUpdate = false;
|
|
4978
|
+
this.add(object);
|
|
4979
|
+
await object.init();
|
|
4980
|
+
object.iterateAllMeshes((mesh) => {
|
|
4981
|
+
const source = mesh.material;
|
|
4982
|
+
let material = this.specialMaterials.get(source);
|
|
4983
|
+
if (!material) {
|
|
4984
|
+
const front = this.options.displayPosition === "gui" /* GUI */ && this.originalModel.gui_light === "front" /* FRONT */;
|
|
4985
|
+
material = SpecialItems.createMaterial(source, !front);
|
|
4986
|
+
this.specialMaterials.set(source, material);
|
|
4987
|
+
}
|
|
4988
|
+
mesh.material = material;
|
|
4989
|
+
});
|
|
4990
|
+
for (const [name, rotation] of Object.entries(part.rotations)) {
|
|
4991
|
+
object.getGroupByName(name)?.rotation.set(...rotation, "ZYX");
|
|
4992
|
+
}
|
|
4993
|
+
}
|
|
4994
|
+
} catch (error) {
|
|
4995
|
+
this.disposeAndRemoveAllChildren();
|
|
4996
|
+
throw error;
|
|
4997
|
+
}
|
|
4998
|
+
this.notifyDirty();
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
4236
5001
|
await this.loadTextures();
|
|
4237
5002
|
this.createMeshes();
|
|
4238
5003
|
this.applyTextures();
|
|
@@ -4282,12 +5047,12 @@ var init_ModelObject = __esm({
|
|
|
4282
5047
|
}
|
|
4283
5048
|
elGeo.setAttribute("color", new BufferAttribute5(colors, 3));
|
|
4284
5049
|
}
|
|
4285
|
-
elGeo.applyMatrix4(new
|
|
4286
|
-
elGeo.applyMatrix4(new
|
|
5050
|
+
elGeo.applyMatrix4(new Matrix49().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
|
|
5051
|
+
elGeo.applyMatrix4(new Matrix49().makeTranslation(el.from[0], el.from[1], el.from[2]));
|
|
4287
5052
|
if (el.rotation) {
|
|
4288
5053
|
applyElementRotation(el.rotation, elGeo);
|
|
4289
5054
|
}
|
|
4290
|
-
elGeo.applyMatrix4(new
|
|
5055
|
+
elGeo.applyMatrix4(new Matrix49().makeTranslation(-8, -8, -8));
|
|
4291
5056
|
if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
|
|
4292
5057
|
if (this.options.mergeMeshes) {
|
|
4293
5058
|
allGeos.push(elGeo);
|
|
@@ -4377,6 +5142,8 @@ var init_ModelObject = __esm({
|
|
|
4377
5142
|
this.atlasMaterial?.dispose();
|
|
4378
5143
|
this.atlasTexture = void 0;
|
|
4379
5144
|
this.atlasMaterial = void 0;
|
|
5145
|
+
for (const material of this.specialMaterials.values()) material.dispose();
|
|
5146
|
+
this.specialMaterials.clear();
|
|
4380
5147
|
super.disposeAndRemoveAllChildren();
|
|
4381
5148
|
}
|
|
4382
5149
|
};
|
|
@@ -4727,96 +5494,8 @@ var Meshes = class _Meshes {
|
|
|
4727
5494
|
}
|
|
4728
5495
|
};
|
|
4729
5496
|
|
|
4730
|
-
// src/
|
|
4731
|
-
|
|
4732
|
-
init_CubeFace();
|
|
4733
|
-
var MinecraftCubeTexture = class {
|
|
4734
|
-
constructor(u, v, width, height) {
|
|
4735
|
-
this.u = u;
|
|
4736
|
-
this.v = v;
|
|
4737
|
-
this.width = width;
|
|
4738
|
-
this.height = height;
|
|
4739
|
-
}
|
|
4740
|
-
mapW(x) {
|
|
4741
|
-
return x / this.width;
|
|
4742
|
-
}
|
|
4743
|
-
mapH(x) {
|
|
4744
|
-
return 1 - x / this.height;
|
|
4745
|
-
}
|
|
4746
|
-
getUvEast(w, h, l) {
|
|
4747
|
-
return [
|
|
4748
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
4749
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
4750
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)],
|
|
4751
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
4752
|
-
];
|
|
4753
|
-
}
|
|
4754
|
-
getUvWest(w, h, l) {
|
|
4755
|
-
return [
|
|
4756
|
-
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
4757
|
-
[this.mapW(this.u), this.mapH(this.v + l + h)],
|
|
4758
|
-
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
4759
|
-
[this.mapW(this.u), this.mapH(this.v + l)]
|
|
4760
|
-
];
|
|
4761
|
-
}
|
|
4762
|
-
getUvUp(w, h, l) {
|
|
4763
|
-
return [
|
|
4764
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
4765
|
-
[this.mapW(this.u + l + w + w), this.mapH(this.v + l)],
|
|
4766
|
-
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
4767
|
-
[this.mapW(this.u + l + w + w), this.mapH(this.v)]
|
|
4768
|
-
];
|
|
4769
|
-
}
|
|
4770
|
-
getUvDown(w, h, l) {
|
|
4771
|
-
return [
|
|
4772
|
-
[this.mapW(this.u + l), this.mapH(this.v)],
|
|
4773
|
-
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
4774
|
-
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
4775
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
4776
|
-
];
|
|
4777
|
-
}
|
|
4778
|
-
getUvSouth(w, h, l) {
|
|
4779
|
-
return [
|
|
4780
|
-
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l + h)],
|
|
4781
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
4782
|
-
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l)],
|
|
4783
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)]
|
|
4784
|
-
];
|
|
4785
|
-
}
|
|
4786
|
-
getUvNorth(w, h, l) {
|
|
4787
|
-
return [
|
|
4788
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
4789
|
-
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
4790
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
4791
|
-
[this.mapW(this.u + l), this.mapH(this.v + l)]
|
|
4792
|
-
];
|
|
4793
|
-
}
|
|
4794
|
-
getFaceUv(face, w, h, l) {
|
|
4795
|
-
switch (face) {
|
|
4796
|
-
case "east" /* EAST */:
|
|
4797
|
-
return this.getUvEast(w, h, l);
|
|
4798
|
-
case "west" /* WEST */:
|
|
4799
|
-
return this.getUvWest(w, h, l);
|
|
4800
|
-
case "up" /* UP */:
|
|
4801
|
-
return this.getUvUp(w, h, l);
|
|
4802
|
-
case "down" /* DOWN */:
|
|
4803
|
-
return this.getUvDown(w, h, l);
|
|
4804
|
-
case "south" /* SOUTH */:
|
|
4805
|
-
return this.getUvSouth(w, h, l);
|
|
4806
|
-
case "north" /* NORTH */:
|
|
4807
|
-
return this.getUvNorth(w, h, l);
|
|
4808
|
-
}
|
|
4809
|
-
}
|
|
4810
|
-
toUvArray(w, h, l, mirror = false) {
|
|
4811
|
-
const uv = [];
|
|
4812
|
-
for (let i = 0; i < CUBE_FACES.length; i++) {
|
|
4813
|
-
const face = mirror && i < 2 ? CUBE_FACES[1 - i] : CUBE_FACES[i];
|
|
4814
|
-
const corners = this.getFaceUv(face, w, h, l);
|
|
4815
|
-
UVMapper.setFaceUvInArray(uv, i * 4, mirror ? [corners[1], corners[0], corners[3], corners[2]] : corners);
|
|
4816
|
-
}
|
|
4817
|
-
return uv;
|
|
4818
|
-
}
|
|
4819
|
-
};
|
|
5497
|
+
// src/index.ts
|
|
5498
|
+
init_MinecraftCubeTexture();
|
|
4820
5499
|
|
|
4821
5500
|
// src/SceneStats.ts
|
|
4822
5501
|
var SceneStats = class {
|
|
@@ -4910,116 +5589,7 @@ var BlockEntities = class {
|
|
|
4910
5589
|
|
|
4911
5590
|
// src/assets/index.ts
|
|
4912
5591
|
init_BlockStates();
|
|
4913
|
-
|
|
4914
|
-
// src/assets/Entities.ts
|
|
4915
|
-
init_AssetKey();
|
|
4916
|
-
init_AssetLoader();
|
|
4917
|
-
init_source();
|
|
4918
|
-
init_Caching();
|
|
4919
|
-
init_Assets();
|
|
4920
|
-
init_MineRenderError();
|
|
4921
|
-
init_ModelTextures();
|
|
4922
|
-
var Entities = class {
|
|
4923
|
-
static async getEntityList() {
|
|
4924
|
-
const collect = async (path) => {
|
|
4925
|
-
const prefix2 = path ? `${path}/` : "";
|
|
4926
|
-
const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
|
|
4927
|
-
const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
|
|
4928
|
-
if (!list) return [];
|
|
4929
|
-
const files = list.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
|
|
4930
|
-
const children = await Promise.all(list.directories.map((directory) => collect(`${prefix2}${directory}`)));
|
|
4931
|
-
return [...files, ...children.flat()];
|
|
4932
|
-
};
|
|
4933
|
-
return collect("");
|
|
4934
|
-
}
|
|
4935
|
-
static async getModelFile(modelKey) {
|
|
4936
|
-
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4937
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
|
|
4938
|
-
return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4939
|
-
}
|
|
4940
|
-
static async getLayerList(modelKey) {
|
|
4941
|
-
return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
|
|
4942
|
-
}
|
|
4943
|
-
/** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
|
|
4944
|
-
static async getPassList(modelKey) {
|
|
4945
|
-
return (await this.getModelFile(modelKey))?.passes ?? [];
|
|
4946
|
-
}
|
|
4947
|
-
static async getEntity(modelKey, textureKey, options) {
|
|
4948
|
-
const model = await this.getModelFile(modelKey);
|
|
4949
|
-
if (!model) return void 0;
|
|
4950
|
-
const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
|
|
4951
|
-
const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
|
|
4952
|
-
if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
|
|
4953
|
-
draws.push(...passes);
|
|
4954
|
-
const names = [];
|
|
4955
|
-
const selected = draws.map((pass) => {
|
|
4956
|
-
const layer = model.layers[pass.layer];
|
|
4957
|
-
if (!layer) {
|
|
4958
|
-
throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
|
|
4959
|
-
}
|
|
4960
|
-
let name = pass.layer;
|
|
4961
|
-
for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
|
|
4962
|
-
names.push(name);
|
|
4963
|
-
return { name, layer, pass };
|
|
4964
|
-
});
|
|
4965
|
-
const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
|
|
4966
|
-
const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
|
|
4967
|
-
const textureLocation = pass.textureLocation ?? layer.textureLocation;
|
|
4968
|
-
let texture;
|
|
4969
|
-
if (override) {
|
|
4970
|
-
const path = isAssetKey(override) ? override.getFullPath() : override.path;
|
|
4971
|
-
texture = isAssetKey(override) && override.assetType === "textures" && path.startsWith("entity/") ? override : new AssetKey(override.namespace, path, "textures", "entity", "assets", ".png", isAssetKey(override) ? override.root : void 0);
|
|
4972
|
-
} else if (textureLocation !== void 0) {
|
|
4973
|
-
texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
|
|
4974
|
-
} else {
|
|
4975
|
-
texture = await this.resolveTexture(modelKey);
|
|
4976
|
-
}
|
|
4977
|
-
const render = pass.render ?? layer.render;
|
|
4978
|
-
return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
|
|
4979
|
-
})));
|
|
4980
|
-
return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
|
|
4981
|
-
}
|
|
4982
|
-
/**
|
|
4983
|
-
* Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
|
|
4984
|
-
*/
|
|
4985
|
-
static async getAnimations(modelKey) {
|
|
4986
|
-
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4987
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
|
|
4988
|
-
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4989
|
-
return file?.animations;
|
|
4990
|
-
}
|
|
4991
|
-
static async resolveTexture(modelKey) {
|
|
4992
|
-
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4993
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
|
|
4994
|
-
return Caching.entityTextureCache.get(key.serialize(), async () => {
|
|
4995
|
-
const name = path.split("/").pop();
|
|
4996
|
-
for (const candidate of [path, `${path}/${name}`]) {
|
|
4997
|
-
const texture = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png");
|
|
4998
|
-
if (await ModelTextures.get(texture)) return texture;
|
|
4999
|
-
}
|
|
5000
|
-
const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json");
|
|
5001
|
-
const list = await AssetLoader.get(listKey, "list" /* LIST */);
|
|
5002
|
-
const files = list?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
|
|
5003
|
-
const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
|
|
5004
|
-
if (!file) return void 0;
|
|
5005
|
-
const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json");
|
|
5006
|
-
const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
|
|
5007
|
-
const assets = variant?.assets;
|
|
5008
|
-
const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
|
|
5009
|
-
return typeof textureId === "string" ? AssetKey.parse("textures", textureId) : void 0;
|
|
5010
|
-
});
|
|
5011
|
-
}
|
|
5012
|
-
/** @deprecated Use getEntityList(); block entities share the entity dataset. */
|
|
5013
|
-
static getBlockList() {
|
|
5014
|
-
return this.getEntityList();
|
|
5015
|
-
}
|
|
5016
|
-
/** @deprecated Use getEntity(); block entities share the entity dataset. */
|
|
5017
|
-
static getBlock(modelKey, textureKey, options) {
|
|
5018
|
-
return this.getEntity(modelKey, textureKey, options);
|
|
5019
|
-
}
|
|
5020
|
-
};
|
|
5021
|
-
|
|
5022
|
-
// src/assets/index.ts
|
|
5592
|
+
init_Entities();
|
|
5023
5593
|
init_ModelTextures();
|
|
5024
5594
|
init_Models();
|
|
5025
5595
|
init_source();
|
|
@@ -5064,347 +5634,12 @@ function trimCanvas(source) {
|
|
|
5064
5634
|
return canvas;
|
|
5065
5635
|
}
|
|
5066
5636
|
|
|
5067
|
-
// src/entity/
|
|
5068
|
-
|
|
5069
|
-
function catmullRom(delta, p0, p1, p22, p32) {
|
|
5070
|
-
return 0.5 * (2 * p1 + (p22 - p0) * delta + (2 * p0 - 5 * p1 + 4 * p22 - p32) * delta * delta + (3 * p1 - p0 - 3 * p22 + p32) * delta * delta * delta);
|
|
5071
|
-
}
|
|
5072
|
-
function sampleEntityKeyframes(keyframes, time) {
|
|
5073
|
-
if (keyframes.length === 0) return [0, 0, 0];
|
|
5074
|
-
let low = 0, high = keyframes.length;
|
|
5075
|
-
while (low < high) {
|
|
5076
|
-
const middle = low + high >>> 1;
|
|
5077
|
-
if (time <= keyframes[middle].time) high = middle;
|
|
5078
|
-
else low = middle + 1;
|
|
5079
|
-
}
|
|
5080
|
-
const a = Math.max(0, low - 1);
|
|
5081
|
-
const b = Math.min(keyframes.length - 1, a + 1);
|
|
5082
|
-
const from = keyframes[a];
|
|
5083
|
-
const to = keyframes[b];
|
|
5084
|
-
const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
|
|
5085
|
-
if (to.interpolation === "catmullrom") {
|
|
5086
|
-
const before = keyframes[Math.max(0, a - 1)].value;
|
|
5087
|
-
const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
|
|
5088
|
-
return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
|
|
5089
|
-
}
|
|
5090
|
-
const target = to.pre ?? to.value;
|
|
5091
|
-
return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
|
|
5092
|
-
}
|
|
5093
|
-
function entityAnimationTime(animation, time, loop = animation.loop) {
|
|
5094
|
-
return loop && animation.length > 0 ? time % animation.length : time;
|
|
5095
|
-
}
|
|
5096
|
-
function sampleEntityAnimation(animation, time, loop = animation.loop) {
|
|
5097
|
-
const elapsed = entityAnimationTime(animation, time, loop);
|
|
5098
|
-
const pose = {};
|
|
5099
|
-
for (const [name, bone] of Object.entries(animation.bones)) {
|
|
5100
|
-
const sampled = pose[name] = {};
|
|
5101
|
-
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
5102
|
-
const keyframes = bone[channel];
|
|
5103
|
-
if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
|
|
5104
|
-
}
|
|
5105
|
-
}
|
|
5106
|
-
return pose;
|
|
5107
|
-
}
|
|
5108
|
-
|
|
5109
|
-
// src/entity/scene/EntityAnimationPlayer.ts
|
|
5110
|
-
var ZERO = [0, 0, 0];
|
|
5111
|
-
var EntityAnimationPlayer = class {
|
|
5112
|
-
constructor() {
|
|
5113
|
-
this.parts = [];
|
|
5114
|
-
this._time = 0;
|
|
5115
|
-
this.loop = false;
|
|
5116
|
-
this.speed = 1;
|
|
5117
|
-
}
|
|
5118
|
-
get animation() {
|
|
5119
|
-
return this._animation;
|
|
5120
|
-
}
|
|
5121
|
-
get time() {
|
|
5122
|
-
return this._time;
|
|
5123
|
-
}
|
|
5124
|
-
/**
|
|
5125
|
-
* Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
|
|
5126
|
-
* bones without a matching part are skipped.
|
|
5127
|
-
*/
|
|
5128
|
-
play(layers, animation, options = {}) {
|
|
5129
|
-
this.stop();
|
|
5130
|
-
this._animation = animation;
|
|
5131
|
-
this._time = options.time ?? 0;
|
|
5132
|
-
this.loop = options.loop ?? animation.loop;
|
|
5133
|
-
this.speed = options.speed ?? 1;
|
|
5134
|
-
for (const layer of layers) {
|
|
5135
|
-
for (const bone of Object.keys(animation.bones)) {
|
|
5136
|
-
const object = layer.getObjectByName(`group:${bone}`);
|
|
5137
|
-
if (!object) continue;
|
|
5138
|
-
this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
|
|
5139
|
-
}
|
|
5140
|
-
}
|
|
5141
|
-
this.apply();
|
|
5142
|
-
}
|
|
5143
|
-
/** Restores the default poses. Returns whether an animation was active. */
|
|
5144
|
-
stop() {
|
|
5145
|
-
if (!this._animation) return false;
|
|
5146
|
-
for (const part of this.parts) {
|
|
5147
|
-
part.object.position.copy(part.position);
|
|
5148
|
-
part.object.rotation.copy(part.rotation);
|
|
5149
|
-
part.object.scale.copy(part.scale);
|
|
5150
|
-
}
|
|
5151
|
-
this.clear();
|
|
5152
|
-
return true;
|
|
5153
|
-
}
|
|
5154
|
-
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
5155
|
-
clear() {
|
|
5156
|
-
this.parts = [];
|
|
5157
|
-
this._animation = void 0;
|
|
5158
|
-
this._time = 0;
|
|
5159
|
-
}
|
|
5160
|
-
setTime(seconds) {
|
|
5161
|
-
if (!this._animation) return false;
|
|
5162
|
-
this._time = seconds;
|
|
5163
|
-
this.apply();
|
|
5164
|
-
return true;
|
|
5165
|
-
}
|
|
5166
|
-
advance(deltaSeconds) {
|
|
5167
|
-
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
5168
|
-
}
|
|
5169
|
-
apply() {
|
|
5170
|
-
const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
|
|
5171
|
-
for (const part of this.parts) {
|
|
5172
|
-
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
|
|
5173
|
-
part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
|
|
5174
|
-
part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
|
|
5175
|
-
part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
|
|
5176
|
-
}
|
|
5177
|
-
}
|
|
5178
|
-
};
|
|
5637
|
+
// src/entity/index.ts
|
|
5638
|
+
init_EntityAnimation();
|
|
5179
5639
|
|
|
5180
|
-
// src/entity/scene/
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
var import_ts_deepmerge4 = __toESM(require_dist());
|
|
5184
|
-
init_Ticker();
|
|
5185
|
-
init_model();
|
|
5186
|
-
init_ModelTextures();
|
|
5187
|
-
init_AssetKey();
|
|
5188
|
-
init_Materials();
|
|
5189
|
-
import { Color as Color3, Euler as Euler4, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
|
|
5190
|
-
init_three();
|
|
5191
|
-
var EntityObject = class _EntityObject extends SceneObject {
|
|
5192
|
-
constructor(entity, options) {
|
|
5193
|
-
super();
|
|
5194
|
-
this.entity = entity;
|
|
5195
|
-
this.isEntityObject = true;
|
|
5196
|
-
this.meshesCreated = false;
|
|
5197
|
-
this.geometries = /* @__PURE__ */ new Set();
|
|
5198
|
-
this.disposeWireframes = [];
|
|
5199
|
-
/** Scrolling materials are owned: their texture offset follows this entity's age. */
|
|
5200
|
-
this.scrollMaterials = [];
|
|
5201
|
-
/** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
|
|
5202
|
-
this.age = 0;
|
|
5203
|
-
this.animationPlayer = new EntityAnimationPlayer();
|
|
5204
|
-
this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
|
|
5205
|
-
this.addEventListener("added", () => this.updateScrollSubscription());
|
|
5206
|
-
this.addEventListener("removed", () => this.updateScrollSubscription());
|
|
5207
|
-
}
|
|
5208
|
-
static {
|
|
5209
|
-
this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
|
|
5210
|
-
}
|
|
5211
|
-
async init() {
|
|
5212
|
-
this.createMeshes();
|
|
5213
|
-
await this.applyTextures();
|
|
5214
|
-
}
|
|
5215
|
-
dispose() {
|
|
5216
|
-
super.dispose();
|
|
5217
|
-
}
|
|
5218
|
-
disposeAndRemoveAllChildren() {
|
|
5219
|
-
this.clearScrollMaterials();
|
|
5220
|
-
for (const geometry of this.geometries) geometry.dispose();
|
|
5221
|
-
this.geometries.clear();
|
|
5222
|
-
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
5223
|
-
this.animationPlayer.clear();
|
|
5224
|
-
super.disposeAndRemoveAllChildren();
|
|
5225
|
-
}
|
|
5226
|
-
clearScrollMaterials() {
|
|
5227
|
-
Ticker.remove(this.scrollTicker);
|
|
5228
|
-
this.scrollTicker = void 0;
|
|
5229
|
-
for (const { material } of this.scrollMaterials.splice(0)) {
|
|
5230
|
-
material.map?.dispose();
|
|
5231
|
-
material.dispose();
|
|
5232
|
-
}
|
|
5233
|
-
}
|
|
5234
|
-
updateScrollSubscription() {
|
|
5235
|
-
if (this.parent && this.scrollMaterials.length) {
|
|
5236
|
-
if (this.scrollTicker === void 0) {
|
|
5237
|
-
this.scrollTicker = Ticker.add(() => {
|
|
5238
|
-
this.age++;
|
|
5239
|
-
this.updateScroll();
|
|
5240
|
-
});
|
|
5241
|
-
}
|
|
5242
|
-
} else {
|
|
5243
|
-
Ticker.remove(this.scrollTicker);
|
|
5244
|
-
this.scrollTicker = void 0;
|
|
5245
|
-
}
|
|
5246
|
-
}
|
|
5247
|
-
/** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
|
|
5248
|
-
updateScroll() {
|
|
5249
|
-
for (const { offset, speed } of this.scrollMaterials) {
|
|
5250
|
-
offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
|
|
5251
|
-
}
|
|
5252
|
-
this.notifyDirty();
|
|
5253
|
-
}
|
|
5254
|
-
//<editor-fold desc="ANIMATION">
|
|
5255
|
-
/** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
|
|
5256
|
-
get animation() {
|
|
5257
|
-
return this.animationPlayer.animation;
|
|
5258
|
-
}
|
|
5259
|
-
/** Seconds since the animation started, before looping. */
|
|
5260
|
-
get animationTime() {
|
|
5261
|
-
return this.animationPlayer.time;
|
|
5262
|
-
}
|
|
5263
|
-
/**
|
|
5264
|
-
* Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
|
|
5265
|
-
* Parts of every layer are matched by name and their current pose is the default the offsets add to.
|
|
5266
|
-
* The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
|
|
5267
|
-
*/
|
|
5268
|
-
playAnimation(animation, options) {
|
|
5269
|
-
this.createMeshes();
|
|
5270
|
-
const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
|
|
5271
|
-
this.animationPlayer.play(layers, animation, options);
|
|
5272
|
-
this.notifyDirty();
|
|
5273
|
-
}
|
|
5274
|
-
/** Stops the animation and restores the default pose. */
|
|
5275
|
-
stopAnimation() {
|
|
5276
|
-
if (this.animationPlayer.stop()) this.notifyDirty();
|
|
5277
|
-
}
|
|
5278
|
-
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
5279
|
-
setAnimationTime(seconds) {
|
|
5280
|
-
if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
|
|
5281
|
-
}
|
|
5282
|
-
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
5283
|
-
advanceAnimation(deltaSeconds) {
|
|
5284
|
-
if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
|
|
5285
|
-
}
|
|
5286
|
-
//</editor-fold>
|
|
5287
|
-
getLayerGroup(name) {
|
|
5288
|
-
return super.getGroupByName(`layer:${name}`);
|
|
5289
|
-
}
|
|
5290
|
-
getGroupByName(name, layerName) {
|
|
5291
|
-
return layerName === void 0 ? super.getGroupByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);
|
|
5292
|
-
}
|
|
5293
|
-
getMeshByName(name, layerName) {
|
|
5294
|
-
return layerName === void 0 ? super.getMeshByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`);
|
|
5295
|
-
}
|
|
5296
|
-
get entityLayers() {
|
|
5297
|
-
return this.entity.layers ?? { main: this.entity };
|
|
5298
|
-
}
|
|
5299
|
-
getTextureKey(layer) {
|
|
5300
|
-
if (layer.texture) return layer.texture;
|
|
5301
|
-
const key = layer.key;
|
|
5302
|
-
return new AssetKey(
|
|
5303
|
-
key.namespace,
|
|
5304
|
-
isAssetKey(key) ? key.getFullPath() : key.path,
|
|
5305
|
-
"textures",
|
|
5306
|
-
"entity",
|
|
5307
|
-
"assets",
|
|
5308
|
-
".png"
|
|
5309
|
-
);
|
|
5310
|
-
}
|
|
5311
|
-
async loadTextures(layer = this.entity) {
|
|
5312
|
-
return ModelTextures.get(this.getTextureKey(layer));
|
|
5313
|
-
}
|
|
5314
|
-
createMeshes(force = false) {
|
|
5315
|
-
if (this.meshesCreated && !force) return;
|
|
5316
|
-
const modelRoot = new Object3D3();
|
|
5317
|
-
const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
|
|
5318
|
-
if (transform) {
|
|
5319
|
-
for (const op of transform) {
|
|
5320
|
-
const matrix = new Matrix45();
|
|
5321
|
-
if ("scale" in op) matrix.makeScale(...op.scale);
|
|
5322
|
-
else if ("translate" in op) matrix.makeTranslation(...op.translate);
|
|
5323
|
-
else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
|
|
5324
|
-
modelRoot.matrix.multiply(matrix);
|
|
5325
|
-
}
|
|
5326
|
-
modelRoot.matrixAutoUpdate = false;
|
|
5327
|
-
} else if (this.options.flip ?? true) {
|
|
5328
|
-
modelRoot.scale.set(-1, -1, 1);
|
|
5329
|
-
}
|
|
5330
|
-
this.add(modelRoot);
|
|
5331
|
-
Object.entries(this.entityLayers).forEach(([name, layer], index) => {
|
|
5332
|
-
const group = this.createGroup(`layer:${name}`);
|
|
5333
|
-
modelRoot.add(group);
|
|
5334
|
-
const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
|
|
5335
|
-
this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
|
|
5336
|
-
});
|
|
5337
|
-
this.meshesCreated = true;
|
|
5338
|
-
}
|
|
5339
|
-
createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
|
|
5340
|
-
const anchor = this.createGroup(name);
|
|
5341
|
-
anchor.position.fromArray(part.pose.offset);
|
|
5342
|
-
anchor.rotation.set(...part.pose.rotation, "ZYX");
|
|
5343
|
-
anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
|
|
5344
|
-
parent.add(anchor);
|
|
5345
|
-
const size = part.texture ?? textureSize;
|
|
5346
|
-
for (const cube of part.cubes) {
|
|
5347
|
-
const [width, height, depth] = cube.size;
|
|
5348
|
-
const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];
|
|
5349
|
-
const texture = new MinecraftCubeTexture(...cube.uv, ...size);
|
|
5350
|
-
const uv = size[0] === 0 || size[1] === 0 ? new Array(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);
|
|
5351
|
-
const geometry = this._getBoxGeometryForDimensionsAndUv(
|
|
5352
|
-
width + growX * 2,
|
|
5353
|
-
height + growY * 2,
|
|
5354
|
-
depth + growZ * 2,
|
|
5355
|
-
uv
|
|
5356
|
-
).clone();
|
|
5357
|
-
this.geometries.add(geometry);
|
|
5358
|
-
geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
|
|
5359
|
-
if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
|
|
5360
|
-
const index = Array.from(geometry.getIndex().array);
|
|
5361
|
-
geometry.setIndex(index.concat(index.slice().reverse()));
|
|
5362
|
-
}
|
|
5363
|
-
const mesh = this.createMesh(name, geometry, material);
|
|
5364
|
-
mesh.renderOrder = renderOrder;
|
|
5365
|
-
anchor.add(mesh);
|
|
5366
|
-
if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));
|
|
5367
|
-
}
|
|
5368
|
-
for (const [childName, child] of Object.entries(part.children)) {
|
|
5369
|
-
this.createPart(childName, child, anchor, size, material, renderOrder, inward);
|
|
5370
|
-
}
|
|
5371
|
-
}
|
|
5372
|
-
async applyTextures() {
|
|
5373
|
-
this.clearScrollMaterials();
|
|
5374
|
-
await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
|
|
5375
|
-
const mode = layer.render ?? layer.layer.render ?? "cutout";
|
|
5376
|
-
const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
|
|
5377
|
-
const scroll = Materials.entityModeScroll(mode);
|
|
5378
|
-
const assetKeyStr = this.getTextureKey(layer).serialize();
|
|
5379
|
-
const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color3(tint).getHexString()}:${assetKeyStr}`;
|
|
5380
|
-
let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
|
|
5381
|
-
if (!mat) {
|
|
5382
|
-
const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
|
|
5383
|
-
const imageData = await this.loadTextures(layer);
|
|
5384
|
-
if (!imageData) return;
|
|
5385
|
-
const canvas = imageData.data.canvas;
|
|
5386
|
-
const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
|
|
5387
|
-
mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
|
|
5388
|
-
if (scroll) {
|
|
5389
|
-
this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
|
|
5390
|
-
}
|
|
5391
|
-
}
|
|
5392
|
-
this.getLayerGroup(name)?.traverse((object) => {
|
|
5393
|
-
if (isMesh(object)) object.material = mat;
|
|
5394
|
-
});
|
|
5395
|
-
}));
|
|
5396
|
-
if (!this.children.length) {
|
|
5397
|
-
this.clearScrollMaterials();
|
|
5398
|
-
} else if (this.scrollMaterials.length) {
|
|
5399
|
-
this.updateScroll();
|
|
5400
|
-
}
|
|
5401
|
-
this.updateScrollSubscription();
|
|
5402
|
-
this.notifyDirty();
|
|
5403
|
-
}
|
|
5404
|
-
};
|
|
5405
|
-
function isEntityObject(obj) {
|
|
5406
|
-
return obj.isEntityObject;
|
|
5407
|
-
}
|
|
5640
|
+
// src/entity/scene/index.ts
|
|
5641
|
+
init_EntityAnimationPlayer();
|
|
5642
|
+
init_EntityObject();
|
|
5408
5643
|
|
|
5409
5644
|
// src/error/index.ts
|
|
5410
5645
|
init_MineRenderError();
|
|
@@ -8033,16 +8268,8 @@ init_SceneObject();
|
|
|
8033
8268
|
init_Materials();
|
|
8034
8269
|
init_ModelObject();
|
|
8035
8270
|
init_DisplayPosition();
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
// src/model/GuiLight.ts
|
|
8039
|
-
var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
|
|
8040
|
-
GuiLight2["FRONT"] = "front";
|
|
8041
|
-
GuiLight2["SIDE"] = "side";
|
|
8042
|
-
return GuiLight2;
|
|
8043
|
-
})(GuiLight || {});
|
|
8044
|
-
|
|
8045
|
-
// src/gui/scene/GuiObject.ts
|
|
8271
|
+
init_GuiLight();
|
|
8272
|
+
import { Box2, Box3 as Box32, Matrix4 as Matrix410, Mesh as Mesh7, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
|
|
8046
8273
|
var GuiObject = class extends SceneObject {
|
|
8047
8274
|
constructor(textureLayers, options) {
|
|
8048
8275
|
super({ ...options, instanceMeshes: false, mergeMeshes: false });
|
|
@@ -8065,13 +8292,13 @@ var GuiObject = class extends SceneObject {
|
|
|
8065
8292
|
const item = await this.createItem(layer, index);
|
|
8066
8293
|
item.position.set(x + width2 / 2, -y - height2 / 2, 0);
|
|
8067
8294
|
item.scale.set(width2 / 16, height2 / 16, width2 / 16);
|
|
8068
|
-
item.
|
|
8295
|
+
item.updateWorldMatrix(true, true);
|
|
8296
|
+
const inverse = this.matrixWorld.clone().invert();
|
|
8069
8297
|
const bounds = new Box32();
|
|
8070
8298
|
item.iterateAllMeshes((mesh2) => {
|
|
8071
8299
|
mesh2.geometry.computeBoundingBox();
|
|
8072
|
-
bounds.union(mesh2.geometry.boundingBox);
|
|
8300
|
+
bounds.union(mesh2.geometry.boundingBox.clone().applyMatrix4(new Matrix410().multiplyMatrices(inverse, mesh2.matrixWorld)));
|
|
8073
8301
|
});
|
|
8074
|
-
bounds.applyMatrix4(item.matrix);
|
|
8075
8302
|
item.position.z = depth - bounds.min.z;
|
|
8076
8303
|
depth += bounds.max.z - bounds.min.z + 0.01;
|
|
8077
8304
|
this.bounds.expandByPoint(new Vector23(x, y));
|
|
@@ -8126,7 +8353,7 @@ var GuiObject = class extends SceneObject {
|
|
|
8126
8353
|
this.add(item);
|
|
8127
8354
|
await item.init();
|
|
8128
8355
|
item.iterateAllMeshes((mesh) => {
|
|
8129
|
-
this.geometries.add(mesh.geometry);
|
|
8356
|
+
if (!model.special) this.geometries.add(mesh.geometry);
|
|
8130
8357
|
mesh.name = `mesh:${layer.name ?? index}`;
|
|
8131
8358
|
mesh.renderOrder = index;
|
|
8132
8359
|
for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
|
|
@@ -8584,26 +8811,12 @@ function isInstanceable(obj) {
|
|
|
8584
8811
|
// src/model/index.ts
|
|
8585
8812
|
init_DisplayPosition();
|
|
8586
8813
|
init_DisplayTransforms();
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
var ITEM_GENERATED = "item/generated";
|
|
8590
|
-
var BUILTIN_GENERATED = "builtin/generated";
|
|
8591
|
-
var BUILTIN_ENTITY = "builtin/entity";
|
|
8592
|
-
var DEFAULT_ELEMENTS = [];
|
|
8593
|
-
function isDoubleArray(obj) {
|
|
8594
|
-
return Array.isArray(obj) && obj.length === 2;
|
|
8595
|
-
}
|
|
8596
|
-
function isTripleArray(obj) {
|
|
8597
|
-
return Array.isArray(obj) && obj.length === 3;
|
|
8598
|
-
}
|
|
8599
|
-
function isQuadArray(obj) {
|
|
8600
|
-
return Array.isArray(obj) && obj.length === 4;
|
|
8601
|
-
}
|
|
8602
|
-
|
|
8603
|
-
// src/model/index.ts
|
|
8814
|
+
init_GuiLight();
|
|
8815
|
+
init_Model();
|
|
8604
8816
|
init_ModelCulling();
|
|
8605
8817
|
init_ModelGenerator();
|
|
8606
8818
|
init_ModelMerger();
|
|
8819
|
+
init_SpecialItems();
|
|
8607
8820
|
|
|
8608
8821
|
// src/model/block/BlockStateResolver.ts
|
|
8609
8822
|
init_BlockStates();
|
|
@@ -8794,9 +9007,10 @@ var import_ts_deepmerge6 = __toESM(require_dist());
|
|
|
8794
9007
|
init_MineRenderError();
|
|
8795
9008
|
init_InstanceReference();
|
|
8796
9009
|
init_AssetKey();
|
|
8797
|
-
import { Euler as Euler8, Matrix4 as
|
|
9010
|
+
import { Euler as Euler8, Matrix4 as Matrix411, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
|
|
8798
9011
|
init_ModelCulling();
|
|
8799
9012
|
init_FluidGeometry();
|
|
9013
|
+
init_Entities();
|
|
8800
9014
|
var BlockObject = class _BlockObject extends SceneObject {
|
|
8801
9015
|
constructor(blockState, options) {
|
|
8802
9016
|
super(options);
|
|
@@ -8812,7 +9026,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
8812
9026
|
this._models = [];
|
|
8813
9027
|
this._cullMask = 0;
|
|
8814
9028
|
this._entities = [];
|
|
8815
|
-
this._entityPlacement = new
|
|
9029
|
+
this._entityPlacement = new Matrix411();
|
|
8816
9030
|
this._entityGeneration = 0;
|
|
8817
9031
|
this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
|
|
8818
9032
|
}
|
|
@@ -8897,7 +9111,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
8897
9111
|
return true;
|
|
8898
9112
|
}
|
|
8899
9113
|
placeEntities() {
|
|
8900
|
-
const matrix = new
|
|
9114
|
+
const matrix = new Matrix411().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
|
|
8901
9115
|
for (const entity of this._entities) {
|
|
8902
9116
|
matrix.decompose(entity.position, entity.quaternion, entity.scale);
|
|
8903
9117
|
}
|
|
@@ -8983,7 +9197,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
8983
9197
|
() => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
|
|
8984
9198
|
);
|
|
8985
9199
|
const previous = this._fluidModel;
|
|
8986
|
-
const matrix = previous ? this.getModelMatrix(previous) : new
|
|
9200
|
+
const matrix = previous ? this.getModelMatrix(previous) : new Matrix411().makeTranslation(...this.position.toArray());
|
|
8987
9201
|
if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
|
|
8988
9202
|
else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
|
|
8989
9203
|
this._models = this._models.filter((model) => model !== previous);
|
|
@@ -9121,7 +9335,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
9121
9335
|
setPositionRotationScaleAt(index, position, rotation, scale) {
|
|
9122
9336
|
super.setPositionRotationScaleAt(index, position, rotation, scale);
|
|
9123
9337
|
}
|
|
9124
|
-
getMatrixAt(index, matrix = new
|
|
9338
|
+
getMatrixAt(index, matrix = new Matrix411()) {
|
|
9125
9339
|
if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
|
|
9126
9340
|
const child = this._models[0];
|
|
9127
9341
|
if (child && isModelObject(child)) {
|
|
@@ -11724,7 +11938,7 @@ init_util();
|
|
|
11724
11938
|
init_Caching();
|
|
11725
11939
|
init_CacheKey();
|
|
11726
11940
|
init_MineRenderError();
|
|
11727
|
-
import { DataTexture as DataTexture2, DoubleSide as DoubleSide4, FrontSide as FrontSide2, MeshBasicMaterial as
|
|
11941
|
+
import { DataTexture as DataTexture2, DoubleSide as DoubleSide4, FrontSide as FrontSide2, MeshBasicMaterial as MeshBasicMaterial6, SRGBColorSpace as SRGBColorSpace5 } from "three";
|
|
11728
11942
|
|
|
11729
11943
|
// src/skin/SkinImage.ts
|
|
11730
11944
|
init_Caching();
|
|
@@ -11809,7 +12023,7 @@ var SkinTextures = class {
|
|
|
11809
12023
|
texture.colorSpace = SRGBColorSpace5;
|
|
11810
12024
|
texture.flipY = true;
|
|
11811
12025
|
texture.needsUpdate = true;
|
|
11812
|
-
return new
|
|
12026
|
+
return new MeshBasicMaterial6({ map: texture, transparent, side: transparent ? DoubleSide4 : FrontSide2, alphaTest: transparent ? 0.1 : 0 });
|
|
11813
12027
|
}
|
|
11814
12028
|
static isSlim(image, scale) {
|
|
11815
12029
|
for (const [x, y] of [[46, 52], [54, 20]]) {
|
|
@@ -12037,6 +12251,7 @@ var SkinObject = class extends SceneObject {
|
|
|
12037
12251
|
};
|
|
12038
12252
|
|
|
12039
12253
|
// src/renderer/MineRenderScene.ts
|
|
12254
|
+
init_EntityObject();
|
|
12040
12255
|
var MineRenderScene = class _MineRenderScene extends Scene5 {
|
|
12041
12256
|
constructor(options) {
|
|
12042
12257
|
super();
|
|
@@ -12168,9 +12383,10 @@ function isMineRenderScene(obj) {
|
|
|
12168
12383
|
import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera as PerspectiveCamera2, SRGBColorSpace as SRGBColorSpace6, Vector3 as Vector313, WebGLRenderer as WebGLRenderer2 } from "three";
|
|
12169
12384
|
var import_ts_deepmerge9 = __toESM(require_dist());
|
|
12170
12385
|
init_util();
|
|
12386
|
+
init_Model();
|
|
12387
|
+
init_three();
|
|
12171
12388
|
import Stats from "stats.js";
|
|
12172
12389
|
import { EffectComposer, RenderPass } from "postprocessing";
|
|
12173
|
-
init_three();
|
|
12174
12390
|
|
|
12175
12391
|
// src/three/OrbitControls.js
|
|
12176
12392
|
import {
|
|
@@ -13674,6 +13890,7 @@ init_BlockStates();
|
|
|
13674
13890
|
init_AssetKey();
|
|
13675
13891
|
|
|
13676
13892
|
// src/world/MineRenderWorld.ts
|
|
13893
|
+
init_Model();
|
|
13677
13894
|
import { Vector3 as Vector315 } from "three";
|
|
13678
13895
|
init_BatchedExecutor();
|
|
13679
13896
|
init_AssetKey();
|
|
@@ -13684,7 +13901,7 @@ init_CubeFace();
|
|
|
13684
13901
|
init_AssetKey();
|
|
13685
13902
|
init_Models();
|
|
13686
13903
|
init_CubeFace();
|
|
13687
|
-
import { Matrix4 as
|
|
13904
|
+
import { Matrix4 as Matrix412, Vector3 as Vector314 } from "three";
|
|
13688
13905
|
init_ModelCulling();
|
|
13689
13906
|
init_ModelObject();
|
|
13690
13907
|
init_UVMapper();
|
|
@@ -13747,7 +13964,7 @@ var SectionModels = class {
|
|
|
13747
13964
|
});
|
|
13748
13965
|
await object.init();
|
|
13749
13966
|
const geometry = object.children[0].geometry;
|
|
13750
|
-
geometry.applyMatrix4(new
|
|
13967
|
+
geometry.applyMatrix4(new Matrix412().makeRotationFromEuler(rotation));
|
|
13751
13968
|
object.clear();
|
|
13752
13969
|
const cullFaces = CUBE_FACES.map((face) => {
|
|
13753
13970
|
const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
|
|
@@ -13994,6 +14211,9 @@ var MineRenderWorld = class {
|
|
|
13994
14211
|
}
|
|
13995
14212
|
};
|
|
13996
14213
|
|
|
14214
|
+
// src/world/Chunk.ts
|
|
14215
|
+
init_Model();
|
|
14216
|
+
|
|
13997
14217
|
// src/world/SectionMesh.ts
|
|
13998
14218
|
init_CanvasCompat();
|
|
13999
14219
|
init_Materials();
|
|
@@ -14342,6 +14562,7 @@ export {
|
|
|
14342
14562
|
SkinPart,
|
|
14343
14563
|
SkinTextures,
|
|
14344
14564
|
Skins,
|
|
14565
|
+
SpecialItems,
|
|
14345
14566
|
StructureParser,
|
|
14346
14567
|
TextureAtlas,
|
|
14347
14568
|
TextureLoader,
|