@adatechnology/game-items-three 0.5.0 → 0.6.1

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
  }
@@ -7002,6 +7171,7 @@ function renderItemThumbnail(T, renderer, item, options = {}) {
7002
7171
  }
7003
7172
 
7004
7173
  // src/area.ts
7174
+ import { discardObject3D } from "@adatechnology/game-shapes-three";
7005
7175
  import { markKitOrigin as markKitOrigin2 } from "@adatechnology/game-contracts";
7006
7176
  import { furnitureSpec } from "@adatechnology/game-floorplan-three";
7007
7177
  import { rng } from "@adatechnology/game-interactables";
@@ -7219,7 +7389,15 @@ function createItemsTestModule(options) {
7219
7389
  const provider = options.provider ?? createFindsProvider(catalog);
7220
7390
  const items = catalog.list();
7221
7391
  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);
7392
+ const openerOf = (item) => {
7393
+ const id = item.seal?.openWith?.find((tool2) => catalog.has(tool2));
7394
+ return id === void 0 ? void 0 : catalog.get(id);
7395
+ };
7396
+ const laid = items.flatMap((item) => {
7397
+ const opener = openerOf(item);
7398
+ return opener ? [item, { id: opener.id, category: item.category, size: opener.size }] : [item];
7399
+ });
7400
+ const shelves = shelvesLayout(laid, categories);
7223
7401
  const showcase = listItemModels().map((id) => ({ id, size: sizeOfModel(id), def: catalog.has(id) ? catalog.get(id) : void 0 }));
7224
7402
  const state = {
7225
7403
  category: CATEGORY_ALL,
@@ -7270,12 +7448,27 @@ function createItemsTestModule(options) {
7270
7448
  const contents = itemContents(subject);
7271
7449
  return contents ? { fluid: { container: contents.container, part: SHELL_PART_ID } } : {};
7272
7450
  };
7451
+ const sealOf = (def, fluid) => {
7452
+ const model = def.model;
7453
+ if (!def.seal || model === void 0 || !itemOpening(model)) return fluid;
7454
+ const openWith = def.seal.openWith ? [...def.seal.openWith, ...def.seal.openWith.map((id) => `${ITEM_PREFIX}${id}`)] : void 0;
7455
+ const seal = {
7456
+ ...def.seal,
7457
+ ...openWith ? { openWith } : {},
7458
+ open: (root) => void (latestTHREE && openItem(latestTHREE, root, model)),
7459
+ contents: (root, share) => setOpeningContents(root, share),
7460
+ // a screw cap is turned off by the other hand before the first bite or sip
7461
+ ...itemOpening(model)?.style === "screw_cap" ? { openUse: "unscrew", turn: (root, state2) => void turnItem(root, model, state2) } : {}
7462
+ };
7463
+ const eaten = def.category === "food" && fluid.fluid ? { fluid: { ...fluid.fluid, uses: ["eat", "pour_out"] } } : fluid;
7464
+ return { ...eaten, seal };
7465
+ };
7273
7466
  const itemOf = (def) => ({
7274
7467
  id: `${ITEM_PREFIX}${def.id}`,
7275
7468
  name: nameOf(def),
7276
7469
  movable: true,
7277
7470
  thumbnail: itemThumbnailSvg(drawable(def)),
7278
- ...fluidOf({ ...def.model === void 0 ? {} : { model: def.model }, size: def.size, weight: def.weight }),
7471
+ ...sealOf(def, fluidOf({ ...def.model === void 0 ? {} : { model: def.model }, size: def.size, weight: def.weight })),
7279
7472
  build: (THREE) => {
7280
7473
  const T = THREE;
7281
7474
  latestTHREE = T;
@@ -7372,9 +7565,7 @@ function createItemsTestModule(options) {
7372
7565
  }
7373
7566
  };
7374
7567
  const clearBoxes = () => {
7375
- for (const box2 of boxes) {
7376
- box2.parent?.remove(box2);
7377
- }
7568
+ discardObject3D(boxes);
7378
7569
  boxes = [];
7379
7570
  };
7380
7571
  const applyBoxes = () => {
@@ -7393,7 +7584,7 @@ function createItemsTestModule(options) {
7393
7584
  };
7394
7585
  const clearFinds = () => {
7395
7586
  if (findsGroup) {
7396
- findsGroup.parent?.remove(findsGroup);
7587
+ discardObject3D(findsGroup);
7397
7588
  findsGroup = null;
7398
7589
  }
7399
7590
  };
@@ -7639,7 +7830,7 @@ function createItemsTestModule(options) {
7639
7830
  id: "modeled",
7640
7831
  name: text.metrics.modeled,
7641
7832
  read: () => {
7642
- const shown = visibleEntries().filter((entry) => entry.group === "shelf");
7833
+ const shown = [...new Map(visibleEntries().filter((entry) => entry.group === "shelf").map((entry) => [entry.itemId, entry])).values()];
7643
7834
  return `${shown.filter((entry) => entry.kind === "model").length}/${shown.length}`;
7644
7835
  }
7645
7836
  },
@@ -7651,7 +7842,9 @@ function createItemsTestModule(options) {
7651
7842
  latestTHREE = lent.THREE;
7652
7843
  const offChange = lent.bench?.onChange(onChange);
7653
7844
  const offFrame = lent.onFrame((dt) => {
7654
- for (const entry of entries2) if (entry.group === "showcase" && entry.root.parent) entry.root.rotation.y += dt * SPIN;
7845
+ for (let i = entries2.length - 1; i >= 0; i--) if (!entries2[i].root.parent) entries2.splice(i, 1);
7846
+ for (let i = shelfRoots.length - 1; i >= 0; i--) if (!shelfRoots[i].parent) shelfRoots.splice(i, 1);
7847
+ for (const entry of entries2) if (entry.group === "showcase") entry.root.rotation.y += dt * SPIN;
7655
7848
  });
7656
7849
  return () => {
7657
7850
  offChange?.();
@@ -7766,6 +7959,7 @@ export {
7766
7959
  ITEM_FAMILIES,
7767
7960
  ITEM_PREFIX,
7768
7961
  MODEL_BUDGET_DEVIATIONS,
7962
+ OPENING_NAME,
7769
7963
  ROW_LIMIT,
7770
7964
  RULER_HEIGHT,
7771
7965
  RULER_ID,
@@ -7779,6 +7973,7 @@ export {
7779
7973
  WEAR_AMOUNT,
7780
7974
  WEAR_TAGS,
7781
7975
  WEAR_TARGET,
7976
+ asLid,
7782
7977
  buildItem,
7783
7978
  buildItemLod,
7784
7979
  canonicalFrame,
@@ -7797,14 +7992,18 @@ export {
7797
7992
  itemFamily,
7798
7993
  itemModelBuilder,
7799
7994
  itemModelEntry,
7995
+ itemOpening,
7800
7996
  itemThumbnail,
7801
7997
  itemThumbnailSvg,
7802
7998
  listItemModels,
7803
7999
  mergeItem,
8000
+ openItem,
7804
8001
  registerItemModel,
7805
8002
  renderItemThumbnail,
8003
+ setOpeningContents,
7806
8004
  setWear,
7807
8005
  shade,
8006
+ shapeDestruction,
7808
8007
  shapeOf,
7809
8008
  shapeThumbnailSvg,
7810
8009
  shelvesLayout,
@@ -7812,6 +8011,7 @@ export {
7812
8011
  tagForDestruction,
7813
8012
  thumbnailPatch,
7814
8013
  triangleBudgetOf,
8014
+ turnItem,
7815
8015
  unregisterItemModel,
7816
8016
  wearableMaterials
7817
8017
  };