@adatechnology/game-floorplan-three 0.10.3 → 0.11.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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RoomRects, T as Three, H as HouseRendererOptions, a as HouseRenderer, b as HouseRecord } from './testing-DWLAejq6.js';
2
- export { A as AreaContext, B as BuildOptions, D as DEFAULT_SPECIMENS, c as Damageable, F as FLOORPLAN_AREA_ID, d as FloorplanEngineLike, e as FloorplanTestOptions, f as House, g as HouseBoxCollider, h as HouseFurnitureCollider, i as HouseInteractable, j as HouseInteractives, k as HousePart, l as HousePlan, m as HousePoint, n as HouseTargetOptions, L as LightingOptions, M as Messages, S as SPECIMEN_AT, o as SpecimenDef, p as TemplateGroup, q as Translate, r as buildSpecimenMeshes, s as createFloorplanTestModule, t as createHouseScenarios, u as createTranslator, v as en, w as locales, x as ptBR, y as specimenSpec } from './testing-DWLAejq6.js';
1
+ import { R as RoomRects, T as Three, H as HouseRendererOptions, a as HouseRenderer, b as HouseRecord } from './testing-Db8KbfLm.js';
2
+ export { A as AreaContext, B as BuildOptions, D as DEFAULT_SPECIMENS, c as Damageable, F as FLOORPLAN_AREA_ID, d as FloorplanEngineLike, e as FloorplanTestOptions, f as House, g as HouseBoxCollider, h as HouseFurnitureCollider, i as HouseInteractable, j as HouseInteractives, k as HousePart, l as HousePlan, m as HousePoint, n as HouseTargetOptions, L as LightingOptions, M as Messages, S as SPECIMEN_AT, o as SpecimenDef, p as TemplateGroup, q as Translate, r as buildSpecimenMeshes, s as createFloorplanTestModule, t as createHouseScenarios, u as createTranslator, v as en, w as locales, x as ptBR, y as specimenSpec } from './testing-Db8KbfLm.js';
3
3
  import { DestructionEvent, DestructionWorld } from '@adatechnology/game-destruction';
4
4
  import { DestructibleSpec, WarmUpProbes } from '@adatechnology/game-contracts';
5
5
  import * as THREE_NS from 'three';
@@ -397,4 +397,28 @@ declare function wallPlan(options: WallPieceOptions): WallPlan;
397
397
  */
398
398
  declare function wallPiece(THREE: Three, options: WallPieceOptions): WallPiece;
399
399
 
400
- export { type DestructibleHouse, type FloorNavigator, type FurnitureCatalogEntry, type FurnitureSpecOptions, type FurnitureSpecResult, HouseRenderer, HouseRendererOptions, type NavFlight, type NavFloor, type NavHouse, type NavHouseDef, type NavRect, type NavResult, type NavShape, type NavStair, type NavigableHouse, type NavigationDefOptions, type NavigatorBinding, OPEN_ROOM_TYPES, type TapSpecOptions, type TapSpecResult, VERSION, type WallPiece, type WallPieceOptions, bindNavigator, create, createFloorNavigator, create as createHouseRenderer, furnitureSpec, isOpenArea, navigationDefOf, planLod, rectsOf, tapSpec, wallPiece, wallPlan };
400
+ /**
401
+ * The outer baseboard is a band of glazed ceramic tiles (cerâmica esmaltada, 8 mm, on 4 mm of tile adhesive: 12 mm out of the plaster), the usual barrado of a
402
+ * facade, which takes the splashes of rain and the knocks at foot height. Each tile is a piece of its own (`baseboard:<wall>:<side>:<n>`, `length` long with a
403
+ * `joint` of grout between tiles), glued to the wall: a shot craters the tile it hits, more shots or a kick crack and shatter that tile and the wall shows
404
+ * behind it, a blast breaks the tiles it reaches, and a tile comes off when its wall goes. `BuildOptions.baseboard: 'band'` draws it as one strip per face
405
+ * (the Visor de casas 3D's drawing), still ceramic.
406
+ */
407
+ declare const BASEBOARD_TILES: {
408
+ readonly length: 0.6;
409
+ readonly joint: 0.003;
410
+ readonly material: "ceramic";
411
+ readonly density: 2300;
412
+ };
413
+ /**
414
+ * The protective sidewalk around the walls is cast concrete (4.5 cm on the ground, 60 cm wide) cut by expansion joints every `length` metres: each slab is a
415
+ * piece resting on the ground, so a blast cracks, chips and breaks the slabs it reaches and a shot marks the one it hits.
416
+ */
417
+ declare const SIDEWALK_SLABS: {
418
+ readonly length: 1.2;
419
+ readonly joint: 0.01;
420
+ readonly material: "concrete";
421
+ readonly density: 2400;
422
+ };
423
+
424
+ export { BASEBOARD_TILES, type DestructibleHouse, type FloorNavigator, type FurnitureCatalogEntry, type FurnitureSpecOptions, type FurnitureSpecResult, HouseRenderer, HouseRendererOptions, type NavFlight, type NavFloor, type NavHouse, type NavHouseDef, type NavRect, type NavResult, type NavShape, type NavStair, type NavigableHouse, type NavigationDefOptions, type NavigatorBinding, OPEN_ROOM_TYPES, SIDEWALK_SLABS, type TapSpecOptions, type TapSpecResult, VERSION, type WallPiece, type WallPieceOptions, bindNavigator, create, createFloorNavigator, create as createHouseRenderer, furnitureSpec, isOpenArea, navigationDefOf, planLod, rectsOf, tapSpec, wallPiece, wallPlan };
@@ -23,9 +23,11 @@ var GameFloorplanThree = (() => {
23
23
  // src/index.ts
24
24
  var index_exports = {};
25
25
  __export(index_exports, {
26
+ BASEBOARD_TILES: () => BASEBOARD_TILES,
26
27
  DEFAULT_SPECIMENS: () => DEFAULT_SPECIMENS,
27
28
  FLOORPLAN_AREA_ID: () => FLOORPLAN_AREA_ID,
28
29
  OPEN_ROOM_TYPES: () => OPEN_ROOM_TYPES,
30
+ SIDEWALK_SLABS: () => SIDEWALK_SLABS,
29
31
  SPECIMEN_AT: () => SPECIMEN_AT,
30
32
  VERSION: () => VERSION,
31
33
  bindNavigator: () => bindNavigator,
@@ -6563,8 +6565,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6563
6565
  }
6564
6566
 
6565
6567
  // src/house/baseboard.ts
6568
+ var BASEBOARD_TILES = { length: 0.6, joint: 3e-3, material: "ceramic", density: 2300 };
6569
+ var SIDEWALK_SLABS = { length: 1.2, joint: 0.01, material: "concrete", density: 2400 };
6566
6570
  function installHouseBaseboard(K, shared) {
6567
- const { Y0, bx, cursor, sideOf } = K;
6571
+ const { Y0, bx, cursor, pieceRecord, sideOf } = K;
6568
6572
  const sh = (...a) => K.sh(...a);
6569
6573
  function baseboardAndSidewalk() {
6570
6574
  const R = shared.ctx.r, W = 0.6, t = 0.012, ht = 0.35, color2 = sh(shared.ctx.colors.facade != null ? shared.ctx.colors.facade : 14209216, 0.62), y0 = Y0(0), cal = 13947078;
@@ -6586,15 +6590,29 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6586
6590
  };
6587
6591
  for (const A of ws) for (const [side, sd] of [[A.w.sides[0], -1], [A.w.sides[1], 1]]) {
6588
6592
  if (!sideOf(side, false).exterior) continue;
6589
- const strip = (k, y1, y2, o0, o1, mat, c, y1b) => {
6593
+ const strip = (k, y1, y2, o0, o1, mat, c, piece2, laid = BASEBOARD_TILES) => {
6590
6594
  const ea = junction(A, A.a, sd) > 0 ? A.th / 2 + k : junction(A, A.a, sd) < 0 ? -A.th / 2 : 0, eb = junction(A, A.b, sd) > 0 ? A.th / 2 + k : junction(A, A.b, sd) < 0 ? -A.th / 2 : 0;
6591
6595
  const s0 = A.a - ea, s1 = A.b + eb, f0 = A.L + sd * (A.th / 2 + o0), f1 = A.L + sd * (A.th / 2 + o1), lo = Math.min(f0, f1), hi = Math.max(f0, f1);
6592
6596
  if (s1 - s0 < 1e-3) return;
6593
- if (A.au) bx(mat, s0, y1, lo, s1, y2, hi, c);
6594
- else bx(mat, lo, y1, s0, hi, y2, s1, c);
6597
+ const box3 = (a, b) => {
6598
+ if (A.au) bx(mat, a, y1, lo, b, y2, hi, c);
6599
+ else bx(mat, lo, y1, a, hi, y2, b, c);
6600
+ };
6601
+ const tag = laid === BASEBOARD_TILES ? "baseboard" : "sidewalk";
6602
+ const tile = (id, a, b) => {
6603
+ cursor.pc = pieceRecord(id, laid.material, null, { floor: 0, mass: Math.round((b - a) * (y2 - y1) * (hi - lo) * laid.density * 100) / 100, tags: [tag] });
6604
+ box3(a, b);
6605
+ };
6606
+ if (!piece2) box3(s0, s1);
6607
+ else if (shared.ctx.baseboardBand) tile(piece2, s0, s1);
6608
+ else {
6609
+ const n = Math.max(1, Math.round((s1 - s0) / laid.length)), w = (s1 - s0) / n, j = laid.joint / 2;
6610
+ for (let i = 0; i < n; i++) tile(`${piece2}:${i}`, s0 + i * w + (i > 0 ? j : 0), s0 + (i + 1) * w - (i < n - 1 ? j : 0));
6611
+ }
6612
+ cursor.pc = null;
6595
6613
  };
6596
- strip(t, y0, y0 + ht, 0, t, "plaster", color2);
6597
- strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal);
6614
+ strip(t, y0, y0 + ht, 0, t, "plaster", color2, A.w.id ? `baseboard:${A.w.id}:${sd < 0 ? 0 : 1}` : void 0);
6615
+ strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal, A.w.id ? `sidewalk:${A.w.id}:${sd < 0 ? 0 : 1}` : void 0, SIDEWALK_SLABS);
6598
6616
  }
6599
6617
  }
6600
6618
  const defined = { baseboardAndSidewalk };
@@ -14209,23 +14227,42 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
14209
14227
  const v = table[mat.penetrationClass ?? mat.id] ?? table[mat.id];
14210
14228
  return v === void 0 ? void 0 : v * (mat.penetrationScale ?? 1);
14211
14229
  };
14212
- var capacityScale = (p) => {
14230
+ var BURIED_BLAST_REACH = 0.5;
14231
+ var GIVE_AT_CUT_HP = 0.5;
14232
+ var capacityScale = (p, borne, through) => {
14213
14233
  const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY;
14214
14234
  if (p.st.stripped) return residual;
14215
- const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, 1 - sectionLoss(p));
14235
+ const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, sectionKept(p, residual, borne, through));
14216
14236
  return Math.max(p.spec.reinforcement ? residual : 0.05, kept);
14217
14237
  };
14218
- var sectionLoss = (p) => {
14238
+ var sectionKept = (p, residual, borne, through) => {
14239
+ let kept = 1;
14240
+ forEachSection(p, borne, (c, along, gone) => {
14241
+ const share = through?.(c.center, along) ?? 1;
14242
+ if (share <= 0) return;
14243
+ kept = Math.min(kept, Math.max(p.spec.reinforcement ? residual : 0, 1 - gone) / share);
14244
+ });
14245
+ return kept;
14246
+ };
14247
+ var sectionLoss = (p, borne) => {
14248
+ let worst = 0;
14249
+ forEachSection(p, borne, (_c, _along, gone) => {
14250
+ worst = Math.max(worst, gone);
14251
+ });
14252
+ return Math.min(1, worst);
14253
+ };
14254
+ var forEachSection = (p, borne, visit) => {
14219
14255
  const cells = p.st.chipped;
14220
- if (!cells?.length) return 0;
14256
+ if (!cells?.length) return;
14221
14257
  const [u, v] = planeAxes(p.thin);
14222
14258
  const role = p.spec.structure?.role;
14223
14259
  const up = rotateVec(p.q, [0, 0, 0].map((_, k) => k === v ? 1 : 0));
14224
14260
  const upright = Math.abs(up[1]) > 0.7 ? v : Math.abs(rotateVec(p.q, [0, 0, 0].map((_, k) => k === u ? 1 : 0))[1]) > 0.7 ? u : -1;
14225
14261
  const along = (role === "wall" || role === "partition" || role === "column") && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v;
14226
14262
  const across = along === u ? v : u;
14227
- let worst = 0;
14263
+ const lying = along !== upright || upright < 0;
14228
14264
  for (const c of cells) {
14265
+ if (lying && borne?.(c.center, along)) continue;
14229
14266
  const spans = [];
14230
14267
  for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) spans.push([d.center[across] - d.size[across] / 2, d.center[across] + d.size[across] / 2]);
14231
14268
  spans.sort((a, b) => a[0] - b[0]);
@@ -14235,9 +14272,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
14235
14272
  gone += b - Math.max(a, end);
14236
14273
  end = b;
14237
14274
  }
14238
- worst = Math.max(worst, gone / Math.max(p.dims[across], 1e-6));
14275
+ visit(c, along, Math.min(1, gone / Math.max(p.dims[across], 1e-6)));
14239
14276
  }
14240
- return Math.min(1, worst);
14241
14277
  };
14242
14278
  var isLost = (p) => p.st.status === "broken" || p.st.status === "melted" || p.st.status === "ashes";
14243
14279
  var clone = (v) => structuredClone(v);
@@ -14548,6 +14584,26 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
14548
14584
  byTouching.set(support, { version: poseVersion, box: box3 });
14549
14585
  return box3;
14550
14586
  };
14587
+ const throughOf = (p) => {
14588
+ const load = p.st.load ?? 0;
14589
+ if (load <= 0) return void 0;
14590
+ const above = Math.max(0, load - p.st.mass);
14591
+ const up = rotateVec(p.q, [0, 1, 0]);
14592
+ return (local, along) => {
14593
+ const axis = [0, 0, 0];
14594
+ axis[along] = 1;
14595
+ const sign2 = Math.sign(rotateVec(p.q, axis)[1]);
14596
+ if (Math.abs(up[1]) < 0.7 && Math.abs(rotateVec(p.q, axis)[1]) < 0.7) return 1;
14597
+ const half = p.dims[along] / 2;
14598
+ const share = clamp2((half - sign2 * local[along]) / Math.max(p.dims[along], 1e-6), 0, 1);
14599
+ return (above + p.st.mass * share) / load;
14600
+ };
14601
+ };
14602
+ const borneOn = (p, supports) => {
14603
+ if (supports.length === 0) return void 0;
14604
+ const boxes = supports.map((support) => contactBox(p, support));
14605
+ return (local, along) => boxes.some(([lo, hi]) => local[along] >= lo[along] - SUPPORT_TOLERANCE && local[along] <= hi[along] + SUPPORT_TOLERANCE);
14606
+ };
14551
14607
  const measureContact = (p, support) => {
14552
14608
  const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q);
14553
14609
  const lo = [0, 0, 0], hi = [0, 0, 0];
@@ -14755,7 +14811,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
14755
14811
  o.unsup[i] = o.anyAnchor && !isLost(p) && !p.orphan;
14756
14812
  continue;
14757
14813
  }
14758
- p.st.stress = p.st.load * structureSafety / (p.cap * capacityScale(p));
14814
+ p.st.stress = p.st.load * structureSafety / (p.cap * capacityScale(p, borneOn(p, (lowerOf.get(i) ?? []).map((k) => parts[k])), throughOf(p)));
14759
14815
  if (p.bend) {
14760
14816
  p.bendLoad = p.st.mass + bending[i];
14761
14817
  const bent = restFlexure(o, p, lowerOf.get(i) ?? []);
@@ -15845,6 +15901,27 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
15845
15901
  debris(o, p, p.mat.breakDebris, center, [0, -1, 0], 6, 1, src);
15846
15902
  return loose.length;
15847
15903
  };
15904
+ const giveAtCut = (o, p, src) => {
15905
+ if (!p.spec.reinforcement || !p.spec.units || !p.st.chipped?.length || sectionLoss(p) <= 0) return false;
15906
+ const opened = [];
15907
+ for (const j of o.byPart.get(p.spec.id) ?? []) {
15908
+ if (j.st.open) continue;
15909
+ const onIt = j.bears === "a_on_b" && j.spec.b === p.spec.id || j.bears === "b_on_a" && j.spec.a === p.spec.id;
15910
+ if (!onIt) continue;
15911
+ j.st.open = true;
15912
+ j.st.openedBy = "break";
15913
+ opened.push(j);
15914
+ }
15915
+ if (opened.length === 0) return false;
15916
+ p.st.hp = Math.max(p.st.hp, p.st.maxHp * GIVE_AT_CUT_HP);
15917
+ markDamaged(p);
15918
+ solveStructure(o);
15919
+ recomputeGroups(o);
15920
+ detachEvents(o, opened, "break", src);
15921
+ exposeRebar(o, p, src);
15922
+ collapseCheck(o, src);
15923
+ return true;
15924
+ };
15848
15925
  const stripPart = (o, p, reinforcement, src) => {
15849
15926
  const bars = rebarBars(p.dims, p.thin, reinforcement.spacing);
15850
15927
  p.st.stripped = true;
@@ -15902,6 +15979,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
15902
15979
  hingeDrop(o, p, src);
15903
15980
  return;
15904
15981
  }
15982
+ if (!force && giveAtCut(o, p, src)) return;
15905
15983
  const ex = p.spec.explodes;
15906
15984
  const style = force ?? (p.snap ? "snap" : p.mat.fracture === "none" ? "snap" : p.mat.fracture);
15907
15985
  const { c, q } = partXf(o, p);
@@ -16248,7 +16326,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
16248
16326
  const dx = local[0] - p.pos[0];
16249
16327
  const dy = local[1] - p.pos[1];
16250
16328
  const dz = local[2] - p.pos[2];
16251
- if (dx * dx + dy * dy + dz * dz < reach * reach) near.push(p);
16329
+ if (dx * dx + dy * dy + dz * dz >= reach * reach) continue;
16330
+ if (p.spec.anchored && p.spec.structure?.role === "foundation" && distToPart(o, p, point) > BURIED_BLAST_REACH) continue;
16331
+ near.push(p);
16252
16332
  }
16253
16333
  blastProbe.partsTested += o.parts.length;
16254
16334
  blastProbe.partsNear += near.length;
@@ -20670,7 +20750,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
20670
20750
  if (!b) continue;
20671
20751
  const vol = Math.max(1e-6, (b[3] - b[0]) * (b[4] - b[1]) * (b[5] - b[2]));
20672
20752
  const p = { id, role: "none", material: pc.mat, aabb: [b[0], b[2], b[3], b[5]], y0: b[1], y1: b[4], floor: pc.floor != null ? pc.floor : floorAtY(b[1] + 0.1), mass: pc.mass != null ? pc.mass : Math.max(0.5, vol * (DENSITY[pc.mat] || 800) * (pc.fill != null ? pc.fill : 0.15)), meshes: meshes.get(id).length, extra: true };
20673
- for (const k of ["contains", "explodes", "tags", "form", "thickness", "fill"]) if (pc[k] != null) p[k] = pc[k];
20753
+ for (const k of ["contains", "explodes", "tags", "form", "thickness", "fill", "units"]) if (pc[k] != null) p[k] = pc[k];
20674
20754
  parts.push(p);
20675
20755
  byId.set(id, p);
20676
20756
  }
@@ -20679,7 +20759,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
20679
20759
  return cx >= q.aabb[0] - m && cx <= q.aabb[2] + m && cz >= q.aabb[1] - m && cz <= q.aabb[3] + m && cy >= q.y0 - m && cy <= q.y1 + m;
20680
20760
  };
20681
20761
  for (const p of parts.slice(base)) {
20682
- if (!/^(window|window_pane|door|jamb|pipe|water_tank)/.test(p.id)) continue;
20762
+ if (/^sidewalk:/.test(p.id)) {
20763
+ supports.push({ part: p.id, on: "ground", joint: "mortar", extra: true });
20764
+ continue;
20765
+ }
20766
+ if (!/^(window|window_pane|door|jamb|pipe|water_tank|baseboard)/.test(p.id)) continue;
20683
20767
  const target = /^water_tank/.test(p.id) ? ["slab"] : ["wall", "partition"];
20684
20768
  let m = null, md = 1e9;
20685
20769
  for (const q of parts.slice(0, base)) {
@@ -20690,7 +20774,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
20690
20774
  m = q;
20691
20775
  }
20692
20776
  }
20693
- if (m) supports.push({ part: p.id, on: m.id, joint: /^(window|jamb)/.test(p.id) ? "glue" : "clip", bears: false, extra: true });
20777
+ if (m) supports.push({ part: p.id, on: m.id, joint: /^(window|jamb|baseboard)/.test(p.id) ? "glue" : "clip", bears: false, extra: true });
20694
20778
  }
20695
20779
  const specParts = parts.slice(), specSupports = supports.slice();
20696
20780
  if (view.panels.length) {
@@ -21792,6 +21876,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21792
21876
  cursor.separate = opts.pieces === "meshes";
21793
21877
  cursor.pc = null;
21794
21878
  shared.ctx.showPillars = opts.pillars !== "hidden";
21879
+ shared.ctx.baseboardBand = opts.baseboard === "band";
21795
21880
  shared.ctx.apartment = r.template === "apartment_modern";
21796
21881
  shared.ctx.pa = Math.max(3, Math.min(20, pr.floors != null ? pr.floors : 5));
21797
21882
  shared.ctx.pf = Math.max(1, Math.min(shared.ctx.pa, pr.floor != null ? pr.floor : 3));