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/browser/index.mjs
CHANGED
|
@@ -1084,6 +1084,26 @@ var init_Materials = __esm({
|
|
|
1084
1084
|
}
|
|
1085
1085
|
});
|
|
1086
1086
|
|
|
1087
|
+
// src/model/Model.ts
|
|
1088
|
+
function isDoubleArray(obj) {
|
|
1089
|
+
return Array.isArray(obj) && obj.length === 2;
|
|
1090
|
+
}
|
|
1091
|
+
function isTripleArray(obj) {
|
|
1092
|
+
return Array.isArray(obj) && obj.length === 3;
|
|
1093
|
+
}
|
|
1094
|
+
function isQuadArray(obj) {
|
|
1095
|
+
return Array.isArray(obj) && obj.length === 4;
|
|
1096
|
+
}
|
|
1097
|
+
var ITEM_GENERATED, BUILTIN_GENERATED, BUILTIN_ENTITY, DEFAULT_ELEMENTS;
|
|
1098
|
+
var init_Model = __esm({
|
|
1099
|
+
"src/model/Model.ts"() {
|
|
1100
|
+
ITEM_GENERATED = "item/generated";
|
|
1101
|
+
BUILTIN_GENERATED = "builtin/generated";
|
|
1102
|
+
BUILTIN_ENTITY = "builtin/entity";
|
|
1103
|
+
DEFAULT_ELEMENTS = [];
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1087
1107
|
// ../../node_modules/ts-deepmerge/dist/index.js
|
|
1088
1108
|
var require_dist = __commonJS({
|
|
1089
1109
|
"../../node_modules/ts-deepmerge/dist/index.js"(exports) {
|
|
@@ -1342,6 +1362,7 @@ var init_DisplayTransforms = __esm({
|
|
|
1342
1362
|
var import_ts_deepmerge, ModelMerger;
|
|
1343
1363
|
var init_ModelMerger = __esm({
|
|
1344
1364
|
"src/model/ModelMerger.ts"() {
|
|
1365
|
+
init_Model();
|
|
1345
1366
|
init_Models();
|
|
1346
1367
|
import_ts_deepmerge = __toESM(require_dist());
|
|
1347
1368
|
init_AssetKey();
|
|
@@ -1367,6 +1388,7 @@ var init_ModelMerger = __esm({
|
|
|
1367
1388
|
}
|
|
1368
1389
|
const models = [];
|
|
1369
1390
|
const parentKey = AssetKey.parse("models", model.parent);
|
|
1391
|
+
if (parentKey.namespace === "minecraft" && parentKey.getFullPath() === BUILTIN_ENTITY) return models;
|
|
1370
1392
|
parentKey.root = model.key?.root;
|
|
1371
1393
|
const parentModel = await Models.getRaw(parentKey);
|
|
1372
1394
|
if (parentModel) {
|
|
@@ -1433,12 +1455,12 @@ var init_Models = __esm({
|
|
|
1433
1455
|
const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
|
|
1434
1456
|
if (!result) return void 0;
|
|
1435
1457
|
if (result.key.assetType !== "items") return { ...result.asset, key };
|
|
1436
|
-
const
|
|
1437
|
-
const modelKey = AssetKey.parse("models",
|
|
1458
|
+
const selected = this.defaultItemModel(result.asset.model, key);
|
|
1459
|
+
const modelKey = AssetKey.parse("models", selected.model);
|
|
1438
1460
|
modelKey.root = key.root;
|
|
1439
1461
|
const model2 = await this.getRaw(modelKey);
|
|
1440
|
-
if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${
|
|
1441
|
-
return model2;
|
|
1462
|
+
if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
|
|
1463
|
+
return selected.special ? { ...model2, special: selected.special } : model2;
|
|
1442
1464
|
});
|
|
1443
1465
|
return model ? { ...model, key: Object.assign(new AssetKey("", ""), model.key) } : void 0;
|
|
1444
1466
|
}
|
|
@@ -1449,8 +1471,25 @@ var init_Models = __esm({
|
|
|
1449
1471
|
}
|
|
1450
1472
|
switch (node.type.replace(/^minecraft:/, "")) {
|
|
1451
1473
|
case "model":
|
|
1452
|
-
if (typeof node.model === "string" && node.model) return node.model;
|
|
1474
|
+
if (typeof node.model === "string" && node.model) return { model: node.model };
|
|
1453
1475
|
break;
|
|
1476
|
+
case "special": {
|
|
1477
|
+
if (!node.base || !node.model || typeof node.model !== "object") break;
|
|
1478
|
+
const special = node.model;
|
|
1479
|
+
switch (special.type) {
|
|
1480
|
+
case "chest":
|
|
1481
|
+
case "minecraft:chest":
|
|
1482
|
+
case "bed":
|
|
1483
|
+
case "minecraft:bed":
|
|
1484
|
+
if (typeof special.texture === "string" && special.texture) return { model: node.base, special };
|
|
1485
|
+
break;
|
|
1486
|
+
case "head":
|
|
1487
|
+
case "minecraft:head":
|
|
1488
|
+
if (typeof special.kind === "string" && special.kind) return { model: node.base, special };
|
|
1489
|
+
break;
|
|
1490
|
+
}
|
|
1491
|
+
throw new Error(`Unsupported special item renderer ${special.type} for ${key.toNamespacedString()}`);
|
|
1492
|
+
}
|
|
1454
1493
|
case "condition":
|
|
1455
1494
|
return this.defaultItemModel(node.on_false, key);
|
|
1456
1495
|
case "select": {
|
|
@@ -3012,6 +3051,102 @@ var init_UVMapper = __esm({
|
|
|
3012
3051
|
}
|
|
3013
3052
|
});
|
|
3014
3053
|
|
|
3054
|
+
// src/MinecraftCubeTexture.ts
|
|
3055
|
+
var MinecraftCubeTexture;
|
|
3056
|
+
var init_MinecraftCubeTexture = __esm({
|
|
3057
|
+
"src/MinecraftCubeTexture.ts"() {
|
|
3058
|
+
init_UVMapper();
|
|
3059
|
+
init_CubeFace();
|
|
3060
|
+
MinecraftCubeTexture = class {
|
|
3061
|
+
constructor(u, v, width, height) {
|
|
3062
|
+
this.u = u;
|
|
3063
|
+
this.v = v;
|
|
3064
|
+
this.width = width;
|
|
3065
|
+
this.height = height;
|
|
3066
|
+
}
|
|
3067
|
+
mapW(x) {
|
|
3068
|
+
return x / this.width;
|
|
3069
|
+
}
|
|
3070
|
+
mapH(x) {
|
|
3071
|
+
return 1 - x / this.height;
|
|
3072
|
+
}
|
|
3073
|
+
getUvEast(w, h, l) {
|
|
3074
|
+
return [
|
|
3075
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
3076
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
3077
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)],
|
|
3078
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
3079
|
+
];
|
|
3080
|
+
}
|
|
3081
|
+
getUvWest(w, h, l) {
|
|
3082
|
+
return [
|
|
3083
|
+
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
3084
|
+
[this.mapW(this.u), this.mapH(this.v + l + h)],
|
|
3085
|
+
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
3086
|
+
[this.mapW(this.u), this.mapH(this.v + l)]
|
|
3087
|
+
];
|
|
3088
|
+
}
|
|
3089
|
+
getUvUp(w, h, l) {
|
|
3090
|
+
return [
|
|
3091
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
3092
|
+
[this.mapW(this.u + l + w + w), this.mapH(this.v + l)],
|
|
3093
|
+
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
3094
|
+
[this.mapW(this.u + l + w + w), this.mapH(this.v)]
|
|
3095
|
+
];
|
|
3096
|
+
}
|
|
3097
|
+
getUvDown(w, h, l) {
|
|
3098
|
+
return [
|
|
3099
|
+
[this.mapW(this.u + l), this.mapH(this.v)],
|
|
3100
|
+
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
3101
|
+
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
3102
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
3103
|
+
];
|
|
3104
|
+
}
|
|
3105
|
+
getUvSouth(w, h, l) {
|
|
3106
|
+
return [
|
|
3107
|
+
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l + h)],
|
|
3108
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
3109
|
+
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l)],
|
|
3110
|
+
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)]
|
|
3111
|
+
];
|
|
3112
|
+
}
|
|
3113
|
+
getUvNorth(w, h, l) {
|
|
3114
|
+
return [
|
|
3115
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
3116
|
+
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
3117
|
+
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
3118
|
+
[this.mapW(this.u + l), this.mapH(this.v + l)]
|
|
3119
|
+
];
|
|
3120
|
+
}
|
|
3121
|
+
getFaceUv(face, w, h, l) {
|
|
3122
|
+
switch (face) {
|
|
3123
|
+
case "east" /* EAST */:
|
|
3124
|
+
return this.getUvEast(w, h, l);
|
|
3125
|
+
case "west" /* WEST */:
|
|
3126
|
+
return this.getUvWest(w, h, l);
|
|
3127
|
+
case "up" /* UP */:
|
|
3128
|
+
return this.getUvUp(w, h, l);
|
|
3129
|
+
case "down" /* DOWN */:
|
|
3130
|
+
return this.getUvDown(w, h, l);
|
|
3131
|
+
case "south" /* SOUTH */:
|
|
3132
|
+
return this.getUvSouth(w, h, l);
|
|
3133
|
+
case "north" /* NORTH */:
|
|
3134
|
+
return this.getUvNorth(w, h, l);
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
toUvArray(w, h, l, mirror = false) {
|
|
3138
|
+
const uv = [];
|
|
3139
|
+
for (let i = 0; i < CUBE_FACES.length; i++) {
|
|
3140
|
+
const face = mirror && i < 2 ? CUBE_FACES[1 - i] : CUBE_FACES[i];
|
|
3141
|
+
const corners = this.getFaceUv(face, w, h, l);
|
|
3142
|
+
UVMapper.setFaceUvInArray(uv, i * 4, mirror ? [corners[1], corners[0], corners[3], corners[2]] : corners);
|
|
3143
|
+
}
|
|
3144
|
+
return uv;
|
|
3145
|
+
}
|
|
3146
|
+
};
|
|
3147
|
+
}
|
|
3148
|
+
});
|
|
3149
|
+
|
|
3015
3150
|
// src/error/MineRenderError.ts
|
|
3016
3151
|
var MineRenderError;
|
|
3017
3152
|
var init_MineRenderError = __esm({
|
|
@@ -3028,6 +3163,248 @@ var init_MineRenderError = __esm({
|
|
|
3028
3163
|
}
|
|
3029
3164
|
});
|
|
3030
3165
|
|
|
3166
|
+
// src/assets/Entities.ts
|
|
3167
|
+
var Entities;
|
|
3168
|
+
var init_Entities = __esm({
|
|
3169
|
+
"src/assets/Entities.ts"() {
|
|
3170
|
+
init_AssetKey();
|
|
3171
|
+
init_AssetLoader();
|
|
3172
|
+
init_source();
|
|
3173
|
+
init_Caching();
|
|
3174
|
+
init_Assets();
|
|
3175
|
+
init_MineRenderError();
|
|
3176
|
+
init_ModelTextures();
|
|
3177
|
+
Entities = class {
|
|
3178
|
+
static async getEntityList() {
|
|
3179
|
+
const collect = async (path) => {
|
|
3180
|
+
const prefix2 = path ? `${path}/` : "";
|
|
3181
|
+
const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
|
|
3182
|
+
const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
|
|
3183
|
+
if (!list) return [];
|
|
3184
|
+
const files = list.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
|
|
3185
|
+
const children = await Promise.all(list.directories.map((directory) => collect(`${prefix2}${directory}`)));
|
|
3186
|
+
return [...files, ...children.flat()];
|
|
3187
|
+
};
|
|
3188
|
+
return collect("");
|
|
3189
|
+
}
|
|
3190
|
+
static async getModelFile(modelKey) {
|
|
3191
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3192
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
|
|
3193
|
+
return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
3194
|
+
}
|
|
3195
|
+
static async getLayerList(modelKey) {
|
|
3196
|
+
return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
|
|
3197
|
+
}
|
|
3198
|
+
/** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
|
|
3199
|
+
static async getPassList(modelKey) {
|
|
3200
|
+
return (await this.getModelFile(modelKey))?.passes ?? [];
|
|
3201
|
+
}
|
|
3202
|
+
static async getEntity(modelKey, textureKey, options) {
|
|
3203
|
+
const model = await this.getModelFile(modelKey);
|
|
3204
|
+
if (!model) return void 0;
|
|
3205
|
+
const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
|
|
3206
|
+
const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
|
|
3207
|
+
if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
|
|
3208
|
+
draws.push(...passes);
|
|
3209
|
+
const names = [];
|
|
3210
|
+
const selected = draws.map((pass) => {
|
|
3211
|
+
const layer = model.layers[pass.layer];
|
|
3212
|
+
if (!layer) {
|
|
3213
|
+
throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
|
|
3214
|
+
}
|
|
3215
|
+
let name = pass.layer;
|
|
3216
|
+
for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
|
|
3217
|
+
names.push(name);
|
|
3218
|
+
return { name, layer, pass };
|
|
3219
|
+
});
|
|
3220
|
+
const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
|
|
3221
|
+
const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
|
|
3222
|
+
const textureLocation = pass.textureLocation ?? layer.textureLocation;
|
|
3223
|
+
let texture;
|
|
3224
|
+
if (override) {
|
|
3225
|
+
const path = isAssetKey(override) ? override.getFullPath() : override.path;
|
|
3226
|
+
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);
|
|
3227
|
+
} else if (textureLocation !== void 0) {
|
|
3228
|
+
texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
|
|
3229
|
+
if (isAssetKey(modelKey)) texture.root = modelKey.root;
|
|
3230
|
+
} else {
|
|
3231
|
+
texture = await this.resolveTexture(modelKey);
|
|
3232
|
+
}
|
|
3233
|
+
const render = pass.render ?? layer.render;
|
|
3234
|
+
return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
|
|
3235
|
+
})));
|
|
3236
|
+
return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
|
|
3237
|
+
}
|
|
3238
|
+
/**
|
|
3239
|
+
* Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
|
|
3240
|
+
*/
|
|
3241
|
+
static async getAnimations(modelKey) {
|
|
3242
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3243
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
|
|
3244
|
+
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
3245
|
+
return file?.animations;
|
|
3246
|
+
}
|
|
3247
|
+
static async resolveTexture(modelKey) {
|
|
3248
|
+
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3249
|
+
const root = isAssetKey(modelKey) ? modelKey.root : void 0;
|
|
3250
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", root);
|
|
3251
|
+
return Caching.entityTextureCache.get(key.serialize(), async () => {
|
|
3252
|
+
const name = path.split("/").pop();
|
|
3253
|
+
for (const candidate of [path, `${path}/${name}`]) {
|
|
3254
|
+
const texture2 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
|
|
3255
|
+
if (await ModelTextures.get(texture2)) return texture2;
|
|
3256
|
+
}
|
|
3257
|
+
const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json", root);
|
|
3258
|
+
const list = await AssetLoader.get(listKey, "list" /* LIST */);
|
|
3259
|
+
const files = list?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
|
|
3260
|
+
const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
|
|
3261
|
+
if (!file) return void 0;
|
|
3262
|
+
const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json", root);
|
|
3263
|
+
const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
|
|
3264
|
+
const assets = variant?.assets;
|
|
3265
|
+
const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
|
|
3266
|
+
if (typeof textureId !== "string") return void 0;
|
|
3267
|
+
const texture = AssetKey.parse("textures", textureId);
|
|
3268
|
+
texture.root = root;
|
|
3269
|
+
return texture;
|
|
3270
|
+
});
|
|
3271
|
+
}
|
|
3272
|
+
/** @deprecated Use getEntityList(); block entities share the entity dataset. */
|
|
3273
|
+
static getBlockList() {
|
|
3274
|
+
return this.getEntityList();
|
|
3275
|
+
}
|
|
3276
|
+
/** @deprecated Use getEntity(); block entities share the entity dataset. */
|
|
3277
|
+
static getBlock(modelKey, textureKey, options) {
|
|
3278
|
+
return this.getEntity(modelKey, textureKey, options);
|
|
3279
|
+
}
|
|
3280
|
+
};
|
|
3281
|
+
}
|
|
3282
|
+
});
|
|
3283
|
+
|
|
3284
|
+
// src/entity/EntityAnimation.ts
|
|
3285
|
+
function catmullRom(delta, p0, p1, p22, p32) {
|
|
3286
|
+
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);
|
|
3287
|
+
}
|
|
3288
|
+
function sampleEntityKeyframes(keyframes, time) {
|
|
3289
|
+
if (keyframes.length === 0) return [0, 0, 0];
|
|
3290
|
+
let low = 0, high = keyframes.length;
|
|
3291
|
+
while (low < high) {
|
|
3292
|
+
const middle = low + high >>> 1;
|
|
3293
|
+
if (time <= keyframes[middle].time) high = middle;
|
|
3294
|
+
else low = middle + 1;
|
|
3295
|
+
}
|
|
3296
|
+
const a = Math.max(0, low - 1);
|
|
3297
|
+
const b = Math.min(keyframes.length - 1, a + 1);
|
|
3298
|
+
const from = keyframes[a];
|
|
3299
|
+
const to = keyframes[b];
|
|
3300
|
+
const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
|
|
3301
|
+
if (to.interpolation === "catmullrom") {
|
|
3302
|
+
const before = keyframes[Math.max(0, a - 1)].value;
|
|
3303
|
+
const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
|
|
3304
|
+
return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
|
|
3305
|
+
}
|
|
3306
|
+
const target = to.pre ?? to.value;
|
|
3307
|
+
return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
|
|
3308
|
+
}
|
|
3309
|
+
function entityAnimationTime(animation, time, loop = animation.loop) {
|
|
3310
|
+
return loop && animation.length > 0 ? time % animation.length : time;
|
|
3311
|
+
}
|
|
3312
|
+
function sampleEntityAnimation(animation, time, loop = animation.loop) {
|
|
3313
|
+
const elapsed = entityAnimationTime(animation, time, loop);
|
|
3314
|
+
const pose = {};
|
|
3315
|
+
for (const [name, bone] of Object.entries(animation.bones)) {
|
|
3316
|
+
const sampled = pose[name] = {};
|
|
3317
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
3318
|
+
const keyframes = bone[channel];
|
|
3319
|
+
if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
return pose;
|
|
3323
|
+
}
|
|
3324
|
+
var ENTITY_ANIMATION_CHANNELS;
|
|
3325
|
+
var init_EntityAnimation = __esm({
|
|
3326
|
+
"src/entity/EntityAnimation.ts"() {
|
|
3327
|
+
ENTITY_ANIMATION_CHANNELS = ["position", "rotation", "scale"];
|
|
3328
|
+
}
|
|
3329
|
+
});
|
|
3330
|
+
|
|
3331
|
+
// src/entity/scene/EntityAnimationPlayer.ts
|
|
3332
|
+
var ZERO, EntityAnimationPlayer;
|
|
3333
|
+
var init_EntityAnimationPlayer = __esm({
|
|
3334
|
+
"src/entity/scene/EntityAnimationPlayer.ts"() {
|
|
3335
|
+
init_EntityAnimation();
|
|
3336
|
+
ZERO = [0, 0, 0];
|
|
3337
|
+
EntityAnimationPlayer = class {
|
|
3338
|
+
constructor() {
|
|
3339
|
+
this.parts = [];
|
|
3340
|
+
this._time = 0;
|
|
3341
|
+
this.loop = false;
|
|
3342
|
+
this.speed = 1;
|
|
3343
|
+
}
|
|
3344
|
+
get animation() {
|
|
3345
|
+
return this._animation;
|
|
3346
|
+
}
|
|
3347
|
+
get time() {
|
|
3348
|
+
return this._time;
|
|
3349
|
+
}
|
|
3350
|
+
/**
|
|
3351
|
+
* Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
|
|
3352
|
+
* bones without a matching part are skipped.
|
|
3353
|
+
*/
|
|
3354
|
+
play(layers, animation, options = {}) {
|
|
3355
|
+
this.stop();
|
|
3356
|
+
this._animation = animation;
|
|
3357
|
+
this._time = options.time ?? 0;
|
|
3358
|
+
this.loop = options.loop ?? animation.loop;
|
|
3359
|
+
this.speed = options.speed ?? 1;
|
|
3360
|
+
for (const layer of layers) {
|
|
3361
|
+
for (const bone of Object.keys(animation.bones)) {
|
|
3362
|
+
const object = layer.getObjectByName(`group:${bone}`);
|
|
3363
|
+
if (!object) continue;
|
|
3364
|
+
this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
this.apply();
|
|
3368
|
+
}
|
|
3369
|
+
/** Restores the default poses. Returns whether an animation was active. */
|
|
3370
|
+
stop() {
|
|
3371
|
+
if (!this._animation) return false;
|
|
3372
|
+
for (const part of this.parts) {
|
|
3373
|
+
part.object.position.copy(part.position);
|
|
3374
|
+
part.object.rotation.copy(part.rotation);
|
|
3375
|
+
part.object.scale.copy(part.scale);
|
|
3376
|
+
}
|
|
3377
|
+
this.clear();
|
|
3378
|
+
return true;
|
|
3379
|
+
}
|
|
3380
|
+
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
3381
|
+
clear() {
|
|
3382
|
+
this.parts = [];
|
|
3383
|
+
this._animation = void 0;
|
|
3384
|
+
this._time = 0;
|
|
3385
|
+
}
|
|
3386
|
+
setTime(seconds) {
|
|
3387
|
+
if (!this._animation) return false;
|
|
3388
|
+
this._time = seconds;
|
|
3389
|
+
this.apply();
|
|
3390
|
+
return true;
|
|
3391
|
+
}
|
|
3392
|
+
advance(deltaSeconds) {
|
|
3393
|
+
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
3394
|
+
}
|
|
3395
|
+
apply() {
|
|
3396
|
+
const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
|
|
3397
|
+
for (const part of this.parts) {
|
|
3398
|
+
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
|
|
3399
|
+
part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
|
|
3400
|
+
part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
|
|
3401
|
+
part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
});
|
|
3407
|
+
|
|
3031
3408
|
// src/instance/InstanceReference.ts
|
|
3032
3409
|
function isInstanceReference(obj) {
|
|
3033
3410
|
return obj.isInstanceReference;
|
|
@@ -3524,6 +3901,241 @@ var init_SceneObject = __esm({
|
|
|
3524
3901
|
}
|
|
3525
3902
|
});
|
|
3526
3903
|
|
|
3904
|
+
// src/entity/scene/EntityObject.ts
|
|
3905
|
+
import { Color as Color3, Euler as Euler4, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
|
|
3906
|
+
function isEntityObject(obj) {
|
|
3907
|
+
return obj.isEntityObject;
|
|
3908
|
+
}
|
|
3909
|
+
var import_ts_deepmerge4, _EntityObject, EntityObject;
|
|
3910
|
+
var init_EntityObject = __esm({
|
|
3911
|
+
"src/entity/scene/EntityObject.ts"() {
|
|
3912
|
+
init_SceneObject();
|
|
3913
|
+
init_Caching();
|
|
3914
|
+
import_ts_deepmerge4 = __toESM(require_dist());
|
|
3915
|
+
init_Ticker();
|
|
3916
|
+
init_model();
|
|
3917
|
+
init_ModelTextures();
|
|
3918
|
+
init_AssetKey();
|
|
3919
|
+
init_Materials();
|
|
3920
|
+
init_MinecraftCubeTexture();
|
|
3921
|
+
init_three();
|
|
3922
|
+
init_EntityAnimationPlayer();
|
|
3923
|
+
_EntityObject = class _EntityObject extends SceneObject {
|
|
3924
|
+
constructor(entity, options) {
|
|
3925
|
+
super();
|
|
3926
|
+
this.entity = entity;
|
|
3927
|
+
this.isEntityObject = true;
|
|
3928
|
+
this.meshesCreated = false;
|
|
3929
|
+
this.geometries = /* @__PURE__ */ new Set();
|
|
3930
|
+
this.disposeWireframes = [];
|
|
3931
|
+
/** Scrolling materials are owned: their texture offset follows this entity's age. */
|
|
3932
|
+
this.scrollMaterials = [];
|
|
3933
|
+
/** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
|
|
3934
|
+
this.age = 0;
|
|
3935
|
+
this.animationPlayer = new EntityAnimationPlayer();
|
|
3936
|
+
this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
|
|
3937
|
+
this.addEventListener("added", () => this.updateScrollSubscription());
|
|
3938
|
+
this.addEventListener("removed", () => this.updateScrollSubscription());
|
|
3939
|
+
}
|
|
3940
|
+
async init() {
|
|
3941
|
+
this.createMeshes();
|
|
3942
|
+
await this.applyTextures();
|
|
3943
|
+
}
|
|
3944
|
+
dispose() {
|
|
3945
|
+
super.dispose();
|
|
3946
|
+
}
|
|
3947
|
+
disposeAndRemoveAllChildren() {
|
|
3948
|
+
this.clearScrollMaterials();
|
|
3949
|
+
for (const geometry of this.geometries) geometry.dispose();
|
|
3950
|
+
this.geometries.clear();
|
|
3951
|
+
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
3952
|
+
this.animationPlayer.clear();
|
|
3953
|
+
super.disposeAndRemoveAllChildren();
|
|
3954
|
+
}
|
|
3955
|
+
clearScrollMaterials() {
|
|
3956
|
+
Ticker.remove(this.scrollTicker);
|
|
3957
|
+
this.scrollTicker = void 0;
|
|
3958
|
+
for (const { material } of this.scrollMaterials.splice(0)) {
|
|
3959
|
+
material.map?.dispose();
|
|
3960
|
+
material.dispose();
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
updateScrollSubscription() {
|
|
3964
|
+
if (this.parent && this.scrollMaterials.length) {
|
|
3965
|
+
if (this.scrollTicker === void 0) {
|
|
3966
|
+
this.scrollTicker = Ticker.add(() => {
|
|
3967
|
+
this.age++;
|
|
3968
|
+
this.updateScroll();
|
|
3969
|
+
});
|
|
3970
|
+
}
|
|
3971
|
+
} else {
|
|
3972
|
+
Ticker.remove(this.scrollTicker);
|
|
3973
|
+
this.scrollTicker = void 0;
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3976
|
+
/** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
|
|
3977
|
+
updateScroll() {
|
|
3978
|
+
for (const { offset, speed } of this.scrollMaterials) {
|
|
3979
|
+
offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
|
|
3980
|
+
}
|
|
3981
|
+
this.notifyDirty();
|
|
3982
|
+
}
|
|
3983
|
+
//<editor-fold desc="ANIMATION">
|
|
3984
|
+
/** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
|
|
3985
|
+
get animation() {
|
|
3986
|
+
return this.animationPlayer.animation;
|
|
3987
|
+
}
|
|
3988
|
+
/** Seconds since the animation started, before looping. */
|
|
3989
|
+
get animationTime() {
|
|
3990
|
+
return this.animationPlayer.time;
|
|
3991
|
+
}
|
|
3992
|
+
/**
|
|
3993
|
+
* Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
|
|
3994
|
+
* Parts of every layer are matched by name and their current pose is the default the offsets add to.
|
|
3995
|
+
* The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
|
|
3996
|
+
*/
|
|
3997
|
+
playAnimation(animation, options) {
|
|
3998
|
+
this.createMeshes();
|
|
3999
|
+
const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
|
|
4000
|
+
this.animationPlayer.play(layers, animation, options);
|
|
4001
|
+
this.notifyDirty();
|
|
4002
|
+
}
|
|
4003
|
+
/** Stops the animation and restores the default pose. */
|
|
4004
|
+
stopAnimation() {
|
|
4005
|
+
if (this.animationPlayer.stop()) this.notifyDirty();
|
|
4006
|
+
}
|
|
4007
|
+
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
4008
|
+
setAnimationTime(seconds) {
|
|
4009
|
+
if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
|
|
4010
|
+
}
|
|
4011
|
+
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
4012
|
+
advanceAnimation(deltaSeconds) {
|
|
4013
|
+
if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
|
|
4014
|
+
}
|
|
4015
|
+
//</editor-fold>
|
|
4016
|
+
getLayerGroup(name) {
|
|
4017
|
+
return super.getGroupByName(`layer:${name}`);
|
|
4018
|
+
}
|
|
4019
|
+
getGroupByName(name, layerName) {
|
|
4020
|
+
return layerName === void 0 ? super.getGroupByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);
|
|
4021
|
+
}
|
|
4022
|
+
getMeshByName(name, layerName) {
|
|
4023
|
+
return layerName === void 0 ? super.getMeshByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`);
|
|
4024
|
+
}
|
|
4025
|
+
get entityLayers() {
|
|
4026
|
+
return this.entity.layers ?? { main: this.entity };
|
|
4027
|
+
}
|
|
4028
|
+
getTextureKey(layer) {
|
|
4029
|
+
if (layer.texture) return layer.texture;
|
|
4030
|
+
const key = layer.key;
|
|
4031
|
+
return new AssetKey(
|
|
4032
|
+
key.namespace,
|
|
4033
|
+
isAssetKey(key) ? key.getFullPath() : key.path,
|
|
4034
|
+
"textures",
|
|
4035
|
+
"entity",
|
|
4036
|
+
"assets",
|
|
4037
|
+
".png"
|
|
4038
|
+
);
|
|
4039
|
+
}
|
|
4040
|
+
async loadTextures(layer = this.entity) {
|
|
4041
|
+
return ModelTextures.get(this.getTextureKey(layer));
|
|
4042
|
+
}
|
|
4043
|
+
createMeshes(force = false) {
|
|
4044
|
+
if (this.meshesCreated && !force) return;
|
|
4045
|
+
const modelRoot = new Object3D3();
|
|
4046
|
+
const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
|
|
4047
|
+
if (transform) {
|
|
4048
|
+
for (const op of transform) {
|
|
4049
|
+
const matrix = new Matrix45();
|
|
4050
|
+
if ("scale" in op) matrix.makeScale(...op.scale);
|
|
4051
|
+
else if ("translate" in op) matrix.makeTranslation(...op.translate);
|
|
4052
|
+
else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
|
|
4053
|
+
modelRoot.matrix.multiply(matrix);
|
|
4054
|
+
}
|
|
4055
|
+
modelRoot.matrixAutoUpdate = false;
|
|
4056
|
+
} else if (this.options.flip ?? true) {
|
|
4057
|
+
modelRoot.scale.set(-1, -1, 1);
|
|
4058
|
+
}
|
|
4059
|
+
this.add(modelRoot);
|
|
4060
|
+
Object.entries(this.entityLayers).forEach(([name, layer], index) => {
|
|
4061
|
+
const group = this.createGroup(`layer:${name}`);
|
|
4062
|
+
modelRoot.add(group);
|
|
4063
|
+
const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
|
|
4064
|
+
this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
|
|
4065
|
+
});
|
|
4066
|
+
this.meshesCreated = true;
|
|
4067
|
+
}
|
|
4068
|
+
createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
|
|
4069
|
+
const anchor = this.createGroup(name);
|
|
4070
|
+
anchor.position.fromArray(part.pose.offset);
|
|
4071
|
+
anchor.rotation.set(...part.pose.rotation, "ZYX");
|
|
4072
|
+
anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
|
|
4073
|
+
parent.add(anchor);
|
|
4074
|
+
const size = part.texture ?? textureSize;
|
|
4075
|
+
for (const cube of part.cubes) {
|
|
4076
|
+
const [width, height, depth] = cube.size;
|
|
4077
|
+
const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];
|
|
4078
|
+
const texture = new MinecraftCubeTexture(...cube.uv, ...size);
|
|
4079
|
+
const uv = size[0] === 0 || size[1] === 0 ? new Array(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);
|
|
4080
|
+
const geometry = this._getBoxGeometryForDimensionsAndUv(
|
|
4081
|
+
width + growX * 2,
|
|
4082
|
+
height + growY * 2,
|
|
4083
|
+
depth + growZ * 2,
|
|
4084
|
+
uv
|
|
4085
|
+
).clone();
|
|
4086
|
+
this.geometries.add(geometry);
|
|
4087
|
+
geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
|
|
4088
|
+
if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
|
|
4089
|
+
const index = Array.from(geometry.getIndex().array);
|
|
4090
|
+
geometry.setIndex(index.concat(index.slice().reverse()));
|
|
4091
|
+
}
|
|
4092
|
+
const mesh = this.createMesh(name, geometry, material);
|
|
4093
|
+
mesh.renderOrder = renderOrder;
|
|
4094
|
+
anchor.add(mesh);
|
|
4095
|
+
if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));
|
|
4096
|
+
}
|
|
4097
|
+
for (const [childName, child] of Object.entries(part.children)) {
|
|
4098
|
+
this.createPart(childName, child, anchor, size, material, renderOrder, inward);
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
async applyTextures() {
|
|
4102
|
+
this.clearScrollMaterials();
|
|
4103
|
+
await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
|
|
4104
|
+
const mode = layer.render ?? layer.layer.render ?? "cutout";
|
|
4105
|
+
const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
|
|
4106
|
+
const scroll = Materials.entityModeScroll(mode);
|
|
4107
|
+
const assetKeyStr = this.getTextureKey(layer).serialize();
|
|
4108
|
+
const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color3(tint).getHexString()}:${assetKeyStr}`;
|
|
4109
|
+
let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
|
|
4110
|
+
if (!mat) {
|
|
4111
|
+
const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
|
|
4112
|
+
const imageData = await this.loadTextures(layer);
|
|
4113
|
+
if (!imageData) return;
|
|
4114
|
+
const canvas = imageData.data.canvas;
|
|
4115
|
+
const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
|
|
4116
|
+
mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
|
|
4117
|
+
if (scroll) {
|
|
4118
|
+
this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
this.getLayerGroup(name)?.traverse((object) => {
|
|
4122
|
+
if (isMesh(object)) object.material = mat;
|
|
4123
|
+
});
|
|
4124
|
+
}));
|
|
4125
|
+
if (!this.children.length) {
|
|
4126
|
+
this.clearScrollMaterials();
|
|
4127
|
+
} else if (this.scrollMaterials.length) {
|
|
4128
|
+
this.updateScroll();
|
|
4129
|
+
}
|
|
4130
|
+
this.updateScrollSubscription();
|
|
4131
|
+
this.notifyDirty();
|
|
4132
|
+
}
|
|
4133
|
+
};
|
|
4134
|
+
_EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
|
|
4135
|
+
EntityObject = _EntityObject;
|
|
4136
|
+
}
|
|
4137
|
+
});
|
|
4138
|
+
|
|
3527
4139
|
// src/three/BufferGeometryUtils.js
|
|
3528
4140
|
import {
|
|
3529
4141
|
BufferAttribute as BufferAttribute4,
|
|
@@ -4112,8 +4724,121 @@ var init_ModelCulling = __esm({
|
|
|
4112
4724
|
}
|
|
4113
4725
|
});
|
|
4114
4726
|
|
|
4727
|
+
// src/model/SpecialItems.ts
|
|
4728
|
+
import { Matrix4 as Matrix48 } from "three";
|
|
4729
|
+
var SpecialItems;
|
|
4730
|
+
var init_SpecialItems = __esm({
|
|
4731
|
+
"src/model/SpecialItems.ts"() {
|
|
4732
|
+
init_AssetKey();
|
|
4733
|
+
init_Entities();
|
|
4734
|
+
SpecialItems = class {
|
|
4735
|
+
/** Resolves the static entity parts drawn by a special item renderer, in model units. */
|
|
4736
|
+
static async getParts(special, root) {
|
|
4737
|
+
const texture = (id, directory) => {
|
|
4738
|
+
const key = AssetKey.parse("textures", id);
|
|
4739
|
+
return new AssetKey(
|
|
4740
|
+
key.namespace,
|
|
4741
|
+
[directory, key.getFullPath()].filter(Boolean).join("/"),
|
|
4742
|
+
"textures",
|
|
4743
|
+
"entity",
|
|
4744
|
+
"assets",
|
|
4745
|
+
".png",
|
|
4746
|
+
root
|
|
4747
|
+
);
|
|
4748
|
+
};
|
|
4749
|
+
const load = async (id, textureKey, transform, rotations = {}) => {
|
|
4750
|
+
const key = new AssetKey("minecraft", id, void 0, void 0, "entity-models", ".json", root);
|
|
4751
|
+
const model = await Entities.getEntity(key, textureKey, { layer: "main" });
|
|
4752
|
+
if (!model) throw new Error(`Missing entity model minecraft:${id} for special item ${special.type}`);
|
|
4753
|
+
return { model, transform, rotations };
|
|
4754
|
+
};
|
|
4755
|
+
switch (special.type) {
|
|
4756
|
+
case "minecraft:chest":
|
|
4757
|
+
case "chest": {
|
|
4758
|
+
const angle = -(special.openness ?? 0) * Math.PI / 2;
|
|
4759
|
+
const chest = await load("chest", texture(special.texture, "chest"), new Matrix48(), {
|
|
4760
|
+
lid: [angle, 0, 0],
|
|
4761
|
+
lock: [angle, 0, 0]
|
|
4762
|
+
});
|
|
4763
|
+
chest.model = { ...chest.model, render: "solid", layers: void 0 };
|
|
4764
|
+
return [chest];
|
|
4765
|
+
}
|
|
4766
|
+
case "minecraft:bed":
|
|
4767
|
+
case "bed": {
|
|
4768
|
+
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));
|
|
4769
|
+
const key = texture(special.texture, "bed");
|
|
4770
|
+
return Promise.all([
|
|
4771
|
+
load("bed_head", key, transform),
|
|
4772
|
+
load("bed_foot", key, new Matrix48().makeTranslation(0, 0, -16).multiply(transform))
|
|
4773
|
+
]);
|
|
4774
|
+
}
|
|
4775
|
+
case "minecraft:head":
|
|
4776
|
+
case "head": {
|
|
4777
|
+
const models = {
|
|
4778
|
+
skeleton: "skeleton_skull",
|
|
4779
|
+
wither_skeleton: "wither_skeleton_skull",
|
|
4780
|
+
zombie: "zombie_head",
|
|
4781
|
+
creeper: "creeper_head",
|
|
4782
|
+
dragon: "dragon_skull",
|
|
4783
|
+
piglin: "piglin_head"
|
|
4784
|
+
};
|
|
4785
|
+
const id = Object.prototype.hasOwnProperty.call(models, special.kind) ? models[special.kind] : void 0;
|
|
4786
|
+
if (!id) throw new Error(`Unsupported special item head kind ${special.kind}`);
|
|
4787
|
+
const animation = (special.animation ?? 0) * Math.PI * 0.2;
|
|
4788
|
+
const rotations = { head: [0, Math.PI, 0] };
|
|
4789
|
+
if (special.kind === "dragon") rotations.jaw = [(Math.sin(animation) + 1) * 0.2, 0, 0];
|
|
4790
|
+
if (special.kind === "piglin") {
|
|
4791
|
+
rotations.left_ear = [0, 0, -(Math.cos(animation * 1.2) + 2.5) * 0.2];
|
|
4792
|
+
rotations.right_ear = [0, 0, (Math.cos(animation) + 2.5) * 0.2];
|
|
4793
|
+
}
|
|
4794
|
+
return [await load(
|
|
4795
|
+
id,
|
|
4796
|
+
special.texture ? texture(special.texture, "") : void 0,
|
|
4797
|
+
new Matrix48().makeTranslation(8, 0, 8).multiply(new Matrix48().makeScale(-1, -1, 1)),
|
|
4798
|
+
rotations
|
|
4799
|
+
)];
|
|
4800
|
+
}
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
/** An owned material with model-preview shading; its entity texture remains shared. */
|
|
4804
|
+
static createMaterial(source, shade) {
|
|
4805
|
+
const material = source.clone();
|
|
4806
|
+
if (shade) {
|
|
4807
|
+
material.onBeforeCompile = (shader) => {
|
|
4808
|
+
shader.vertexShader = `varying float itemLight;
|
|
4809
|
+
${shader.vertexShader}`.replace("#include <begin_vertex>", `
|
|
4810
|
+
#include <begin_vertex>
|
|
4811
|
+
vec3 N = inverseTransformDirection(normalMatrix * normal, viewMatrix);
|
|
4812
|
+
itemLight = (1.0 + N.y) * 0.25 - N.x * N.x * 0.15 + N.z * N.z * 0.05 + 0.5;
|
|
4813
|
+
`);
|
|
4814
|
+
shader.fragmentShader = `varying float itemLight;
|
|
4815
|
+
${shader.fragmentShader}`.replace(
|
|
4816
|
+
"#include <color_fragment>",
|
|
4817
|
+
"#include <color_fragment>\ndiffuseColor.rgb *= itemLight;"
|
|
4818
|
+
);
|
|
4819
|
+
};
|
|
4820
|
+
material.customProgramCacheKey = () => "special-item-side";
|
|
4821
|
+
}
|
|
4822
|
+
return material;
|
|
4823
|
+
}
|
|
4824
|
+
};
|
|
4825
|
+
}
|
|
4826
|
+
});
|
|
4827
|
+
|
|
4828
|
+
// src/model/GuiLight.ts
|
|
4829
|
+
var GuiLight;
|
|
4830
|
+
var init_GuiLight = __esm({
|
|
4831
|
+
"src/model/GuiLight.ts"() {
|
|
4832
|
+
GuiLight = /* @__PURE__ */ ((GuiLight2) => {
|
|
4833
|
+
GuiLight2["FRONT"] = "front";
|
|
4834
|
+
GuiLight2["SIDE"] = "side";
|
|
4835
|
+
return GuiLight2;
|
|
4836
|
+
})(GuiLight || {});
|
|
4837
|
+
}
|
|
4838
|
+
});
|
|
4839
|
+
|
|
4115
4840
|
// src/model/scene/ModelObject.ts
|
|
4116
|
-
import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as
|
|
4841
|
+
import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as Matrix49 } from "three";
|
|
4117
4842
|
function isModelObject(obj) {
|
|
4118
4843
|
return obj.isModelObject;
|
|
4119
4844
|
}
|
|
@@ -4128,21 +4853,60 @@ var init_ModelObject = __esm({
|
|
|
4128
4853
|
import_ts_deepmerge5 = __toESM(require_dist());
|
|
4129
4854
|
init_log();
|
|
4130
4855
|
init_CubeFace();
|
|
4856
|
+
init_DisplayPosition();
|
|
4131
4857
|
init_DisplayTransforms();
|
|
4132
4858
|
init_ModelCulling();
|
|
4859
|
+
init_SpecialItems();
|
|
4860
|
+
init_EntityObject();
|
|
4861
|
+
init_GuiLight();
|
|
4133
4862
|
p7 = prefix("ModelObject");
|
|
4134
4863
|
_ModelObject = class _ModelObject extends SceneObject {
|
|
4135
4864
|
constructor(originalModel, options) {
|
|
4136
4865
|
super(options);
|
|
4137
4866
|
this.originalModel = originalModel;
|
|
4138
4867
|
this.isModelObject = true;
|
|
4868
|
+
this.specialMaterials = /* @__PURE__ */ new Map();
|
|
4139
4869
|
this.meshesCreated = false;
|
|
4140
4870
|
this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
|
|
4871
|
+
if (originalModel.special) this.options.instanceMeshes = false;
|
|
4141
4872
|
if (this.options.tints) this.options.tints = { ...this.options.tints };
|
|
4142
4873
|
this.addEventListener("added", () => this.updateAnimationSubscription());
|
|
4143
4874
|
this.addEventListener("removed", () => this.updateAnimationSubscription());
|
|
4144
4875
|
}
|
|
4145
4876
|
async init() {
|
|
4877
|
+
const special = this.originalModel.special;
|
|
4878
|
+
if (special) {
|
|
4879
|
+
const parts = await SpecialItems.getParts(special, this.originalModel.key?.root);
|
|
4880
|
+
const transform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : new Matrix49();
|
|
4881
|
+
transform.multiply(new Matrix49().makeTranslation(-8, -8, -8));
|
|
4882
|
+
try {
|
|
4883
|
+
for (const part of parts) {
|
|
4884
|
+
const object = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe });
|
|
4885
|
+
object.matrix.copy(transform).multiply(part.transform);
|
|
4886
|
+
object.matrixAutoUpdate = false;
|
|
4887
|
+
this.add(object);
|
|
4888
|
+
await object.init();
|
|
4889
|
+
object.iterateAllMeshes((mesh) => {
|
|
4890
|
+
const source = mesh.material;
|
|
4891
|
+
let material = this.specialMaterials.get(source);
|
|
4892
|
+
if (!material) {
|
|
4893
|
+
const front = this.options.displayPosition === "gui" /* GUI */ && this.originalModel.gui_light === "front" /* FRONT */;
|
|
4894
|
+
material = SpecialItems.createMaterial(source, !front);
|
|
4895
|
+
this.specialMaterials.set(source, material);
|
|
4896
|
+
}
|
|
4897
|
+
mesh.material = material;
|
|
4898
|
+
});
|
|
4899
|
+
for (const [name, rotation] of Object.entries(part.rotations)) {
|
|
4900
|
+
object.getGroupByName(name)?.rotation.set(...rotation, "ZYX");
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
} catch (error) {
|
|
4904
|
+
this.disposeAndRemoveAllChildren();
|
|
4905
|
+
throw error;
|
|
4906
|
+
}
|
|
4907
|
+
this.notifyDirty();
|
|
4908
|
+
return;
|
|
4909
|
+
}
|
|
4146
4910
|
await this.loadTextures();
|
|
4147
4911
|
this.createMeshes();
|
|
4148
4912
|
this.applyTextures();
|
|
@@ -4192,12 +4956,12 @@ var init_ModelObject = __esm({
|
|
|
4192
4956
|
}
|
|
4193
4957
|
elGeo.setAttribute("color", new BufferAttribute5(colors, 3));
|
|
4194
4958
|
}
|
|
4195
|
-
elGeo.applyMatrix4(new
|
|
4196
|
-
elGeo.applyMatrix4(new
|
|
4959
|
+
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));
|
|
4960
|
+
elGeo.applyMatrix4(new Matrix49().makeTranslation(el.from[0], el.from[1], el.from[2]));
|
|
4197
4961
|
if (el.rotation) {
|
|
4198
4962
|
applyElementRotation(el.rotation, elGeo);
|
|
4199
4963
|
}
|
|
4200
|
-
elGeo.applyMatrix4(new
|
|
4964
|
+
elGeo.applyMatrix4(new Matrix49().makeTranslation(-8, -8, -8));
|
|
4201
4965
|
if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
|
|
4202
4966
|
if (this.options.mergeMeshes) {
|
|
4203
4967
|
allGeos.push(elGeo);
|
|
@@ -4287,6 +5051,8 @@ var init_ModelObject = __esm({
|
|
|
4287
5051
|
this.atlasMaterial?.dispose();
|
|
4288
5052
|
this.atlasTexture = void 0;
|
|
4289
5053
|
this.atlasMaterial = void 0;
|
|
5054
|
+
for (const material of this.specialMaterials.values()) material.dispose();
|
|
5055
|
+
this.specialMaterials.clear();
|
|
4290
5056
|
super.disposeAndRemoveAllChildren();
|
|
4291
5057
|
}
|
|
4292
5058
|
};
|
|
@@ -4677,96 +5443,8 @@ var Meshes = class _Meshes {
|
|
|
4677
5443
|
}
|
|
4678
5444
|
};
|
|
4679
5445
|
|
|
4680
|
-
// src/
|
|
4681
|
-
|
|
4682
|
-
init_CubeFace();
|
|
4683
|
-
var MinecraftCubeTexture = class {
|
|
4684
|
-
constructor(u, v, width, height) {
|
|
4685
|
-
this.u = u;
|
|
4686
|
-
this.v = v;
|
|
4687
|
-
this.width = width;
|
|
4688
|
-
this.height = height;
|
|
4689
|
-
}
|
|
4690
|
-
mapW(x) {
|
|
4691
|
-
return x / this.width;
|
|
4692
|
-
}
|
|
4693
|
-
mapH(x) {
|
|
4694
|
-
return 1 - x / this.height;
|
|
4695
|
-
}
|
|
4696
|
-
getUvEast(w, h, l) {
|
|
4697
|
-
return [
|
|
4698
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
4699
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
4700
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)],
|
|
4701
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
4702
|
-
];
|
|
4703
|
-
}
|
|
4704
|
-
getUvWest(w, h, l) {
|
|
4705
|
-
return [
|
|
4706
|
-
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
4707
|
-
[this.mapW(this.u), this.mapH(this.v + l + h)],
|
|
4708
|
-
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
4709
|
-
[this.mapW(this.u), this.mapH(this.v + l)]
|
|
4710
|
-
];
|
|
4711
|
-
}
|
|
4712
|
-
getUvUp(w, h, l) {
|
|
4713
|
-
return [
|
|
4714
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
4715
|
-
[this.mapW(this.u + l + w + w), this.mapH(this.v + l)],
|
|
4716
|
-
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
4717
|
-
[this.mapW(this.u + l + w + w), this.mapH(this.v)]
|
|
4718
|
-
];
|
|
4719
|
-
}
|
|
4720
|
-
getUvDown(w, h, l) {
|
|
4721
|
-
return [
|
|
4722
|
-
[this.mapW(this.u + l), this.mapH(this.v)],
|
|
4723
|
-
[this.mapW(this.u + l + w), this.mapH(this.v)],
|
|
4724
|
-
[this.mapW(this.u + l), this.mapH(this.v + l)],
|
|
4725
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)]
|
|
4726
|
-
];
|
|
4727
|
-
}
|
|
4728
|
-
getUvSouth(w, h, l) {
|
|
4729
|
-
return [
|
|
4730
|
-
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l + h)],
|
|
4731
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
|
|
4732
|
-
[this.mapW(this.u + l + w + l + w), this.mapH(this.v + l)],
|
|
4733
|
-
[this.mapW(this.u + l + w + l), this.mapH(this.v + l)]
|
|
4734
|
-
];
|
|
4735
|
-
}
|
|
4736
|
-
getUvNorth(w, h, l) {
|
|
4737
|
-
return [
|
|
4738
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
|
|
4739
|
-
[this.mapW(this.u + l), this.mapH(this.v + l + h)],
|
|
4740
|
-
[this.mapW(this.u + l + w), this.mapH(this.v + l)],
|
|
4741
|
-
[this.mapW(this.u + l), this.mapH(this.v + l)]
|
|
4742
|
-
];
|
|
4743
|
-
}
|
|
4744
|
-
getFaceUv(face, w, h, l) {
|
|
4745
|
-
switch (face) {
|
|
4746
|
-
case "east" /* EAST */:
|
|
4747
|
-
return this.getUvEast(w, h, l);
|
|
4748
|
-
case "west" /* WEST */:
|
|
4749
|
-
return this.getUvWest(w, h, l);
|
|
4750
|
-
case "up" /* UP */:
|
|
4751
|
-
return this.getUvUp(w, h, l);
|
|
4752
|
-
case "down" /* DOWN */:
|
|
4753
|
-
return this.getUvDown(w, h, l);
|
|
4754
|
-
case "south" /* SOUTH */:
|
|
4755
|
-
return this.getUvSouth(w, h, l);
|
|
4756
|
-
case "north" /* NORTH */:
|
|
4757
|
-
return this.getUvNorth(w, h, l);
|
|
4758
|
-
}
|
|
4759
|
-
}
|
|
4760
|
-
toUvArray(w, h, l, mirror = false) {
|
|
4761
|
-
const uv = [];
|
|
4762
|
-
for (let i = 0; i < CUBE_FACES.length; i++) {
|
|
4763
|
-
const face = mirror && i < 2 ? CUBE_FACES[1 - i] : CUBE_FACES[i];
|
|
4764
|
-
const corners = this.getFaceUv(face, w, h, l);
|
|
4765
|
-
UVMapper.setFaceUvInArray(uv, i * 4, mirror ? [corners[1], corners[0], corners[3], corners[2]] : corners);
|
|
4766
|
-
}
|
|
4767
|
-
return uv;
|
|
4768
|
-
}
|
|
4769
|
-
};
|
|
5446
|
+
// src/index.ts
|
|
5447
|
+
init_MinecraftCubeTexture();
|
|
4770
5448
|
|
|
4771
5449
|
// src/SceneStats.ts
|
|
4772
5450
|
var SceneStats = class {
|
|
@@ -4860,116 +5538,7 @@ var BlockEntities = class {
|
|
|
4860
5538
|
|
|
4861
5539
|
// src/assets/index.ts
|
|
4862
5540
|
init_BlockStates();
|
|
4863
|
-
|
|
4864
|
-
// src/assets/Entities.ts
|
|
4865
|
-
init_AssetKey();
|
|
4866
|
-
init_AssetLoader();
|
|
4867
|
-
init_source();
|
|
4868
|
-
init_Caching();
|
|
4869
|
-
init_Assets();
|
|
4870
|
-
init_MineRenderError();
|
|
4871
|
-
init_ModelTextures();
|
|
4872
|
-
var Entities = class {
|
|
4873
|
-
static async getEntityList() {
|
|
4874
|
-
const collect = async (path) => {
|
|
4875
|
-
const prefix2 = path ? `${path}/` : "";
|
|
4876
|
-
const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
|
|
4877
|
-
const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
|
|
4878
|
-
if (!list) return [];
|
|
4879
|
-
const files = list.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
|
|
4880
|
-
const children = await Promise.all(list.directories.map((directory) => collect(`${prefix2}${directory}`)));
|
|
4881
|
-
return [...files, ...children.flat()];
|
|
4882
|
-
};
|
|
4883
|
-
return collect("");
|
|
4884
|
-
}
|
|
4885
|
-
static async getModelFile(modelKey) {
|
|
4886
|
-
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4887
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
|
|
4888
|
-
return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4889
|
-
}
|
|
4890
|
-
static async getLayerList(modelKey) {
|
|
4891
|
-
return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
|
|
4892
|
-
}
|
|
4893
|
-
/** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
|
|
4894
|
-
static async getPassList(modelKey) {
|
|
4895
|
-
return (await this.getModelFile(modelKey))?.passes ?? [];
|
|
4896
|
-
}
|
|
4897
|
-
static async getEntity(modelKey, textureKey, options) {
|
|
4898
|
-
const model = await this.getModelFile(modelKey);
|
|
4899
|
-
if (!model) return void 0;
|
|
4900
|
-
const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
|
|
4901
|
-
const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
|
|
4902
|
-
if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
|
|
4903
|
-
draws.push(...passes);
|
|
4904
|
-
const names = [];
|
|
4905
|
-
const selected = draws.map((pass) => {
|
|
4906
|
-
const layer = model.layers[pass.layer];
|
|
4907
|
-
if (!layer) {
|
|
4908
|
-
throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
|
|
4909
|
-
}
|
|
4910
|
-
let name = pass.layer;
|
|
4911
|
-
for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
|
|
4912
|
-
names.push(name);
|
|
4913
|
-
return { name, layer, pass };
|
|
4914
|
-
});
|
|
4915
|
-
const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
|
|
4916
|
-
const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
|
|
4917
|
-
const textureLocation = pass.textureLocation ?? layer.textureLocation;
|
|
4918
|
-
let texture;
|
|
4919
|
-
if (override) {
|
|
4920
|
-
const path = isAssetKey(override) ? override.getFullPath() : override.path;
|
|
4921
|
-
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);
|
|
4922
|
-
} else if (textureLocation !== void 0) {
|
|
4923
|
-
texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
|
|
4924
|
-
} else {
|
|
4925
|
-
texture = await this.resolveTexture(modelKey);
|
|
4926
|
-
}
|
|
4927
|
-
const render = pass.render ?? layer.render;
|
|
4928
|
-
return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
|
|
4929
|
-
})));
|
|
4930
|
-
return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
|
|
4931
|
-
}
|
|
4932
|
-
/**
|
|
4933
|
-
* Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
|
|
4934
|
-
*/
|
|
4935
|
-
static async getAnimations(modelKey) {
|
|
4936
|
-
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4937
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
|
|
4938
|
-
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4939
|
-
return file?.animations;
|
|
4940
|
-
}
|
|
4941
|
-
static async resolveTexture(modelKey) {
|
|
4942
|
-
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4943
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
|
|
4944
|
-
return Caching.entityTextureCache.get(key.serialize(), async () => {
|
|
4945
|
-
const name = path.split("/").pop();
|
|
4946
|
-
for (const candidate of [path, `${path}/${name}`]) {
|
|
4947
|
-
const texture = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png");
|
|
4948
|
-
if (await ModelTextures.get(texture)) return texture;
|
|
4949
|
-
}
|
|
4950
|
-
const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json");
|
|
4951
|
-
const list = await AssetLoader.get(listKey, "list" /* LIST */);
|
|
4952
|
-
const files = list?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
|
|
4953
|
-
const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
|
|
4954
|
-
if (!file) return void 0;
|
|
4955
|
-
const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json");
|
|
4956
|
-
const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
|
|
4957
|
-
const assets = variant?.assets;
|
|
4958
|
-
const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
|
|
4959
|
-
return typeof textureId === "string" ? AssetKey.parse("textures", textureId) : void 0;
|
|
4960
|
-
});
|
|
4961
|
-
}
|
|
4962
|
-
/** @deprecated Use getEntityList(); block entities share the entity dataset. */
|
|
4963
|
-
static getBlockList() {
|
|
4964
|
-
return this.getEntityList();
|
|
4965
|
-
}
|
|
4966
|
-
/** @deprecated Use getEntity(); block entities share the entity dataset. */
|
|
4967
|
-
static getBlock(modelKey, textureKey, options) {
|
|
4968
|
-
return this.getEntity(modelKey, textureKey, options);
|
|
4969
|
-
}
|
|
4970
|
-
};
|
|
4971
|
-
|
|
4972
|
-
// src/assets/index.ts
|
|
5541
|
+
init_Entities();
|
|
4973
5542
|
init_ModelTextures();
|
|
4974
5543
|
init_Models();
|
|
4975
5544
|
init_source();
|
|
@@ -5014,346 +5583,12 @@ function trimCanvas(source) {
|
|
|
5014
5583
|
return canvas;
|
|
5015
5584
|
}
|
|
5016
5585
|
|
|
5017
|
-
// src/entity/
|
|
5018
|
-
|
|
5019
|
-
function catmullRom(delta, p0, p1, p22, p32) {
|
|
5020
|
-
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);
|
|
5021
|
-
}
|
|
5022
|
-
function sampleEntityKeyframes(keyframes, time) {
|
|
5023
|
-
if (keyframes.length === 0) return [0, 0, 0];
|
|
5024
|
-
let low = 0, high = keyframes.length;
|
|
5025
|
-
while (low < high) {
|
|
5026
|
-
const middle = low + high >>> 1;
|
|
5027
|
-
if (time <= keyframes[middle].time) high = middle;
|
|
5028
|
-
else low = middle + 1;
|
|
5029
|
-
}
|
|
5030
|
-
const a = Math.max(0, low - 1);
|
|
5031
|
-
const b = Math.min(keyframes.length - 1, a + 1);
|
|
5032
|
-
const from = keyframes[a];
|
|
5033
|
-
const to = keyframes[b];
|
|
5034
|
-
const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
|
|
5035
|
-
if (to.interpolation === "catmullrom") {
|
|
5036
|
-
const before = keyframes[Math.max(0, a - 1)].value;
|
|
5037
|
-
const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
|
|
5038
|
-
return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
|
|
5039
|
-
}
|
|
5040
|
-
const target = to.pre ?? to.value;
|
|
5041
|
-
return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
|
|
5042
|
-
}
|
|
5043
|
-
function entityAnimationTime(animation, time, loop = animation.loop) {
|
|
5044
|
-
return loop && animation.length > 0 ? time % animation.length : time;
|
|
5045
|
-
}
|
|
5046
|
-
function sampleEntityAnimation(animation, time, loop = animation.loop) {
|
|
5047
|
-
const elapsed = entityAnimationTime(animation, time, loop);
|
|
5048
|
-
const pose = {};
|
|
5049
|
-
for (const [name, bone] of Object.entries(animation.bones)) {
|
|
5050
|
-
const sampled = pose[name] = {};
|
|
5051
|
-
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
5052
|
-
const keyframes = bone[channel];
|
|
5053
|
-
if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
|
|
5054
|
-
}
|
|
5055
|
-
}
|
|
5056
|
-
return pose;
|
|
5057
|
-
}
|
|
5058
|
-
|
|
5059
|
-
// src/entity/scene/EntityAnimationPlayer.ts
|
|
5060
|
-
var ZERO = [0, 0, 0];
|
|
5061
|
-
var EntityAnimationPlayer = class {
|
|
5062
|
-
constructor() {
|
|
5063
|
-
this.parts = [];
|
|
5064
|
-
this._time = 0;
|
|
5065
|
-
this.loop = false;
|
|
5066
|
-
this.speed = 1;
|
|
5067
|
-
}
|
|
5068
|
-
get animation() {
|
|
5069
|
-
return this._animation;
|
|
5070
|
-
}
|
|
5071
|
-
get time() {
|
|
5072
|
-
return this._time;
|
|
5073
|
-
}
|
|
5074
|
-
/**
|
|
5075
|
-
* Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
|
|
5076
|
-
* bones without a matching part are skipped.
|
|
5077
|
-
*/
|
|
5078
|
-
play(layers, animation, options = {}) {
|
|
5079
|
-
this.stop();
|
|
5080
|
-
this._animation = animation;
|
|
5081
|
-
this._time = options.time ?? 0;
|
|
5082
|
-
this.loop = options.loop ?? animation.loop;
|
|
5083
|
-
this.speed = options.speed ?? 1;
|
|
5084
|
-
for (const layer of layers) {
|
|
5085
|
-
for (const bone of Object.keys(animation.bones)) {
|
|
5086
|
-
const object = layer.getObjectByName(`group:${bone}`);
|
|
5087
|
-
if (!object) continue;
|
|
5088
|
-
this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
|
|
5089
|
-
}
|
|
5090
|
-
}
|
|
5091
|
-
this.apply();
|
|
5092
|
-
}
|
|
5093
|
-
/** Restores the default poses. Returns whether an animation was active. */
|
|
5094
|
-
stop() {
|
|
5095
|
-
if (!this._animation) return false;
|
|
5096
|
-
for (const part of this.parts) {
|
|
5097
|
-
part.object.position.copy(part.position);
|
|
5098
|
-
part.object.rotation.copy(part.rotation);
|
|
5099
|
-
part.object.scale.copy(part.scale);
|
|
5100
|
-
}
|
|
5101
|
-
this.clear();
|
|
5102
|
-
return true;
|
|
5103
|
-
}
|
|
5104
|
-
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
5105
|
-
clear() {
|
|
5106
|
-
this.parts = [];
|
|
5107
|
-
this._animation = void 0;
|
|
5108
|
-
this._time = 0;
|
|
5109
|
-
}
|
|
5110
|
-
setTime(seconds) {
|
|
5111
|
-
if (!this._animation) return false;
|
|
5112
|
-
this._time = seconds;
|
|
5113
|
-
this.apply();
|
|
5114
|
-
return true;
|
|
5115
|
-
}
|
|
5116
|
-
advance(deltaSeconds) {
|
|
5117
|
-
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
5118
|
-
}
|
|
5119
|
-
apply() {
|
|
5120
|
-
const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
|
|
5121
|
-
for (const part of this.parts) {
|
|
5122
|
-
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
|
|
5123
|
-
part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
|
|
5124
|
-
part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
|
|
5125
|
-
part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
|
|
5126
|
-
}
|
|
5127
|
-
}
|
|
5128
|
-
};
|
|
5586
|
+
// src/entity/index.ts
|
|
5587
|
+
init_EntityAnimation();
|
|
5129
5588
|
|
|
5130
|
-
// src/entity/scene/
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
var import_ts_deepmerge4 = __toESM(require_dist());
|
|
5134
|
-
init_Ticker();
|
|
5135
|
-
init_model();
|
|
5136
|
-
init_ModelTextures();
|
|
5137
|
-
init_AssetKey();
|
|
5138
|
-
init_Materials();
|
|
5139
|
-
import { Color as Color3, Euler as Euler4, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
|
|
5140
|
-
init_three();
|
|
5141
|
-
var _EntityObject = class _EntityObject extends SceneObject {
|
|
5142
|
-
constructor(entity, options) {
|
|
5143
|
-
super();
|
|
5144
|
-
this.entity = entity;
|
|
5145
|
-
this.isEntityObject = true;
|
|
5146
|
-
this.meshesCreated = false;
|
|
5147
|
-
this.geometries = /* @__PURE__ */ new Set();
|
|
5148
|
-
this.disposeWireframes = [];
|
|
5149
|
-
/** Scrolling materials are owned: their texture offset follows this entity's age. */
|
|
5150
|
-
this.scrollMaterials = [];
|
|
5151
|
-
/** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
|
|
5152
|
-
this.age = 0;
|
|
5153
|
-
this.animationPlayer = new EntityAnimationPlayer();
|
|
5154
|
-
this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
|
|
5155
|
-
this.addEventListener("added", () => this.updateScrollSubscription());
|
|
5156
|
-
this.addEventListener("removed", () => this.updateScrollSubscription());
|
|
5157
|
-
}
|
|
5158
|
-
async init() {
|
|
5159
|
-
this.createMeshes();
|
|
5160
|
-
await this.applyTextures();
|
|
5161
|
-
}
|
|
5162
|
-
dispose() {
|
|
5163
|
-
super.dispose();
|
|
5164
|
-
}
|
|
5165
|
-
disposeAndRemoveAllChildren() {
|
|
5166
|
-
this.clearScrollMaterials();
|
|
5167
|
-
for (const geometry of this.geometries) geometry.dispose();
|
|
5168
|
-
this.geometries.clear();
|
|
5169
|
-
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
5170
|
-
this.animationPlayer.clear();
|
|
5171
|
-
super.disposeAndRemoveAllChildren();
|
|
5172
|
-
}
|
|
5173
|
-
clearScrollMaterials() {
|
|
5174
|
-
Ticker.remove(this.scrollTicker);
|
|
5175
|
-
this.scrollTicker = void 0;
|
|
5176
|
-
for (const { material } of this.scrollMaterials.splice(0)) {
|
|
5177
|
-
material.map?.dispose();
|
|
5178
|
-
material.dispose();
|
|
5179
|
-
}
|
|
5180
|
-
}
|
|
5181
|
-
updateScrollSubscription() {
|
|
5182
|
-
if (this.parent && this.scrollMaterials.length) {
|
|
5183
|
-
if (this.scrollTicker === void 0) {
|
|
5184
|
-
this.scrollTicker = Ticker.add(() => {
|
|
5185
|
-
this.age++;
|
|
5186
|
-
this.updateScroll();
|
|
5187
|
-
});
|
|
5188
|
-
}
|
|
5189
|
-
} else {
|
|
5190
|
-
Ticker.remove(this.scrollTicker);
|
|
5191
|
-
this.scrollTicker = void 0;
|
|
5192
|
-
}
|
|
5193
|
-
}
|
|
5194
|
-
/** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
|
|
5195
|
-
updateScroll() {
|
|
5196
|
-
for (const { offset, speed } of this.scrollMaterials) {
|
|
5197
|
-
offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
|
|
5198
|
-
}
|
|
5199
|
-
this.notifyDirty();
|
|
5200
|
-
}
|
|
5201
|
-
//<editor-fold desc="ANIMATION">
|
|
5202
|
-
/** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
|
|
5203
|
-
get animation() {
|
|
5204
|
-
return this.animationPlayer.animation;
|
|
5205
|
-
}
|
|
5206
|
-
/** Seconds since the animation started, before looping. */
|
|
5207
|
-
get animationTime() {
|
|
5208
|
-
return this.animationPlayer.time;
|
|
5209
|
-
}
|
|
5210
|
-
/**
|
|
5211
|
-
* Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
|
|
5212
|
-
* Parts of every layer are matched by name and their current pose is the default the offsets add to.
|
|
5213
|
-
* The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
|
|
5214
|
-
*/
|
|
5215
|
-
playAnimation(animation, options) {
|
|
5216
|
-
this.createMeshes();
|
|
5217
|
-
const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
|
|
5218
|
-
this.animationPlayer.play(layers, animation, options);
|
|
5219
|
-
this.notifyDirty();
|
|
5220
|
-
}
|
|
5221
|
-
/** Stops the animation and restores the default pose. */
|
|
5222
|
-
stopAnimation() {
|
|
5223
|
-
if (this.animationPlayer.stop()) this.notifyDirty();
|
|
5224
|
-
}
|
|
5225
|
-
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
5226
|
-
setAnimationTime(seconds) {
|
|
5227
|
-
if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
|
|
5228
|
-
}
|
|
5229
|
-
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
5230
|
-
advanceAnimation(deltaSeconds) {
|
|
5231
|
-
if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
|
|
5232
|
-
}
|
|
5233
|
-
//</editor-fold>
|
|
5234
|
-
getLayerGroup(name) {
|
|
5235
|
-
return super.getGroupByName(`layer:${name}`);
|
|
5236
|
-
}
|
|
5237
|
-
getGroupByName(name, layerName) {
|
|
5238
|
-
return layerName === void 0 ? super.getGroupByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);
|
|
5239
|
-
}
|
|
5240
|
-
getMeshByName(name, layerName) {
|
|
5241
|
-
return layerName === void 0 ? super.getMeshByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`);
|
|
5242
|
-
}
|
|
5243
|
-
get entityLayers() {
|
|
5244
|
-
return this.entity.layers ?? { main: this.entity };
|
|
5245
|
-
}
|
|
5246
|
-
getTextureKey(layer) {
|
|
5247
|
-
if (layer.texture) return layer.texture;
|
|
5248
|
-
const key = layer.key;
|
|
5249
|
-
return new AssetKey(
|
|
5250
|
-
key.namespace,
|
|
5251
|
-
isAssetKey(key) ? key.getFullPath() : key.path,
|
|
5252
|
-
"textures",
|
|
5253
|
-
"entity",
|
|
5254
|
-
"assets",
|
|
5255
|
-
".png"
|
|
5256
|
-
);
|
|
5257
|
-
}
|
|
5258
|
-
async loadTextures(layer = this.entity) {
|
|
5259
|
-
return ModelTextures.get(this.getTextureKey(layer));
|
|
5260
|
-
}
|
|
5261
|
-
createMeshes(force = false) {
|
|
5262
|
-
if (this.meshesCreated && !force) return;
|
|
5263
|
-
const modelRoot = new Object3D3();
|
|
5264
|
-
const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
|
|
5265
|
-
if (transform) {
|
|
5266
|
-
for (const op of transform) {
|
|
5267
|
-
const matrix = new Matrix45();
|
|
5268
|
-
if ("scale" in op) matrix.makeScale(...op.scale);
|
|
5269
|
-
else if ("translate" in op) matrix.makeTranslation(...op.translate);
|
|
5270
|
-
else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
|
|
5271
|
-
modelRoot.matrix.multiply(matrix);
|
|
5272
|
-
}
|
|
5273
|
-
modelRoot.matrixAutoUpdate = false;
|
|
5274
|
-
} else if (this.options.flip ?? true) {
|
|
5275
|
-
modelRoot.scale.set(-1, -1, 1);
|
|
5276
|
-
}
|
|
5277
|
-
this.add(modelRoot);
|
|
5278
|
-
Object.entries(this.entityLayers).forEach(([name, layer], index) => {
|
|
5279
|
-
const group = this.createGroup(`layer:${name}`);
|
|
5280
|
-
modelRoot.add(group);
|
|
5281
|
-
const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
|
|
5282
|
-
this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
|
|
5283
|
-
});
|
|
5284
|
-
this.meshesCreated = true;
|
|
5285
|
-
}
|
|
5286
|
-
createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
|
|
5287
|
-
const anchor = this.createGroup(name);
|
|
5288
|
-
anchor.position.fromArray(part.pose.offset);
|
|
5289
|
-
anchor.rotation.set(...part.pose.rotation, "ZYX");
|
|
5290
|
-
anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
|
|
5291
|
-
parent.add(anchor);
|
|
5292
|
-
const size = part.texture ?? textureSize;
|
|
5293
|
-
for (const cube of part.cubes) {
|
|
5294
|
-
const [width, height, depth] = cube.size;
|
|
5295
|
-
const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];
|
|
5296
|
-
const texture = new MinecraftCubeTexture(...cube.uv, ...size);
|
|
5297
|
-
const uv = size[0] === 0 || size[1] === 0 ? new Array(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);
|
|
5298
|
-
const geometry = this._getBoxGeometryForDimensionsAndUv(
|
|
5299
|
-
width + growX * 2,
|
|
5300
|
-
height + growY * 2,
|
|
5301
|
-
depth + growZ * 2,
|
|
5302
|
-
uv
|
|
5303
|
-
).clone();
|
|
5304
|
-
this.geometries.add(geometry);
|
|
5305
|
-
geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
|
|
5306
|
-
if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
|
|
5307
|
-
const index = Array.from(geometry.getIndex().array);
|
|
5308
|
-
geometry.setIndex(index.concat(index.slice().reverse()));
|
|
5309
|
-
}
|
|
5310
|
-
const mesh = this.createMesh(name, geometry, material);
|
|
5311
|
-
mesh.renderOrder = renderOrder;
|
|
5312
|
-
anchor.add(mesh);
|
|
5313
|
-
if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));
|
|
5314
|
-
}
|
|
5315
|
-
for (const [childName, child] of Object.entries(part.children)) {
|
|
5316
|
-
this.createPart(childName, child, anchor, size, material, renderOrder, inward);
|
|
5317
|
-
}
|
|
5318
|
-
}
|
|
5319
|
-
async applyTextures() {
|
|
5320
|
-
this.clearScrollMaterials();
|
|
5321
|
-
await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
|
|
5322
|
-
const mode = layer.render ?? layer.layer.render ?? "cutout";
|
|
5323
|
-
const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
|
|
5324
|
-
const scroll = Materials.entityModeScroll(mode);
|
|
5325
|
-
const assetKeyStr = this.getTextureKey(layer).serialize();
|
|
5326
|
-
const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color3(tint).getHexString()}:${assetKeyStr}`;
|
|
5327
|
-
let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
|
|
5328
|
-
if (!mat) {
|
|
5329
|
-
const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
|
|
5330
|
-
const imageData = await this.loadTextures(layer);
|
|
5331
|
-
if (!imageData) return;
|
|
5332
|
-
const canvas = imageData.data.canvas;
|
|
5333
|
-
const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
|
|
5334
|
-
mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
|
|
5335
|
-
if (scroll) {
|
|
5336
|
-
this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
|
|
5337
|
-
}
|
|
5338
|
-
}
|
|
5339
|
-
this.getLayerGroup(name)?.traverse((object) => {
|
|
5340
|
-
if (isMesh(object)) object.material = mat;
|
|
5341
|
-
});
|
|
5342
|
-
}));
|
|
5343
|
-
if (!this.children.length) {
|
|
5344
|
-
this.clearScrollMaterials();
|
|
5345
|
-
} else if (this.scrollMaterials.length) {
|
|
5346
|
-
this.updateScroll();
|
|
5347
|
-
}
|
|
5348
|
-
this.updateScrollSubscription();
|
|
5349
|
-
this.notifyDirty();
|
|
5350
|
-
}
|
|
5351
|
-
};
|
|
5352
|
-
_EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
|
|
5353
|
-
var EntityObject = _EntityObject;
|
|
5354
|
-
function isEntityObject(obj) {
|
|
5355
|
-
return obj.isEntityObject;
|
|
5356
|
-
}
|
|
5589
|
+
// src/entity/scene/index.ts
|
|
5590
|
+
init_EntityAnimationPlayer();
|
|
5591
|
+
init_EntityObject();
|
|
5357
5592
|
|
|
5358
5593
|
// src/error/index.ts
|
|
5359
5594
|
init_MineRenderError();
|
|
@@ -7982,16 +8217,8 @@ init_SceneObject();
|
|
|
7982
8217
|
init_Materials();
|
|
7983
8218
|
init_ModelObject();
|
|
7984
8219
|
init_DisplayPosition();
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
// src/model/GuiLight.ts
|
|
7988
|
-
var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
|
|
7989
|
-
GuiLight2["FRONT"] = "front";
|
|
7990
|
-
GuiLight2["SIDE"] = "side";
|
|
7991
|
-
return GuiLight2;
|
|
7992
|
-
})(GuiLight || {});
|
|
7993
|
-
|
|
7994
|
-
// src/gui/scene/GuiObject.ts
|
|
8220
|
+
init_GuiLight();
|
|
8221
|
+
import { Box2, Box3 as Box32, Matrix4 as Matrix410, Mesh as Mesh7, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
|
|
7995
8222
|
var GuiObject = class extends SceneObject {
|
|
7996
8223
|
constructor(textureLayers, options) {
|
|
7997
8224
|
super({ ...options, instanceMeshes: false, mergeMeshes: false });
|
|
@@ -8014,13 +8241,13 @@ var GuiObject = class extends SceneObject {
|
|
|
8014
8241
|
const item = await this.createItem(layer, index);
|
|
8015
8242
|
item.position.set(x + width2 / 2, -y - height2 / 2, 0);
|
|
8016
8243
|
item.scale.set(width2 / 16, height2 / 16, width2 / 16);
|
|
8017
|
-
item.
|
|
8244
|
+
item.updateWorldMatrix(true, true);
|
|
8245
|
+
const inverse = this.matrixWorld.clone().invert();
|
|
8018
8246
|
const bounds = new Box32();
|
|
8019
8247
|
item.iterateAllMeshes((mesh2) => {
|
|
8020
8248
|
mesh2.geometry.computeBoundingBox();
|
|
8021
|
-
bounds.union(mesh2.geometry.boundingBox);
|
|
8249
|
+
bounds.union(mesh2.geometry.boundingBox.clone().applyMatrix4(new Matrix410().multiplyMatrices(inverse, mesh2.matrixWorld)));
|
|
8022
8250
|
});
|
|
8023
|
-
bounds.applyMatrix4(item.matrix);
|
|
8024
8251
|
item.position.z = depth - bounds.min.z;
|
|
8025
8252
|
depth += bounds.max.z - bounds.min.z + 0.01;
|
|
8026
8253
|
this.bounds.expandByPoint(new Vector23(x, y));
|
|
@@ -8075,7 +8302,7 @@ var GuiObject = class extends SceneObject {
|
|
|
8075
8302
|
this.add(item);
|
|
8076
8303
|
await item.init();
|
|
8077
8304
|
item.iterateAllMeshes((mesh) => {
|
|
8078
|
-
this.geometries.add(mesh.geometry);
|
|
8305
|
+
if (!model.special) this.geometries.add(mesh.geometry);
|
|
8079
8306
|
mesh.name = `mesh:${layer.name ?? index}`;
|
|
8080
8307
|
mesh.renderOrder = index;
|
|
8081
8308
|
for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
|
|
@@ -8533,26 +8760,12 @@ function isInstanceable(obj) {
|
|
|
8533
8760
|
// src/model/index.ts
|
|
8534
8761
|
init_DisplayPosition();
|
|
8535
8762
|
init_DisplayTransforms();
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
var ITEM_GENERATED = "item/generated";
|
|
8539
|
-
var BUILTIN_GENERATED = "builtin/generated";
|
|
8540
|
-
var BUILTIN_ENTITY = "builtin/entity";
|
|
8541
|
-
var DEFAULT_ELEMENTS = [];
|
|
8542
|
-
function isDoubleArray(obj) {
|
|
8543
|
-
return Array.isArray(obj) && obj.length === 2;
|
|
8544
|
-
}
|
|
8545
|
-
function isTripleArray(obj) {
|
|
8546
|
-
return Array.isArray(obj) && obj.length === 3;
|
|
8547
|
-
}
|
|
8548
|
-
function isQuadArray(obj) {
|
|
8549
|
-
return Array.isArray(obj) && obj.length === 4;
|
|
8550
|
-
}
|
|
8551
|
-
|
|
8552
|
-
// src/model/index.ts
|
|
8763
|
+
init_GuiLight();
|
|
8764
|
+
init_Model();
|
|
8553
8765
|
init_ModelCulling();
|
|
8554
8766
|
init_ModelGenerator();
|
|
8555
8767
|
init_ModelMerger();
|
|
8768
|
+
init_SpecialItems();
|
|
8556
8769
|
|
|
8557
8770
|
// src/model/block/BlockStateResolver.ts
|
|
8558
8771
|
init_BlockStates();
|
|
@@ -8743,9 +8956,10 @@ var import_ts_deepmerge6 = __toESM(require_dist());
|
|
|
8743
8956
|
init_MineRenderError();
|
|
8744
8957
|
init_InstanceReference();
|
|
8745
8958
|
init_AssetKey();
|
|
8746
|
-
import { Euler as Euler8, Matrix4 as
|
|
8959
|
+
import { Euler as Euler8, Matrix4 as Matrix411, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
|
|
8747
8960
|
init_ModelCulling();
|
|
8748
8961
|
init_FluidGeometry();
|
|
8962
|
+
init_Entities();
|
|
8749
8963
|
var _BlockObject = class _BlockObject extends SceneObject {
|
|
8750
8964
|
constructor(blockState, options) {
|
|
8751
8965
|
super(options);
|
|
@@ -8761,7 +8975,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8761
8975
|
this._models = [];
|
|
8762
8976
|
this._cullMask = 0;
|
|
8763
8977
|
this._entities = [];
|
|
8764
|
-
this._entityPlacement = new
|
|
8978
|
+
this._entityPlacement = new Matrix411();
|
|
8765
8979
|
this._entityGeneration = 0;
|
|
8766
8980
|
this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
|
|
8767
8981
|
}
|
|
@@ -8841,7 +9055,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8841
9055
|
return true;
|
|
8842
9056
|
}
|
|
8843
9057
|
placeEntities() {
|
|
8844
|
-
const matrix = new
|
|
9058
|
+
const matrix = new Matrix411().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
|
|
8845
9059
|
for (const entity of this._entities) {
|
|
8846
9060
|
matrix.decompose(entity.position, entity.quaternion, entity.scale);
|
|
8847
9061
|
}
|
|
@@ -8927,7 +9141,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
8927
9141
|
() => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
|
|
8928
9142
|
);
|
|
8929
9143
|
const previous = this._fluidModel;
|
|
8930
|
-
const matrix = previous ? this.getModelMatrix(previous) : new
|
|
9144
|
+
const matrix = previous ? this.getModelMatrix(previous) : new Matrix411().makeTranslation(...this.position.toArray());
|
|
8931
9145
|
if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
|
|
8932
9146
|
else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
|
|
8933
9147
|
this._models = this._models.filter((model) => model !== previous);
|
|
@@ -9065,7 +9279,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
9065
9279
|
setPositionRotationScaleAt(index, position, rotation, scale) {
|
|
9066
9280
|
super.setPositionRotationScaleAt(index, position, rotation, scale);
|
|
9067
9281
|
}
|
|
9068
|
-
getMatrixAt(index, matrix = new
|
|
9282
|
+
getMatrixAt(index, matrix = new Matrix411()) {
|
|
9069
9283
|
if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
|
|
9070
9284
|
const child = this._models[0];
|
|
9071
9285
|
if (child && isModelObject(child)) {
|
|
@@ -11672,7 +11886,7 @@ init_util();
|
|
|
11672
11886
|
init_Caching();
|
|
11673
11887
|
init_CacheKey();
|
|
11674
11888
|
init_MineRenderError();
|
|
11675
|
-
import { DataTexture as DataTexture2, DoubleSide as DoubleSide4, FrontSide as FrontSide2, MeshBasicMaterial as
|
|
11889
|
+
import { DataTexture as DataTexture2, DoubleSide as DoubleSide4, FrontSide as FrontSide2, MeshBasicMaterial as MeshBasicMaterial6, SRGBColorSpace as SRGBColorSpace5 } from "three";
|
|
11676
11890
|
|
|
11677
11891
|
// src/skin/SkinImage.ts
|
|
11678
11892
|
init_Caching();
|
|
@@ -11757,7 +11971,7 @@ var SkinTextures = class {
|
|
|
11757
11971
|
texture.colorSpace = SRGBColorSpace5;
|
|
11758
11972
|
texture.flipY = true;
|
|
11759
11973
|
texture.needsUpdate = true;
|
|
11760
|
-
return new
|
|
11974
|
+
return new MeshBasicMaterial6({ map: texture, transparent, side: transparent ? DoubleSide4 : FrontSide2, alphaTest: transparent ? 0.1 : 0 });
|
|
11761
11975
|
}
|
|
11762
11976
|
static isSlim(image, scale) {
|
|
11763
11977
|
for (const [x, y] of [[46, 52], [54, 20]]) {
|
|
@@ -11985,6 +12199,7 @@ var SkinObject = class extends SceneObject {
|
|
|
11985
12199
|
};
|
|
11986
12200
|
|
|
11987
12201
|
// src/renderer/MineRenderScene.ts
|
|
12202
|
+
init_EntityObject();
|
|
11988
12203
|
var _MineRenderScene = class _MineRenderScene extends Scene5 {
|
|
11989
12204
|
constructor(options) {
|
|
11990
12205
|
super();
|
|
@@ -12115,9 +12330,10 @@ function isMineRenderScene(obj) {
|
|
|
12115
12330
|
import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera as PerspectiveCamera2, SRGBColorSpace as SRGBColorSpace6, Vector3 as Vector313, WebGLRenderer as WebGLRenderer2 } from "three";
|
|
12116
12331
|
var import_ts_deepmerge9 = __toESM(require_dist());
|
|
12117
12332
|
init_util();
|
|
12333
|
+
init_Model();
|
|
12334
|
+
init_three();
|
|
12118
12335
|
import Stats from "stats.js";
|
|
12119
12336
|
import { EffectComposer, RenderPass } from "postprocessing";
|
|
12120
|
-
init_three();
|
|
12121
12337
|
|
|
12122
12338
|
// src/three/OrbitControls.js
|
|
12123
12339
|
import {
|
|
@@ -13620,6 +13836,7 @@ init_BlockStates();
|
|
|
13620
13836
|
init_AssetKey();
|
|
13621
13837
|
|
|
13622
13838
|
// src/world/MineRenderWorld.ts
|
|
13839
|
+
init_Model();
|
|
13623
13840
|
import { Vector3 as Vector315 } from "three";
|
|
13624
13841
|
init_BatchedExecutor();
|
|
13625
13842
|
init_AssetKey();
|
|
@@ -13630,7 +13847,7 @@ init_CubeFace();
|
|
|
13630
13847
|
init_AssetKey();
|
|
13631
13848
|
init_Models();
|
|
13632
13849
|
init_CubeFace();
|
|
13633
|
-
import { Matrix4 as
|
|
13850
|
+
import { Matrix4 as Matrix412, Vector3 as Vector314 } from "three";
|
|
13634
13851
|
init_ModelCulling();
|
|
13635
13852
|
init_ModelObject();
|
|
13636
13853
|
init_UVMapper();
|
|
@@ -13693,7 +13910,7 @@ var SectionModels = class {
|
|
|
13693
13910
|
});
|
|
13694
13911
|
await object.init();
|
|
13695
13912
|
const geometry = object.children[0].geometry;
|
|
13696
|
-
geometry.applyMatrix4(new
|
|
13913
|
+
geometry.applyMatrix4(new Matrix412().makeRotationFromEuler(rotation));
|
|
13697
13914
|
object.clear();
|
|
13698
13915
|
const cullFaces = CUBE_FACES.map((face) => {
|
|
13699
13916
|
const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
|
|
@@ -13940,6 +14157,9 @@ var MineRenderWorld = class {
|
|
|
13940
14157
|
}
|
|
13941
14158
|
};
|
|
13942
14159
|
|
|
14160
|
+
// src/world/Chunk.ts
|
|
14161
|
+
init_Model();
|
|
14162
|
+
|
|
13943
14163
|
// src/world/SectionMesh.ts
|
|
13944
14164
|
init_CanvasCompat();
|
|
13945
14165
|
init_Materials();
|
|
@@ -14288,6 +14508,7 @@ export {
|
|
|
14288
14508
|
SkinPart,
|
|
14289
14509
|
SkinTextures,
|
|
14290
14510
|
Skins,
|
|
14511
|
+
SpecialItems,
|
|
14291
14512
|
StructureParser,
|
|
14292
14513
|
TextureAtlas,
|
|
14293
14514
|
TextureLoader,
|