@adatechnology/game-items-three 0.5.0 → 0.6.0

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/index.js CHANGED
@@ -562,6 +562,12 @@ var destruction_default = {
562
562
  liquid: "honey",
563
563
  fill: 0.9
564
564
  }
565
+ },
566
+ shapes: {
567
+ box: {
568
+ hollow: true,
569
+ welded: true
570
+ }
565
571
  }
566
572
  };
567
573
 
@@ -577,6 +583,8 @@ var DESTRUCTION_MATERIAL_BY_TAG = {
577
583
  };
578
584
  var FAMILIES = destruction_default.families;
579
585
  var CONTENTS = destruction_default.contents;
586
+ var SHAPES2 = destruction_default.shapes;
587
+ var shapeDestruction = (shapeId) => SHAPES2[shapeId];
580
588
  var FAMILY_OF_MODEL = new Map(Object.entries(FAMILIES).flatMap(([family, entry]) => entry.models.map((model) => [model, family])));
581
589
  var itemFamily = (modelId) => FAMILY_OF_MODEL.get(modelId);
582
590
  var itemDestruction = (modelId) => {
@@ -692,9 +700,9 @@ function tessellateShapes(root, rule, T) {
692
700
  root.userData.tessellationTriangles = added;
693
701
  }
694
702
  function tagForDestruction(root, options = {}) {
695
- const { modelId, weight, size, three } = options;
703
+ const { modelId, shapeId, weight, size, powder, three } = options;
696
704
  if (weight !== void 0 && weight > 0) root.userData.destructionMass = weight;
697
- const rule = modelId === void 0 ? void 0 : itemDestruction(modelId);
705
+ const rule = modelId !== void 0 ? itemDestruction(modelId) : shapeId !== void 0 ? shapeDestruction(shapeId) : void 0;
698
706
  if (rule?.tessellate) tessellateShapes(root, rule.tessellate, three);
699
707
  const solid = [];
700
708
  root.traverse((object) => {
@@ -709,6 +717,7 @@ function tagForDestruction(root, options = {}) {
709
717
  return;
710
718
  }
711
719
  if (rule?.hollow) mesh.userData.hollow = true;
720
+ if (powder) mesh.userData.destructionPowder = { color: powder.color };
712
721
  solid.push(mesh);
713
722
  });
714
723
  if (!rule?.welded || solid.length < 2) return;
@@ -3191,8 +3200,168 @@ var cannedBeans = ({ mesh, cyl, torus, G, metal, paper: paper2, food }) => {
3191
3200
  return G(mesh(cyl(0.32, 0.32, 0.52), m), mesh(cyl(0.326, 0.326, 0.34, 14), food(10172964)), mesh(cyl(0.33, 0.33, 0.06), paper2(14861162), [0, 0.02, 0]), mesh(torus(0.31, 0.025), m, [0, 0.26, 0], [Math.PI / 2, 0, 0]), mesh(torus(0.31, 0.025), m, [0, -0.26, 0], [Math.PI / 2, 0, 0]));
3192
3201
  };
3193
3202
 
3203
+ // src/data/opening.json
3204
+ var opening_default = {
3205
+ families: {
3206
+ drink_can: { style: "pull_tab" },
3207
+ food_tin: { style: "cut_lid" }
3208
+ },
3209
+ models: {
3210
+ empty_can: { style: "none" },
3211
+ canned_beans: { food: "#7a2e1c" },
3212
+ canned_corn_and_peas: { food: "#c7b03c" },
3213
+ canned_sausages: { food: "#c98d5c" },
3214
+ canned_sardines: { style: "peel_lid", food: "#8e979c" },
3215
+ condensed_milk: { food: "#e3cf9c" },
3216
+ energy_drink: { style: "pull_tab" },
3217
+ honey_jar: { style: "screw_cap", food: "#d99a1c" },
3218
+ home_preserves: { style: "screw_cap", food: "#8e1f3a" },
3219
+ cooking_oil: { style: "screw_cap", food: "#e3b830" },
3220
+ water_bottle: { style: "screw_cap" },
3221
+ water_jug_5l: { style: "screw_cap" },
3222
+ dirty_water: { style: "screw_cap" },
3223
+ sports_drink: { style: "screw_cap" },
3224
+ coconut_water: { style: "screw_cap" },
3225
+ cachaca: { style: "screw_cap" },
3226
+ communion_wine: { style: "screw_cap" }
3227
+ }
3228
+ };
3229
+
3230
+ // src/opening.ts
3231
+ var FAMILIES2 = opening_default.families;
3232
+ var MODELS = opening_default.models;
3233
+ var itemOpening = (modelId) => {
3234
+ const family = itemFamily(modelId);
3235
+ const row = { ...family === void 0 ? {} : FAMILIES2[family], ...MODELS[modelId] };
3236
+ if (row.style === void 0 || row.style === "none") return void 0;
3237
+ return { style: row.style, ...row.food === void 0 ? {} : { food: row.food } };
3238
+ };
3239
+ var OPENING_NAME = "opening";
3240
+ var INSIDE = 1315086;
3241
+ var CUT_EDGE = 14278114;
3242
+ var LID = 12172996;
3243
+ var isLid = (o) => o.userData.itemLid === true;
3244
+ var asLid = (mesh) => {
3245
+ mesh.userData.itemLid = true;
3246
+ return mesh;
3247
+ };
3248
+ var localBox = (T, root, only) => {
3249
+ root.updateMatrixWorld(true);
3250
+ const toRoot = new T.Matrix4().copy(root.matrixWorld).invert();
3251
+ const box2 = new T.Box3();
3252
+ const part = new T.Box3();
3253
+ const m = new T.Matrix4();
3254
+ root.traverse((o) => {
3255
+ const mesh = o;
3256
+ if (!mesh.isMesh || mesh.userData.destructionDebris || mesh.name === OPENING_NAME || mesh.parent?.name === OPENING_NAME) return;
3257
+ if (only && !only(mesh)) return;
3258
+ if (!mesh.geometry.boundingBox) mesh.geometry.computeBoundingBox();
3259
+ part.copy(mesh.geometry.boundingBox).applyMatrix4(m.multiplyMatrices(toRoot, mesh.matrixWorld));
3260
+ box2.union(part);
3261
+ });
3262
+ return box2;
3263
+ };
3264
+ function openItem(T, root, modelId) {
3265
+ const look = itemOpening(modelId);
3266
+ if (!look) return false;
3267
+ if (root.userData.itemOpened) return true;
3268
+ const box2 = look.style === "screw_cap" ? localBox(T, root, isLid) : localBox(T, root);
3269
+ if (box2.isEmpty()) return false;
3270
+ const size = box2.getSize(new T.Vector3());
3271
+ const centre = box2.getCenter(new T.Vector3());
3272
+ const top = look.style === "screw_cap" ? box2.min.y : box2.max.y;
3273
+ const lift = size.y * 3e-3;
3274
+ const sheet = Math.max(size.y * 6e-3, 1e-4);
3275
+ const group = new T.Group();
3276
+ group.name = OPENING_NAME;
3277
+ group.position.set(centre.x, top, centre.z);
3278
+ const material = (color, metal = 0) => new T.MeshStandardMaterial({ color, metalness: metal, roughness: metal ? 0.45 : 0.85, polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -2 });
3279
+ const add = (geometry, mat, y, parent = group) => {
3280
+ const mesh = new T.Mesh(geometry, mat);
3281
+ mesh.position.y = y;
3282
+ mesh.renderOrder = 2;
3283
+ mesh.userData.destructionDebris = true;
3284
+ mesh.userData.itemOpening = true;
3285
+ parent.add(mesh);
3286
+ return mesh;
3287
+ };
3288
+ const flat = (geometry) => geometry.rotateX(-Math.PI / 2);
3289
+ const food = look.food ?? INSIDE;
3290
+ if (look.style === "screw_cap") {
3291
+ const r = Math.min(size.x, size.z) / 2;
3292
+ root.traverse((o) => isLid(o) && (o.visible = false));
3293
+ add(flat(new T.CircleGeometry(r * 0.85, 24)), material(INSIDE), lift);
3294
+ if (look.food !== void 0) add(flat(new T.CircleGeometry(r * 0.7, 24)), material(look.food), lift * 2).userData.itemFood = true;
3295
+ } else if (look.style === "pull_tab") {
3296
+ const r = Math.min(size.x, size.z) / 2;
3297
+ const mouth = add(flat(new T.CircleGeometry(r * 0.2, 24)), material(INSIDE), lift);
3298
+ mouth.scale.set(1.15, 1, 0.85);
3299
+ mouth.position.z = r * 0.52;
3300
+ } else if (look.style === "cut_lid") {
3301
+ const r = Math.min(size.x, size.z) / 2;
3302
+ add(flat(new T.CircleGeometry(r * 0.88, 40)), material(INSIDE), lift);
3303
+ add(flat(new T.CircleGeometry(r * 0.76, 40)), material(food), lift * 2).userData.itemFood = true;
3304
+ add(flat(new T.RingGeometry(r * 0.86, r * 0.9, 40)), material(CUT_EDGE, 0.9), lift * 3);
3305
+ const hinge = new T.Group();
3306
+ hinge.position.set(0, lift, -r * 0.86);
3307
+ hinge.rotation.x = -1.95;
3308
+ group.add(hinge);
3309
+ const lid = add(new T.CylinderGeometry(r * 0.86, r * 0.86, sheet, 40), material(LID, 0.4), 0, hinge);
3310
+ lid.position.z = r * 0.86;
3311
+ } else {
3312
+ const long = size.x >= size.z ? "x" : "z";
3313
+ const length = Math.max(size.x, size.z);
3314
+ const width = Math.min(size.x, size.z);
3315
+ const plane = (a, b) => flat(long === "x" ? new T.PlaneGeometry(a, b) : new T.PlaneGeometry(b, a));
3316
+ add(plane(length * 0.92, width * 0.86), material(INSIDE), lift);
3317
+ add(plane(length * 0.84, width * 0.76), material(food), lift * 2).userData.itemFood = true;
3318
+ const hinge = new T.Group();
3319
+ const end = length * 0.46;
3320
+ if (long === "x") {
3321
+ hinge.position.set(end, lift, 0);
3322
+ hinge.rotation.z = -1.7;
3323
+ } else {
3324
+ hinge.position.set(0, lift, end);
3325
+ hinge.rotation.x = 1.7;
3326
+ }
3327
+ group.add(hinge);
3328
+ const lid = add(long === "x" ? new T.BoxGeometry(length * 0.9, sheet, width * 0.84) : new T.BoxGeometry(width * 0.84, sheet, length * 0.9), material(LID, 0.4), 0, hinge);
3329
+ if (long === "x") lid.position.x = -length * 0.45;
3330
+ else lid.position.z = -length * 0.45;
3331
+ }
3332
+ root.add(group);
3333
+ root.userData.itemOpened = true;
3334
+ return true;
3335
+ }
3336
+ var CAP_OFF = 1.6;
3337
+ function turnItem(root, modelId, state) {
3338
+ if (itemOpening(modelId)?.style !== "screw_cap") return false;
3339
+ root.traverse((o) => {
3340
+ var _a;
3341
+ if (!isLid(o)) return;
3342
+ const mesh = o;
3343
+ const base = (_a = mesh.userData).lidBase ?? (_a.lidBase = { y: mesh.position.y, turn: mesh.rotation.y });
3344
+ if (!mesh.geometry.boundingBox) mesh.geometry.computeBoundingBox();
3345
+ const height = (mesh.geometry.boundingBox.max.y - mesh.geometry.boundingBox.min.y) * mesh.scale.y;
3346
+ mesh.rotation.y = base.turn + state.turned;
3347
+ mesh.position.y = base.y + Math.min(1, Math.max(0, state.lift)) * height * CAP_OFF;
3348
+ });
3349
+ return true;
3350
+ }
3351
+ function setOpeningContents(root, share) {
3352
+ const opening = root.getObjectByName(OPENING_NAME);
3353
+ if (!opening) return;
3354
+ const left = Math.max(0, Math.min(1, share));
3355
+ opening.traverse((o) => {
3356
+ if (!o.userData.itemFood) return;
3357
+ o.visible = left > 0.02;
3358
+ const k = 0.35 + 0.65 * left;
3359
+ o.scale.set(k, 1, k);
3360
+ });
3361
+ }
3362
+
3194
3363
  // src/models/water-bottle.ts
3195
- var waterBottle = ({ mesh, cyl, lathe, G, plastic, paper: paper2, glass }) => G(mesh(lathe([[0, -0.6], [0.2, -0.6], [0.22, -0.5], [0.22, 0.2], [0.19, 0.32], [0.09, 0.45], [0.08, 0.55], [0, 0.55]]), glass(9421788, 0.55)), mesh(cyl(0.085, 0.085, 0.1, 12), plastic(2907530), [0, 0.6, 0]), mesh(cyl(0.225, 0.225, 0.22, 16), paper2(15330543), [0, -0.15, 0]), mesh(cyl(0.226, 0.226, 0.05, 16), plastic(3831976), [0, -0.12, 0]));
3364
+ var waterBottle = ({ mesh, cyl, lathe, G, plastic, paper: paper2, glass }) => G(mesh(lathe([[0, -0.6], [0.2, -0.6], [0.22, -0.5], [0.22, 0.2], [0.19, 0.32], [0.09, 0.45], [0.08, 0.55], [0, 0.55]]), glass(9421788, 0.55)), asLid(mesh(cyl(0.085, 0.085, 0.1, 12), plastic(2907530), [0, 0.6, 0])), mesh(cyl(0.225, 0.225, 0.22, 16), paper2(15330543), [0, -0.15, 0]), mesh(cyl(0.226, 0.226, 0.05, 16), plastic(3831976), [0, -0.12, 0]));
3196
3365
 
3197
3366
  // src/models/rice.ts
3198
3367
  var rice = ({ mesh, bx, G, paper: paper2, food }) => G(mesh(bx(0.7, 0.95, 0.28), paper2(15129792)), mesh(bx(0.72, 0.12, 0.1), paper2(14010792), [0, 0.52, 0]), mesh(bx(0.5, 0.3, 0.02), food(11883039), [0, 0.05, 0.15]), mesh(bx(0.3, 0.1, 0.02), paper2(4160069), [0, -0.25, 0.15]));
@@ -3201,7 +3370,7 @@ var rice = ({ mesh, bx, G, paper: paper2, food }) => G(mesh(bx(0.7, 0.95, 0.28),
3201
3370
  var militaryRation = ({ mesh, bx, G, plastic, paper: paper2 }) => G(mesh(bx(0.75, 1, 0.22), plastic(5923142)), mesh(bx(0.77, 0.1, 0.23), plastic(4672823), [0, 0.48, 0]), mesh(bx(0.5, 0.14, 0.01), paper2(2237727), [0, 0.18, 0.115]), mesh(bx(0.36, 0.06, 0.01), paper2(2237727), [0, -0.02, 0.115]));
3202
3371
 
3203
3372
  // src/models/cachaca.ts
3204
- var cachaca = ({ mesh, cyl, lathe, G, wood, paper: paper2, food, glass }) => G(mesh(lathe([[0, -0.6], [0.25, -0.6], [0.27, -0.52], [0.27, 0.1], [0.2, 0.25], [0.09, 0.35], [0.09, 0.58], [0, 0.58]]), glass(12749354, 0.78)), mesh(cyl(0.08, 0.07, 0.14, 10), wood(9071172), [0, 0.64, 0]), mesh(cyl(0.275, 0.275, 0.34, 16), paper2(15327692), [0, -0.25, 0]), mesh(cyl(0.276, 0.276, 0.06, 16), food(8007455), [0, -0.15, 0]));
3373
+ var cachaca = ({ mesh, cyl, lathe, G, wood, paper: paper2, food, glass }) => G(mesh(lathe([[0, -0.6], [0.25, -0.6], [0.27, -0.52], [0.27, 0.1], [0.2, 0.25], [0.09, 0.35], [0.09, 0.58], [0, 0.58]]), glass(12749354, 0.78)), asLid(mesh(cyl(0.08, 0.07, 0.14, 10), wood(9071172), [0, 0.64, 0])), mesh(cyl(0.275, 0.275, 0.34, 16), paper2(15327692), [0, -0.25, 0]), mesh(cyl(0.276, 0.276, 0.06, 16), food(8007455), [0, -0.15, 0]));
3205
3374
 
3206
3375
  // src/models/first-aid-kit.ts
3207
3376
  var firstAidKit = ({ mesh, bx, torus, G, plastic }) => {
@@ -3417,7 +3586,7 @@ var homePreserves = ({ mesh, cyl, G, glass, metal, paper: paper2, food, cloth: c
3417
3586
  mesh(cyl(0.41, 0.41, 0.86, 12), food(9314106), [0, -0.2, 0]),
3418
3587
  mesh(cyl(0.34, 0.445, 0.12, 12), glass(13625070, 0.5), [0, 0.39, 0]),
3419
3588
  mesh(cyl(0.34, 0.34, 0.05, 12), glass(13625070, 0.5), [0, 0.475, 0]),
3420
- mesh(cyl(0.38, 0.38, 0.15, 12), metal(12163644), [0, 0.575, 0]),
3589
+ asLid(mesh(cyl(0.38, 0.38, 0.15, 12), metal(12163644), [0, 0.575, 0])),
3421
3590
  mesh(cyl(0.45, 0.45, 0.4, 12), paper2(15327172), [0, -0.2, 0]),
3422
3591
  mesh(cyl(0.452, 0.452, 0.08, 12), cloth2(10172986), [0, -0.2, 0])
3423
3592
  );
@@ -3622,7 +3791,7 @@ var honeyJar = ({ mesh, cyl, G, glass, metal, paper: paper2, food }) => G(
3622
3791
  mesh(cyl(0.395, 0.395, 0.68, 12), glass(14925936, 0.55), [0, -0.16, 0]),
3623
3792
  mesh(cyl(0.37, 0.37, 0.6, 12), food(14260764), [0, -0.2, 0]),
3624
3793
  mesh(cyl(0.3, 0.395, 0.14, 12), glass(14925936, 0.55), [0, 0.25, 0]),
3625
- mesh(cyl(0.3, 0.3, 0.18, 12), metal(7031324), [0, 0.41, 0]),
3794
+ asLid(mesh(cyl(0.3, 0.3, 0.18, 12), metal(7031324), [0, 0.41, 0])),
3626
3795
  mesh(cyl(0.4, 0.4, 0.34, 12), paper2(15853512), [0, -0.2, 0]),
3627
3796
  mesh(cyl(0.402, 0.402, 0.05, 12), paper2(9067028), [0, -0.1, 0]),
3628
3797
  mesh(cyl(0.402, 0.402, 0.05, 12), paper2(9067028), [0, -0.3, 0])
@@ -3726,7 +3895,7 @@ var cookingOil = ({ mesh, cyl, G, glass, plastic, paper: paper2 }) => G(
3726
3895
  mesh(cyl(0.345, 0.345, 1.7, 12), glass(14923824, 0.65), [0, -0.45, 0]),
3727
3896
  mesh(cyl(0.12, 0.345, 0.5, 12), glass(14923824, 0.65), [0, 0.65, 0]),
3728
3897
  mesh(cyl(0.12, 0.12, 0.25, 12), glass(14923824, 0.65), [0, 1.025, 0]),
3729
- mesh(cyl(0.14, 0.14, 0.15, 12), plastic(4160042), [0, 1.225, 0]),
3898
+ asLid(mesh(cyl(0.14, 0.14, 0.15, 12), plastic(4160042), [0, 1.225, 0])),
3730
3899
  mesh(cyl(0.35, 0.35, 0.8, 12), paper2(15853512), [0, -0.5, 0]),
3731
3900
  mesh(cyl(0.352, 0.352, 0.2, 12), paper2(4160042), [0, -0.5, 0])
3732
3901
  );
@@ -3764,7 +3933,7 @@ var waterJug5l = ({ mesh, bx, cyl, G, plastic, paper: paper2, glass }) => {
3764
3933
  const body = mesh(bx(1.5, 2.3, 1.5), glass(10473710, 0.75), [0, -0.5, 0]);
3765
3934
  const shoulder = mesh(bx(1.2, 0.45, 1.2), glass(10473710, 0.75), [0, 0.875, 0]);
3766
3935
  const neck = mesh(cyl(0.34, 0.34, 0.3, 12), dark, [0, 1.25, 0]);
3767
- const cap = mesh(cyl(0.4, 0.4, 0.25, 12), dark, [0, 1.525, 0]);
3936
+ const cap = asLid(mesh(cyl(0.4, 0.4, 0.25, 12), dark, [0, 1.525, 0]));
3768
3937
  const grip = mesh(bx(0.16, 0.9, 0.3), dark, [1.07, 0.6, 0]);
3769
3938
  const upperBar = mesh(bx(0.45, 0.16, 0.3), dark, [0.925, 0.97, 0]);
3770
3939
  const lowerBar = mesh(bx(0.45, 0.16, 0.3), dark, [0.925, 0.23, 0]);
@@ -3779,7 +3948,7 @@ var sportsDrink = ({ mesh, cyl, lathe, G, plastic, paper: paper2 }) => {
3779
3948
  const label = mesh(cyl(0.332, 0.332, 0.7, 12), paper2(1448738), [0, -0.12, 0]);
3780
3949
  const stripe = mesh(cyl(0.332, 0.332, 0.1, 12), paper2(15753232), [0, 0.28, 0]);
3781
3950
  const collar = mesh(cyl(0.2, 0.2, 0.04, 12), plastic(15263976), [0, 0.705, 0]);
3782
- const cap = mesh(cyl(0.19, 0.19, 0.2, 12), plastic(15753232), [0, 0.815, 0]);
3951
+ const cap = asLid(mesh(cyl(0.19, 0.19, 0.2, 12), plastic(15753232), [0, 0.815, 0]));
3783
3952
  return G(bottle2, label, stripe, collar, cap);
3784
3953
  };
3785
3954
 
@@ -3826,7 +3995,7 @@ var communionWine = ({ mesh, bx, cyl, lathe, G, glass, paper: paper2, metal }) =
3826
3995
  const goldBand = mesh(cyl(0.382, 0.382, 0.05, 12), metal(11896880), [0, 0.075, 0]);
3827
3996
  const crossUpright = mesh(bx(0.06, 0.26, 0.02), paper2(8003371), [0, -0.35, 0.375]);
3828
3997
  const crossArm = mesh(bx(0.18, 0.06, 0.02), paper2(8003371), [0, -0.3, 0.375]);
3829
- const foil = mesh(cyl(0.15, 0.15, 0.46, 12), metal(11896880), [0, 1.27, 0]);
3998
+ const foil = asLid(mesh(cyl(0.15, 0.15, 0.46, 12), metal(11896880), [0, 1.27, 0]));
3830
3999
  return G(bottle2, label, goldBand, crossUpright, crossArm, foil);
3831
4000
  };
3832
4001
 
@@ -3837,7 +4006,7 @@ var coconutWater = ({ mesh, bx, cyl, lathe, G, plastic, paper: paper2 }) => {
3837
4006
  const nut = mesh(cyl(0.11, 0.11, 0.03, 10), paper2(7031339), [0, -0.12, 0.285], [Math.PI / 2, 0, 0]);
3838
4007
  const leafLeft = mesh(bx(0.2, 0.05, 0.01), paper2(15135448), [-0.12, 0.08, 0.292], [0, 0, 0.5]);
3839
4008
  const leafRight = mesh(bx(0.2, 0.05, 0.01), paper2(15135448), [0.12, 0.08, 0.292], [0, 0, -0.5]);
3840
- const cap = mesh(cyl(0.14, 0.14, 0.2, 12), plastic(4165450), [0, 0.75, 0]);
4009
+ const cap = asLid(mesh(cyl(0.14, 0.14, 0.2, 12), plastic(4165450), [0, 0.75, 0]));
3841
4010
  return G(bottle2, label, nut, leafLeft, leafRight, cap);
3842
4011
  };
3843
4012
 
@@ -3847,7 +4016,7 @@ var dirtyWater = ({ mesh, cyl, lathe, G, plastic, paper: paper2, glass, food })
3847
4016
  const murk = mesh(lathe([[0, -0.89], [0.27, -0.89], [0.315, -0.84], [0.315, 0.1], [0, 0.1]], 12), food(7035444));
3848
4017
  const sediment = mesh(cyl(0.31, 0.27, 0.12, 8), food(4865314), [0, -0.82, 0]);
3849
4018
  const label = mesh(cyl(0.332, 0.332, 0.22, 12), paper2(13617588), [0, 0.38, 0]);
3850
- const cap = mesh(cyl(0.19, 0.19, 0.2, 8), plastic(5922920), [0, 0.815, 0]);
4019
+ const cap = asLid(mesh(cyl(0.19, 0.19, 0.2, 8), plastic(5922920), [0, 0.815, 0]));
3851
4020
  return G(bottle2, murk, sediment, label, cap);
3852
4021
  };
3853
4022
 
@@ -6836,7 +7005,7 @@ function buildItem(T, item, options = {}) {
6836
7005
  const materials = kit.materials.slice(first);
6837
7006
  if (options.wear) setWear(materials, options.wear);
6838
7007
  root.userData.wear = options.wear ?? 0;
6839
- if (options.destructible) tagForDestruction(root, { ...kind === "model" && item.model !== void 0 ? { modelId: item.model } : {}, ...item.weight === void 0 ? {} : { weight: item.weight }, size: item.size, three: T });
7008
+ if (options.destructible) tagForDestruction(root, { ...kind === "model" && item.model !== void 0 ? { modelId: item.model } : {}, ...shape === void 0 ? {} : { shapeId: shape }, ...item.weight === void 0 ? {} : { weight: item.weight }, size: item.size, ...item.powder ? { powder: item.powder } : {}, three: T });
6840
7009
  markKitOrigin(root, { owner: "game-items-three", kind: "item", id: item.id, ...kind === "shape" ? { standIn: true } : {} });
6841
7010
  return { root, kind, ...shape ? { shape } : {}, size: item.size, materials };
6842
7011
  }
@@ -7219,7 +7388,15 @@ function createItemsTestModule(options) {
7219
7388
  const provider = options.provider ?? createFindsProvider(catalog);
7220
7389
  const items = catalog.list();
7221
7390
  const categories = [...ITEM_CATEGORIES.map((c) => c.id), ...[...catalog.categories.keys()].filter((id) => !ITEM_CATEGORIES.some((c) => c.id === id))].filter((id) => items.some((item) => item.category === id));
7222
- const shelves = shelvesLayout(items, categories);
7391
+ const openerOf = (item) => {
7392
+ const id = item.seal?.openWith?.find((tool2) => catalog.has(tool2));
7393
+ return id === void 0 ? void 0 : catalog.get(id);
7394
+ };
7395
+ const laid = items.flatMap((item) => {
7396
+ const opener = openerOf(item);
7397
+ return opener ? [item, { id: opener.id, category: item.category, size: opener.size }] : [item];
7398
+ });
7399
+ const shelves = shelvesLayout(laid, categories);
7223
7400
  const showcase = listItemModels().map((id) => ({ id, size: sizeOfModel(id), def: catalog.has(id) ? catalog.get(id) : void 0 }));
7224
7401
  const state = {
7225
7402
  category: CATEGORY_ALL,
@@ -7270,12 +7447,27 @@ function createItemsTestModule(options) {
7270
7447
  const contents = itemContents(subject);
7271
7448
  return contents ? { fluid: { container: contents.container, part: SHELL_PART_ID } } : {};
7272
7449
  };
7450
+ const sealOf = (def, fluid) => {
7451
+ const model = def.model;
7452
+ if (!def.seal || model === void 0 || !itemOpening(model)) return fluid;
7453
+ const openWith = def.seal.openWith ? [...def.seal.openWith, ...def.seal.openWith.map((id) => `${ITEM_PREFIX}${id}`)] : void 0;
7454
+ const seal = {
7455
+ ...def.seal,
7456
+ ...openWith ? { openWith } : {},
7457
+ open: (root) => void (latestTHREE && openItem(latestTHREE, root, model)),
7458
+ contents: (root, share) => setOpeningContents(root, share),
7459
+ // a screw cap is turned off by the other hand before the first bite or sip
7460
+ ...itemOpening(model)?.style === "screw_cap" ? { openUse: "unscrew", turn: (root, state2) => void turnItem(root, model, state2) } : {}
7461
+ };
7462
+ const eaten = def.category === "food" && fluid.fluid ? { fluid: { ...fluid.fluid, uses: ["eat", "pour_out"] } } : fluid;
7463
+ return { ...eaten, seal };
7464
+ };
7273
7465
  const itemOf = (def) => ({
7274
7466
  id: `${ITEM_PREFIX}${def.id}`,
7275
7467
  name: nameOf(def),
7276
7468
  movable: true,
7277
7469
  thumbnail: itemThumbnailSvg(drawable(def)),
7278
- ...fluidOf({ ...def.model === void 0 ? {} : { model: def.model }, size: def.size, weight: def.weight }),
7470
+ ...sealOf(def, fluidOf({ ...def.model === void 0 ? {} : { model: def.model }, size: def.size, weight: def.weight })),
7279
7471
  build: (THREE) => {
7280
7472
  const T = THREE;
7281
7473
  latestTHREE = T;
@@ -7639,7 +7831,7 @@ function createItemsTestModule(options) {
7639
7831
  id: "modeled",
7640
7832
  name: text.metrics.modeled,
7641
7833
  read: () => {
7642
- const shown = visibleEntries().filter((entry) => entry.group === "shelf");
7834
+ const shown = [...new Map(visibleEntries().filter((entry) => entry.group === "shelf").map((entry) => [entry.itemId, entry])).values()];
7643
7835
  return `${shown.filter((entry) => entry.kind === "model").length}/${shown.length}`;
7644
7836
  }
7645
7837
  },
@@ -7766,6 +7958,7 @@ export {
7766
7958
  ITEM_FAMILIES,
7767
7959
  ITEM_PREFIX,
7768
7960
  MODEL_BUDGET_DEVIATIONS,
7961
+ OPENING_NAME,
7769
7962
  ROW_LIMIT,
7770
7963
  RULER_HEIGHT,
7771
7964
  RULER_ID,
@@ -7779,6 +7972,7 @@ export {
7779
7972
  WEAR_AMOUNT,
7780
7973
  WEAR_TAGS,
7781
7974
  WEAR_TARGET,
7975
+ asLid,
7782
7976
  buildItem,
7783
7977
  buildItemLod,
7784
7978
  canonicalFrame,
@@ -7797,14 +7991,18 @@ export {
7797
7991
  itemFamily,
7798
7992
  itemModelBuilder,
7799
7993
  itemModelEntry,
7994
+ itemOpening,
7800
7995
  itemThumbnail,
7801
7996
  itemThumbnailSvg,
7802
7997
  listItemModels,
7803
7998
  mergeItem,
7999
+ openItem,
7804
8000
  registerItemModel,
7805
8001
  renderItemThumbnail,
8002
+ setOpeningContents,
7806
8003
  setWear,
7807
8004
  shade,
8005
+ shapeDestruction,
7808
8006
  shapeOf,
7809
8007
  shapeThumbnailSvg,
7810
8008
  shelvesLayout,
@@ -7812,6 +8010,7 @@ export {
7812
8010
  tagForDestruction,
7813
8011
  thumbnailPatch,
7814
8012
  triangleBudgetOf,
8013
+ turnItem,
7815
8014
  unregisterItemModel,
7816
8015
  wearableMaterials
7817
8016
  };