@adatechnology/game-test-room 0.7.0 → 0.9.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/README.md +2 -0
- package/dist/index.d.ts +28 -3
- package/dist/index.global.js +2222 -173
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +95 -9
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// src/room.ts
|
|
2
2
|
import { createDestruction, JOINT_DEFAULTS as JOINT_DEFAULTS2, resolveStrings as resolveDestructionStrings } from "@adatechnology/game-destruction";
|
|
3
|
-
import {
|
|
3
|
+
import { createAudioEngine, createAudioSink } from "@adatechnology/game-audio";
|
|
4
|
+
import { createDestructionRenderer, createDestructionSound, specFromObject3D } from "@adatechnology/game-destruction-three";
|
|
4
5
|
import { createArsenal, DEFAULT_LOADOUT } from "@adatechnology/game-weapons";
|
|
5
6
|
import { createFilmLcg, createFluids, createItemUse, ITEM_USES, resolveStrings as resolveFluidStrings } from "@adatechnology/game-fluids";
|
|
6
7
|
import { createFilmBridge, createFilmManager, createFluidRenderer } from "@adatechnology/game-fluids-three";
|
|
7
8
|
import { createGroundField, createVfx } from "@adatechnology/game-vfx";
|
|
8
9
|
import { createGroundPatch, createVfxRenderer } from "@adatechnology/game-vfx-three";
|
|
9
|
-
import { checkAnimation, checkBench, checkDestructible, checkSpec } from "@adatechnology/game-contracts";
|
|
10
|
+
import { checkAnimation, checkBench, checkDestructible, checkSpec, createEnvironmentBus } from "@adatechnology/game-contracts";
|
|
10
11
|
|
|
11
12
|
// src/items.ts
|
|
12
13
|
import { buildFrame } from "@adatechnology/game-destruction";
|
|
@@ -321,6 +322,16 @@ var en = {
|
|
|
321
322
|
"ui.slow": "Slow motion 0.25\xD7",
|
|
322
323
|
"ui.fast": "Time \xD710",
|
|
323
324
|
"ui.tap": "Tap",
|
|
325
|
+
"ui.blast.shelter": "Shelter",
|
|
326
|
+
"ui.blast.fragmentHits": "Fragments",
|
|
327
|
+
"ui.blast.confinement": "Confinement",
|
|
328
|
+
"ui.blast.shelter.hint": "Blasts: walls and other parts between the blast and the target take their share",
|
|
329
|
+
"ui.blast.fragmentHits.hint": "Blasts: the pieces of what breaks fly on and hit what is behind",
|
|
330
|
+
"ui.blast.confinement.hint": "Blasts: pressure builds up in an enclosed room",
|
|
331
|
+
"metric.blast_shelter": "Blast reaching (%)",
|
|
332
|
+
"metric.blast_confinement": "Blast pressure (x)",
|
|
333
|
+
"metric.blast_fragments": "Fragment hits",
|
|
334
|
+
"act.blast_report": "Blast: {shelter}% reached the most sheltered target, pressure x{confinement}, {fragments} fragment hits, {n} targets",
|
|
324
335
|
"ui.quality": "Quality",
|
|
325
336
|
"ui.quality.low": "low",
|
|
326
337
|
"ui.quality.medium": "medium",
|
|
@@ -646,6 +657,16 @@ var ptBR = {
|
|
|
646
657
|
"ui.slow": "C\xE2mera lenta 0,25\xD7",
|
|
647
658
|
"ui.fast": "Tempo \xD710",
|
|
648
659
|
"ui.tap": "Torneira",
|
|
660
|
+
"ui.blast.shelter": "Abrigo",
|
|
661
|
+
"ui.blast.fragmentHits": "Estilha\xE7os",
|
|
662
|
+
"ui.blast.confinement": "Confinamento",
|
|
663
|
+
"ui.blast.shelter.hint": "Explos\xF5es: paredes e outras partes entre a explos\xE3o e o alvo ficam com a sua parte",
|
|
664
|
+
"ui.blast.fragmentHits.hint": "Explos\xF5es: os peda\xE7os do que quebra voam e acertam o que est\xE1 atr\xE1s",
|
|
665
|
+
"ui.blast.confinement.hint": "Explos\xF5es: a press\xE3o sobe num ambiente fechado",
|
|
666
|
+
"metric.blast_shelter": "Explos\xE3o que chegou (%)",
|
|
667
|
+
"metric.blast_confinement": "Press\xE3o da explos\xE3o (x)",
|
|
668
|
+
"metric.blast_fragments": "Estilha\xE7os que acertaram",
|
|
669
|
+
"act.blast_report": "Explos\xE3o: {shelter}% chegou ao alvo mais abrigado, press\xE3o x{confinement}, {fragments} estilha\xE7os acertaram, {n} alvos",
|
|
649
670
|
"ui.quality": "Qualidade",
|
|
650
671
|
"ui.quality.low": "baixa",
|
|
651
672
|
"ui.quality.medium": "m\xE9dia",
|
|
@@ -1371,6 +1392,16 @@ var segmentTouchesBox = (from, to, min, max) => {
|
|
|
1371
1392
|
|
|
1372
1393
|
// src/explosives.ts
|
|
1373
1394
|
var CONE_BLAST_RADIUS = 0.5;
|
|
1395
|
+
var summarizeBlast = (results) => {
|
|
1396
|
+
const reports = results.flatMap((r) => r.blast ? [r.blast] : []);
|
|
1397
|
+
if (reports.length === 0) return void 0;
|
|
1398
|
+
return {
|
|
1399
|
+
shelter: Math.min(...reports.map((r) => r.shelter)),
|
|
1400
|
+
confinement: reports[0].confinement,
|
|
1401
|
+
fragmentHits: reports.reduce((n, r) => n + r.fragmentHits, 0),
|
|
1402
|
+
targets: reports.length
|
|
1403
|
+
};
|
|
1404
|
+
};
|
|
1374
1405
|
var toArray = (vector) => [vector.x, vector.y, vector.z];
|
|
1375
1406
|
function createExplosives(context) {
|
|
1376
1407
|
const { THREE, scene, camera, world, renderer, arsenal, translate, format, action } = context;
|
|
@@ -1517,17 +1548,27 @@ function createExplosives(context) {
|
|
|
1517
1548
|
if (box2.isEmpty()) box2.expandByPoint(object.position);
|
|
1518
1549
|
const at = mostExposedPoint(box2, detonation);
|
|
1519
1550
|
if (!at) continue;
|
|
1520
|
-
|
|
1551
|
+
const results = world.explode(at, detonation.energy * blastEffect(detonation, at).falloff, CONE_BLAST_RADIUS, "player", context.blast());
|
|
1552
|
+
reached += results.length;
|
|
1553
|
+
told(results);
|
|
1521
1554
|
}
|
|
1522
1555
|
return reached;
|
|
1523
1556
|
};
|
|
1557
|
+
const told = (results) => {
|
|
1558
|
+
const summary = summarizeBlast(results);
|
|
1559
|
+
if (!summary) return;
|
|
1560
|
+
context.blasted(summary);
|
|
1561
|
+
action("blast_report", translate("act.blast_report", { shelter: format(summary.shelter * 100, 0), confinement: format(summary.confinement, 2), fragments: summary.fragmentHits, n: summary.targets }), { data: { ...summary } });
|
|
1562
|
+
};
|
|
1524
1563
|
const detonate = (projectile, detonation) => {
|
|
1525
1564
|
const weaponName = context.toolName(projectile.weapon);
|
|
1526
1565
|
const reach = Math.max(detonation.injuryRadius, detonation.lethalRadius);
|
|
1527
|
-
const
|
|
1566
|
+
const results = detonation.energy <= 0 || detonation.cone ? [] : world.explode(detonation.point, detonation.energy, reach, "player", context.blast());
|
|
1567
|
+
const reached = detonation.energy <= 0 ? 0 : detonation.cone ? coneBlast(detonation) : results.length;
|
|
1568
|
+
if (!detonation.cone) told(results);
|
|
1528
1569
|
if (detonation.energy > 0) {
|
|
1529
1570
|
const isPlayed = context.effects.explosion(detonation.explosive, detonation.point, { direction: detonation.direction }) !== null;
|
|
1530
|
-
renderer.explode(detonation.point, detonation.energy, reach, { visual: !isPlayed });
|
|
1571
|
+
renderer.explode(detonation.point, detonation.energy, reach, { visual: !isPlayed, report: results });
|
|
1531
1572
|
}
|
|
1532
1573
|
if (detonation.stunSeconds !== void 0) renderer.emit("flash", detonation.point, [0, 1, 0], 1, 1);
|
|
1533
1574
|
const onPlayer = blastEffect(detonation, toArray(camera.position));
|
|
@@ -1824,7 +1865,7 @@ function createLog(options = {}) {
|
|
|
1824
1865
|
}
|
|
1825
1866
|
|
|
1826
1867
|
// src/metrics.ts
|
|
1827
|
-
var ROOM_METRICS = ["fps", "frame_ms", "draw_calls", "triangles", "objects", "fragments", "particles", "decals"];
|
|
1868
|
+
var ROOM_METRICS = ["fps", "frame_ms", "draw_calls", "triangles", "objects", "fragments", "particles", "decals", "blast_shelter", "blast_confinement", "blast_fragments"];
|
|
1828
1869
|
var WINDOW_S = 0.5;
|
|
1829
1870
|
function createRoomMetrics(sources) {
|
|
1830
1871
|
const wanted = new Set(sources.ids);
|
|
@@ -1861,6 +1902,12 @@ function createRoomMetrics(sources) {
|
|
|
1861
1902
|
const render = ownsRender ? { calls, triangles } : gl.info?.render;
|
|
1862
1903
|
put("draw_calls", render?.calls);
|
|
1863
1904
|
put("triangles", render?.triangles);
|
|
1905
|
+
const blast = sources.blast?.();
|
|
1906
|
+
if (blast) {
|
|
1907
|
+
put("blast_shelter", blast.shelter * 100);
|
|
1908
|
+
put("blast_confinement", blast.confinement);
|
|
1909
|
+
put("blast_fragments", blast.fragmentHits);
|
|
1910
|
+
}
|
|
1864
1911
|
if (!["objects", "fragments", "particles", "decals"].some((id) => wanted.has(id))) return out;
|
|
1865
1912
|
const destruction = sources.destruction.stats();
|
|
1866
1913
|
const fluids = sources.fluids.stats();
|
|
@@ -3543,6 +3590,8 @@ function createUi(o) {
|
|
|
3543
3590
|
o.onFast(fast);
|
|
3544
3591
|
});
|
|
3545
3592
|
const tapBtn = ctl(t("ui.tap"), () => o.onTap());
|
|
3593
|
+
const blastBtns = ["shelter", "fragmentHits", "confinement"].map((key) => ({ key, b: ctl(t(`ui.blast.${key}`), () => o.onBlast(key)) }));
|
|
3594
|
+
for (const { key, b } of blastBtns) b.title = t(`ui.blast.${key}.hint`);
|
|
3546
3595
|
const qSel = mk2("select");
|
|
3547
3596
|
for (const q of ["low", "medium", "high"]) {
|
|
3548
3597
|
const op = mk2("option", void 0, t(`ui.quality.${q}`));
|
|
@@ -3747,6 +3796,7 @@ function createUi(o) {
|
|
|
3747
3796
|
}
|
|
3748
3797
|
slotsEl.forEach((b, i) => b.classList.toggle("on", i === s.slot));
|
|
3749
3798
|
tapBtn.classList.toggle("on", s.tap);
|
|
3799
|
+
for (const { key: key2, b } of blastBtns) b.classList.toggle("on", s.blast[key2]);
|
|
3750
3800
|
count.textContent = t("ui.objects", { n: s.objects });
|
|
3751
3801
|
const ak = JSON.stringify(s.animations);
|
|
3752
3802
|
if (ak !== lastAnim) {
|
|
@@ -3871,6 +3921,13 @@ function createTestRoom(options) {
|
|
|
3871
3921
|
let simTime = 0;
|
|
3872
3922
|
const log = createLog({ exportCancelled: () => t("log.export_cancelled") });
|
|
3873
3923
|
log.setClock(() => simTime);
|
|
3924
|
+
const ownAudio = options.audio === void 0;
|
|
3925
|
+
const audio = options.audio === false ? null : options.audio ?? createAudioEngine();
|
|
3926
|
+
const destructionSound = audio ? createDestructionSound(audio) : null;
|
|
3927
|
+
const playSound = (key, point, volume) => {
|
|
3928
|
+
destructionSound?.onSound(key, point, volume);
|
|
3929
|
+
options.onSound?.(key, point, volume);
|
|
3930
|
+
};
|
|
3874
3931
|
const craterField = options.craters ? createGroundField() : void 0;
|
|
3875
3932
|
const craterPatch = craterField ? createGroundPatch(THREE, { field: craterField, material: new THREE.MeshStandardMaterial({ color: 9342602, roughness: 0.95 }) }) : void 0;
|
|
3876
3933
|
if (craterPatch) {
|
|
@@ -3897,7 +3954,7 @@ function createTestRoom(options) {
|
|
|
3897
3954
|
quality,
|
|
3898
3955
|
groundAt,
|
|
3899
3956
|
pointScale,
|
|
3900
|
-
onSound:
|
|
3957
|
+
onSound: playSound,
|
|
3901
3958
|
onPiece: (piece) => {
|
|
3902
3959
|
rendererPieces.set(piece.objectId, piece);
|
|
3903
3960
|
loose.push(piece);
|
|
@@ -4621,6 +4678,12 @@ function createTestRoom(options) {
|
|
|
4621
4678
|
bodies.push({ id: "player", box: new THREE.Box3(new THREE.Vector3(x - PLAYER_RADIUS, feet, z - PLAYER_RADIUS), new THREE.Vector3(x + PLAYER_RADIUS, y + 0.1, z + PLAYER_RADIUS)) });
|
|
4622
4679
|
return bodies;
|
|
4623
4680
|
}
|
|
4681
|
+
let blastOptions = { ...options.blast };
|
|
4682
|
+
let lastBlast;
|
|
4683
|
+
const blastOn = (key) => Boolean(blastOptions[key]);
|
|
4684
|
+
const toggleBlast = (key) => {
|
|
4685
|
+
blastOptions = { ...blastOptions, [key]: blastOn(key) ? false : true };
|
|
4686
|
+
};
|
|
4624
4687
|
const explosives = createExplosives({
|
|
4625
4688
|
THREE,
|
|
4626
4689
|
scene,
|
|
@@ -4635,6 +4698,10 @@ function createTestRoom(options) {
|
|
|
4635
4698
|
toolName,
|
|
4636
4699
|
withoutHeld,
|
|
4637
4700
|
groundAt,
|
|
4701
|
+
blast: () => blastOptions,
|
|
4702
|
+
blasted: (summary) => {
|
|
4703
|
+
lastBlast = summary;
|
|
4704
|
+
},
|
|
4638
4705
|
translate: t,
|
|
4639
4706
|
format: num,
|
|
4640
4707
|
action,
|
|
@@ -5061,7 +5128,7 @@ function createTestRoom(options) {
|
|
|
5061
5128
|
let metricsAcc = 0;
|
|
5062
5129
|
let ownsLoop = false;
|
|
5063
5130
|
const roomMetricIds = options.metrics === false ? [] : options.metrics ?? ROOM_METRICS;
|
|
5064
|
-
const roomMetrics = createRoomMetrics({ gl, destruction: renderer, fluids: fluidView, effects: vfx.world, ids: roomMetricIds });
|
|
5131
|
+
const roomMetrics = createRoomMetrics({ gl, destruction: renderer, fluids: fluidView, effects: vfx.world, ids: roomMetricIds, blast: () => lastBlast });
|
|
5065
5132
|
let qualityName = quality;
|
|
5066
5133
|
const syncContainers = (sdt) => {
|
|
5067
5134
|
for (const e of entries.values()) {
|
|
@@ -5120,6 +5187,10 @@ function createTestRoom(options) {
|
|
|
5120
5187
|
s.update(dt);
|
|
5121
5188
|
flushEvents(id, s);
|
|
5122
5189
|
}
|
|
5190
|
+
if (audio) {
|
|
5191
|
+
const look = camera.getWorldDirection(listenerDirection);
|
|
5192
|
+
audio.setListener({ position: [camera.position.x, camera.position.y, camera.position.z], yaw: Math.atan2(-look.x, -look.z) });
|
|
5193
|
+
}
|
|
5123
5194
|
for (const update2 of frameListeners) update2(dt);
|
|
5124
5195
|
for (const tr of tracers) {
|
|
5125
5196
|
if (tr.life > 0) {
|
|
@@ -5176,6 +5247,7 @@ function createTestRoom(options) {
|
|
|
5176
5247
|
timeScale,
|
|
5177
5248
|
fast: fastForward,
|
|
5178
5249
|
tap: isTapOn(),
|
|
5250
|
+
blast: { shelter: blastOn("shelter"), fragmentHits: blastOn("fragmentHits"), confinement: blastOn("confinement") },
|
|
5179
5251
|
quality: qualityName,
|
|
5180
5252
|
objects: [...entries.values()].filter((e) => !e.arena).length
|
|
5181
5253
|
};
|
|
@@ -5229,7 +5301,7 @@ function createTestRoom(options) {
|
|
|
5229
5301
|
const ev = evs[pl.fired++];
|
|
5230
5302
|
action("animation_event", t("act.anim_event", { name: pl.entry.name, clip: pl.clip.id, type: ev.type }), { objectId: pl.entry.so.objectId, itemId: pl.entry.so.itemId, data: { clip: pl.clip.id, type: ev.type, at: ev.t, ...ev.data ?? {} } });
|
|
5231
5303
|
const key = ev.type === "sound" ? ev.data?.key : void 0;
|
|
5232
|
-
if (typeof key === "string")
|
|
5304
|
+
if (typeof key === "string") playSound(key, v3(pl.entry.so.root.getWorldPosition(tmpV)), 1);
|
|
5233
5305
|
}
|
|
5234
5306
|
if (pl.t >= pl.clip.duration) {
|
|
5235
5307
|
playing.splice(i, 1);
|
|
@@ -5322,6 +5394,9 @@ function createTestRoom(options) {
|
|
|
5322
5394
|
};
|
|
5323
5395
|
const hostListeners = /* @__PURE__ */ new Set();
|
|
5324
5396
|
const frameListeners = /* @__PURE__ */ new Set();
|
|
5397
|
+
const listenerDirection = new THREE.Vector3();
|
|
5398
|
+
const environment = options.environment ?? createEnvironmentBus();
|
|
5399
|
+
const audioSink = audio ? createAudioSink(audio) : void 0;
|
|
5325
5400
|
function emitHost(event) {
|
|
5326
5401
|
for (const listener of hostListeners) listener(event);
|
|
5327
5402
|
}
|
|
@@ -5371,6 +5446,8 @@ function createTestRoom(options) {
|
|
|
5371
5446
|
scene,
|
|
5372
5447
|
camera,
|
|
5373
5448
|
locale,
|
|
5449
|
+
...audioSink ? { audio: audioSink } : {},
|
|
5450
|
+
environment,
|
|
5374
5451
|
groundAt,
|
|
5375
5452
|
effects: vfx,
|
|
5376
5453
|
tool: () => ({
|
|
@@ -5624,6 +5701,8 @@ function createTestRoom(options) {
|
|
|
5624
5701
|
arsenal,
|
|
5625
5702
|
fluids,
|
|
5626
5703
|
fluidRenderer: fluidView,
|
|
5704
|
+
audio,
|
|
5705
|
+
environment,
|
|
5627
5706
|
log,
|
|
5628
5707
|
get tool() {
|
|
5629
5708
|
return tool;
|
|
@@ -5684,6 +5763,10 @@ function createTestRoom(options) {
|
|
|
5684
5763
|
heldTilt = rad;
|
|
5685
5764
|
},
|
|
5686
5765
|
toggleTap,
|
|
5766
|
+
blast: () => ({ ...blastOptions }),
|
|
5767
|
+
setBlast: (next) => {
|
|
5768
|
+
blastOptions = { ...blastOptions, ...next };
|
|
5769
|
+
},
|
|
5687
5770
|
pause() {
|
|
5688
5771
|
paused = true;
|
|
5689
5772
|
},
|
|
@@ -5717,6 +5800,8 @@ function createTestRoom(options) {
|
|
|
5717
5800
|
return { room: roomMetrics.sample(), module: moduleMetrics() };
|
|
5718
5801
|
},
|
|
5719
5802
|
dispose() {
|
|
5803
|
+
destructionSound?.dispose();
|
|
5804
|
+
if (ownAudio) audio?.dispose();
|
|
5720
5805
|
for (const detach of detachers.values()) detach();
|
|
5721
5806
|
detachers.clear();
|
|
5722
5807
|
for (const store of benches.values()) store.dispose();
|
|
@@ -5792,6 +5877,7 @@ function createTestRoom(options) {
|
|
|
5792
5877
|
setTool(loadout[index]);
|
|
5793
5878
|
},
|
|
5794
5879
|
onTap: () => toggleTap(),
|
|
5880
|
+
onBlast: (key) => toggleBlast(key),
|
|
5795
5881
|
onPlay: (objectId, clipId) => {
|
|
5796
5882
|
playAnimation(clipId, objectId);
|
|
5797
5883
|
},
|