@adatechnology/game-test-room 0.23.0 → 0.24.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 +5 -0
- package/dist/index.global.js +217 -140
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -751,6 +751,11 @@ interface TestRoomOptions {
|
|
|
751
751
|
audio?: AudioEngine | false;
|
|
752
752
|
/** Where the kit's recorded sound files (game-audio `assets/sfx/`) are served, for the room's engine (default `./sfx/`); `null` plays the recipes only. */
|
|
753
753
|
samplesBaseUrl?: string | null;
|
|
754
|
+
/**
|
|
755
|
+
* Where the owner's own sounds are served (`sfx:user` of game-audio writes them to `.sfx-local/`, kept out of git), default `./sfx-local/`; `null`
|
|
756
|
+
* leaves them out. They load after the kit's: a sound the kit lacks plays the owner's file, and one the kit has keeps the kit's in front.
|
|
757
|
+
*/
|
|
758
|
+
userSamplesBaseUrl?: string | null;
|
|
754
759
|
/** The environment store modules get as `host.environment` (the weather module writes it, the others read it). Default: a new one with a calm dry day. */
|
|
755
760
|
environment?: EnvironmentBus;
|
|
756
761
|
/** Show the built-in HUD and panels (default true). */
|
package/dist/index.global.js
CHANGED
|
@@ -6657,7 +6657,7 @@ var GameTestRoom = (() => {
|
|
|
6657
6657
|
};
|
|
6658
6658
|
var resolveStrings = (locale) => locales[locale ?? "en"] ?? locales.en;
|
|
6659
6659
|
|
|
6660
|
-
// ../game-audio/dist/chunk-
|
|
6660
|
+
// ../game-audio/dist/chunk-KBTUANNG.js
|
|
6661
6661
|
var DISTANCE_CURVES = {
|
|
6662
6662
|
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
6663
6663
|
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
@@ -8526,10 +8526,12 @@ var GameTestRoom = (() => {
|
|
|
8526
8526
|
noise: () => noiseBuffer(store, audio, mix.noise.seconds),
|
|
8527
8527
|
time
|
|
8528
8528
|
});
|
|
8529
|
+
const recipeBank = registry.bankOf(plan.id);
|
|
8529
8530
|
announce({
|
|
8530
8531
|
id: plan.id,
|
|
8531
8532
|
kind: "recipe",
|
|
8532
8533
|
...fallbackOf ? { fallbackOf } : {},
|
|
8534
|
+
...recipeBank ? { bank: recipeBank } : {},
|
|
8533
8535
|
requestedAt,
|
|
8534
8536
|
startAt: time,
|
|
8535
8537
|
outputLatency: latencyOf(audio),
|
|
@@ -8631,9 +8633,11 @@ var GameTestRoom = (() => {
|
|
|
8631
8633
|
const time = requestedAt + (playOptions.delay ?? 0);
|
|
8632
8634
|
const chokeList = sample.choke ? choked(sample.id) : void 0;
|
|
8633
8635
|
const realized = realizeSample(plan, { context: audio, output: sampleOutput(plan.bus), buffer: (url2) => sampleStore.buffer(url2), time });
|
|
8636
|
+
const sampleBank = registry.bankOf(plan.id);
|
|
8634
8637
|
announce({
|
|
8635
8638
|
id: plan.id,
|
|
8636
8639
|
kind: "sample",
|
|
8640
|
+
...sampleBank ? { bank: sampleBank } : {},
|
|
8637
8641
|
requestedAt,
|
|
8638
8642
|
startAt: time,
|
|
8639
8643
|
outputLatency: latencyOf(audio),
|
|
@@ -8954,7 +8958,11 @@ var GameTestRoom = (() => {
|
|
|
8954
8958
|
["casing_drop_terra_pistol", 1],
|
|
8955
8959
|
["casing_drop_terra_rifle", 1],
|
|
8956
8960
|
["casing_drop_terra_shell", 1],
|
|
8957
|
-
["rocket_fire", 2]
|
|
8961
|
+
["rocket_fire", 2],
|
|
8962
|
+
["smg_45_auto", 2, "sfx_pistol"],
|
|
8963
|
+
["weapon_draw", 2],
|
|
8964
|
+
["suppressor_attach", 3],
|
|
8965
|
+
["suppressor_detach", 3]
|
|
8958
8966
|
]),
|
|
8959
8967
|
...entries("explosoes-fogo", [
|
|
8960
8968
|
["explosion_grenade", 1, "boom"],
|
|
@@ -8968,7 +8976,11 @@ var GameTestRoom = (() => {
|
|
|
8968
8976
|
["fire_loop_large", 1],
|
|
8969
8977
|
["fire_extinguish", 2, "hiss"],
|
|
8970
8978
|
["gas_leak_hiss", 2],
|
|
8971
|
-
["structure_collapse", 2, "crumble"]
|
|
8979
|
+
["structure_collapse", 2, "crumble"],
|
|
8980
|
+
["grenade_bounce", 1],
|
|
8981
|
+
["c4_plant", 2],
|
|
8982
|
+
["c4_beep", 2],
|
|
8983
|
+
["c4_disarm", 2]
|
|
8972
8984
|
]),
|
|
8973
8985
|
...entries("personagem", [
|
|
8974
8986
|
["footstep_concrete_walk", 1, "sfx_step"],
|
|
@@ -8984,7 +8996,19 @@ var GameTestRoom = (() => {
|
|
|
8984
8996
|
["blunt_hit", 1],
|
|
8985
8997
|
["bite", 1, "sfx_flesh"],
|
|
8986
8998
|
["body_fall", 1],
|
|
8987
|
-
["player_hurt", 2]
|
|
8999
|
+
["player_hurt", 2],
|
|
9000
|
+
["footstep_tile_walk", 1, "sfx_step"],
|
|
9001
|
+
["footstep_water_walk", 1, "sfx_step"],
|
|
9002
|
+
["footstep_grate_walk", 2, "sfx_step"],
|
|
9003
|
+
["footstep_duct_walk", 3, "sfx_step"],
|
|
9004
|
+
["ladder_climb", 2],
|
|
9005
|
+
["swim", 2],
|
|
9006
|
+
["zombie_groan", 1],
|
|
9007
|
+
["zombie_alert", 1],
|
|
9008
|
+
["zombie_attack", 1],
|
|
9009
|
+
["zombie_pain", 1],
|
|
9010
|
+
["zombie_claw_hit", 1, "sfx_flesh"],
|
|
9011
|
+
["zombie_claw_miss", 2]
|
|
8988
9012
|
]),
|
|
8989
9013
|
...entries("veiculos", [
|
|
8990
9014
|
["engine_loop_car", 1],
|
|
@@ -9012,7 +9036,8 @@ var GameTestRoom = (() => {
|
|
|
9012
9036
|
["wind_loop", 2],
|
|
9013
9037
|
["thunder_near", 2],
|
|
9014
9038
|
["thunder_far", 2],
|
|
9015
|
-
["water_splash", 2]
|
|
9039
|
+
["water_splash", 2],
|
|
9040
|
+
["helicopter_loop", 3]
|
|
9016
9041
|
])
|
|
9017
9042
|
];
|
|
9018
9043
|
var SFX_MATERIALS = [
|
|
@@ -9094,6 +9119,175 @@ var GameTestRoom = (() => {
|
|
|
9094
9119
|
burst: 20,
|
|
9095
9120
|
burstSpacing: 0.06
|
|
9096
9121
|
};
|
|
9122
|
+
var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
|
|
9123
|
+
function splitTier(id) {
|
|
9124
|
+
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
9125
|
+
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
9126
|
+
}
|
|
9127
|
+
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
9128
|
+
function sampleBankFromManifest(manifest, options) {
|
|
9129
|
+
const baseUrl = options.baseUrl ?? "";
|
|
9130
|
+
const samples = [];
|
|
9131
|
+
const tiersOf = /* @__PURE__ */ new Map();
|
|
9132
|
+
for (const sound of manifest.sounds) {
|
|
9133
|
+
const { base, tier } = splitTier(sound.id);
|
|
9134
|
+
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
9135
|
+
}
|
|
9136
|
+
const bases = /* @__PURE__ */ new Map();
|
|
9137
|
+
for (const sound of manifest.sounds) {
|
|
9138
|
+
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
9139
|
+
}
|
|
9140
|
+
for (const [base, tiers] of tiersOf) {
|
|
9141
|
+
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
9142
|
+
}
|
|
9143
|
+
for (const sound of bases.values()) {
|
|
9144
|
+
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
9145
|
+
const close = refsOf(sound.layers.close, baseUrl);
|
|
9146
|
+
if (!numbers || close.length === 0) continue;
|
|
9147
|
+
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
9148
|
+
const name = splitTier(tier.id).tier;
|
|
9149
|
+
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
9150
|
+
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
9151
|
+
}).sort((a, b) => a.from - b.from);
|
|
9152
|
+
const far = refsOf(sound.layers.far, baseUrl);
|
|
9153
|
+
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
9154
|
+
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
9155
|
+
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
9156
|
+
samples.push({
|
|
9157
|
+
id: sound.id,
|
|
9158
|
+
bus: numbers.bus,
|
|
9159
|
+
close,
|
|
9160
|
+
...far.length > 0 ? { far } : {},
|
|
9161
|
+
...tiers.length > 0 ? { tiers } : {},
|
|
9162
|
+
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
9163
|
+
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
9164
|
+
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
9165
|
+
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
9166
|
+
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
9167
|
+
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
9168
|
+
...numbers.group ? { group: numbers.group } : {},
|
|
9169
|
+
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
9170
|
+
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
9171
|
+
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
9172
|
+
});
|
|
9173
|
+
}
|
|
9174
|
+
return { id: options.id, samples };
|
|
9175
|
+
}
|
|
9176
|
+
var KIT_CATEGORY_BUS = {
|
|
9177
|
+
armas: "weapons",
|
|
9178
|
+
impactos: "world",
|
|
9179
|
+
"explosoes-fogo": "world",
|
|
9180
|
+
personagem: "world",
|
|
9181
|
+
veiculos: "world",
|
|
9182
|
+
"itens-portas": "world",
|
|
9183
|
+
ambiente: "ambience"
|
|
9184
|
+
};
|
|
9185
|
+
var VOICE_IDS = /^(player_(hurt|death|effort|breath)|scream|zombie_)/;
|
|
9186
|
+
var KIT_SAMPLE_ALIASES = {
|
|
9187
|
+
// a house door: the latch giving, the hinge, the leaf meeting the frame, a locked one shaken; a drawer on its runners
|
|
9188
|
+
latch: "metal_latch",
|
|
9189
|
+
creak_wood: "door_creak",
|
|
9190
|
+
shut_wood: "door_wood_shut",
|
|
9191
|
+
rattle: "door_locked_rattle",
|
|
9192
|
+
// a drawer stays on its recipe: the recorded runs (1 to 1.9 s) outlast a drawer's pull
|
|
9193
|
+
// an item taken in the hand (game-destruction-three grab_* keys)
|
|
9194
|
+
grab_hard: "item_pickup_generic",
|
|
9195
|
+
grab_soft: "item_pickup_leather"
|
|
9196
|
+
};
|
|
9197
|
+
function kitSampleDefaults(sound) {
|
|
9198
|
+
const bus = VOICE_IDS.test(sound.id) ? "voices" : KIT_CATEGORY_BUS[sound.category];
|
|
9199
|
+
if (!bus) return void 0;
|
|
9200
|
+
return { bus, pitch: sound.category === "ambiente" || /_loop/.test(sound.id) ? 0 : 0.04 };
|
|
9201
|
+
}
|
|
9202
|
+
function withAliases(manifest, aliases) {
|
|
9203
|
+
const byId = new Map(manifest.sounds.map((sound) => [sound.id, sound]));
|
|
9204
|
+
const extra = [];
|
|
9205
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
9206
|
+
const sound = byId.get(target);
|
|
9207
|
+
if (sound && !byId.has(alias)) extra.push({ ...sound, id: alias });
|
|
9208
|
+
}
|
|
9209
|
+
return { ...manifest, sounds: [...manifest.sounds, ...extra] };
|
|
9210
|
+
}
|
|
9211
|
+
function kitSampleBank(manifest, options = {}) {
|
|
9212
|
+
return sampleBankFromManifest(withAliases(manifest, options.aliases ?? KIT_SAMPLE_ALIASES), {
|
|
9213
|
+
id: options.id ?? "kit_samples",
|
|
9214
|
+
baseUrl: options.baseUrl ?? "",
|
|
9215
|
+
defaults: kitSampleDefaults
|
|
9216
|
+
});
|
|
9217
|
+
}
|
|
9218
|
+
var isFileUrl = (url2) => {
|
|
9219
|
+
const page = globalThis.location?.href;
|
|
9220
|
+
try {
|
|
9221
|
+
return new URL(url2, page).protocol === "file:";
|
|
9222
|
+
} catch {
|
|
9223
|
+
return false;
|
|
9224
|
+
}
|
|
9225
|
+
};
|
|
9226
|
+
var fetchJson = async (url2) => {
|
|
9227
|
+
if (isFileUrl(url2)) throw new Error(`${url2}: file:// is not fetched`);
|
|
9228
|
+
const response = await fetch(url2);
|
|
9229
|
+
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
9230
|
+
return await response.json();
|
|
9231
|
+
};
|
|
9232
|
+
async function loadKitSamples(engine, options = {}) {
|
|
9233
|
+
const baseUrl = options.baseUrl ?? "";
|
|
9234
|
+
let manifest;
|
|
9235
|
+
try {
|
|
9236
|
+
manifest = await (options.fetchManifest ?? fetchJson)(`${baseUrl}manifest.json`);
|
|
9237
|
+
} catch {
|
|
9238
|
+
return null;
|
|
9239
|
+
}
|
|
9240
|
+
const bank = kitSampleBank(manifest, options);
|
|
9241
|
+
engine.register(bank);
|
|
9242
|
+
if (options.preload && engine.loadSamples) void engine.loadSamples(options.preload).catch(() => void 0);
|
|
9243
|
+
return bank;
|
|
9244
|
+
}
|
|
9245
|
+
var USER_SAMPLES_BANK = "user_samples";
|
|
9246
|
+
var USER_SOUND_PREFIX = "user:";
|
|
9247
|
+
function userSampleBank(manifest, options = {}) {
|
|
9248
|
+
const playing = [];
|
|
9249
|
+
const behindKit = [];
|
|
9250
|
+
const sounds = [];
|
|
9251
|
+
for (const picked of manifest.sounds) {
|
|
9252
|
+
const sound = { ...picked, id: splitTier(picked.id).base };
|
|
9253
|
+
sounds.push({ ...sound, id: `${USER_SOUND_PREFIX}${sound.id}` });
|
|
9254
|
+
if (sound.role === "fallback" && options.kitHas?.(sound.id)) {
|
|
9255
|
+
behindKit.push(sound.id);
|
|
9256
|
+
continue;
|
|
9257
|
+
}
|
|
9258
|
+
sounds.push(sound);
|
|
9259
|
+
playing.push(sound.id);
|
|
9260
|
+
}
|
|
9261
|
+
const bank = sampleBankFromManifest(
|
|
9262
|
+
{ sounds },
|
|
9263
|
+
{
|
|
9264
|
+
id: USER_SAMPLES_BANK,
|
|
9265
|
+
baseUrl: options.baseUrl ?? "",
|
|
9266
|
+
defaults: (sound) => kitSampleDefaults({ id: sound.id.replace(USER_SOUND_PREFIX, ""), category: sound.category })
|
|
9267
|
+
}
|
|
9268
|
+
);
|
|
9269
|
+
return { bank, playing, behindKit };
|
|
9270
|
+
}
|
|
9271
|
+
var fetchManifestJson = async (url2) => {
|
|
9272
|
+
const page = globalThis.location?.href;
|
|
9273
|
+
if (new URL(url2, page ?? "http://localhost/").protocol === "file:") throw new Error(`${url2}: file:// is not fetched`);
|
|
9274
|
+
const response = await fetch(url2);
|
|
9275
|
+
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
9276
|
+
return await response.json();
|
|
9277
|
+
};
|
|
9278
|
+
async function loadUserSamples(engine, options = {}) {
|
|
9279
|
+
const baseUrl = options.baseUrl ?? "./sfx-local/";
|
|
9280
|
+
let manifest;
|
|
9281
|
+
try {
|
|
9282
|
+
manifest = await (options.fetchManifest ?? fetchManifestJson)(`${baseUrl}manifest.json`);
|
|
9283
|
+
} catch {
|
|
9284
|
+
return null;
|
|
9285
|
+
}
|
|
9286
|
+
const kitHas = options.kitHas ?? ((id) => Boolean(engine.registry?.sample(id)));
|
|
9287
|
+
const result2 = userSampleBank(manifest, { baseUrl, kitHas });
|
|
9288
|
+
engine.register(result2.bank);
|
|
9289
|
+
return result2;
|
|
9290
|
+
}
|
|
9097
9291
|
var PT = {
|
|
9098
9292
|
group: "Som",
|
|
9099
9293
|
name: "Painel de som (arquivos e C1\u2013C10)",
|
|
@@ -9101,6 +9295,7 @@ var GameTestRoom = (() => {
|
|
|
9101
9295
|
category: "1 \xB7 Categoria",
|
|
9102
9296
|
sound: "1 \xB7 Som",
|
|
9103
9297
|
play: "1 \xB7 \u25B6 Tocar",
|
|
9298
|
+
play_user: "1 \xB7 \u25B6 Tocar o seu",
|
|
9104
9299
|
material: "2 \xB7 Material",
|
|
9105
9300
|
blow: "2 \xB7 Golpe",
|
|
9106
9301
|
strike: "2 \xB7 \u25B6 Tocar golpe",
|
|
@@ -9122,6 +9317,7 @@ var GameTestRoom = (() => {
|
|
|
9122
9317
|
approve: "5 \xB7 Aprovo (C10)"
|
|
9123
9318
|
},
|
|
9124
9319
|
hints: {
|
|
9320
|
+
play_user: "Toca a sua grava\xE7\xE3o deste som (dos seus pacotes, fora do git), mesmo quando o SDK tem uma melhor e toca na frente.",
|
|
9125
9321
|
sound: "A = arquivo, S = sintetizado, F = faltando. O que tem arquivo toca o arquivo; o resto toca o som atual.",
|
|
9126
9322
|
strike: "Toca impact_<material>_<golpe>: o arquivo se existir, sen\xE3o o som atual daquele material.",
|
|
9127
9323
|
wall: "P\xF5e a parede de casa entre voc\xEA e a fonte: o som fica abafado (C4).",
|
|
@@ -9166,9 +9362,10 @@ var GameTestRoom = (() => {
|
|
|
9166
9362
|
strengths: { light: "leve", medium: "m\xE9dio", heavy: "forte" },
|
|
9167
9363
|
states: { file: "A", synth: "S", missing: "F" },
|
|
9168
9364
|
criteria: { C1: "C1 Sincronia", C2: "C2 Certo p/ a\xE7\xE3o", C3: "C3 Dist\xE2ncia", C4: "C4 Posi\xE7\xE3o", C5: "C5 Varia\xE7\xE3o", C6: "C6 Volume", C7: "C7 Intensidade", C8: "C8 Cauda", C9: "C9 Rajada", C10: "C10 Escuta" },
|
|
9169
|
-
metrics: { chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo" },
|
|
9365
|
+
metrics: { source: "1 \xB7 Fonte do que tocou", chosen: "1 \xB7 Escolhido", matrix: "2 \xB7 Matriz", last: "\xDAltimo tocado", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Prefer\xEAncias", state: "5 \xB7 Medi\xE7\xE3o", count: "1 \xB7 Cat\xE1logo" },
|
|
9170
9366
|
run: { idle: "parada", measuring: "medindo\u2026", done: "pronta", failed: "falhou", recording: "gravando\u2026", recorded: "grava\xE7\xE3o baixada" },
|
|
9171
9367
|
words: { none: "\u2014", hidden: "? (revele)", prefers: "prefere", approved: "aprovado pelo dono" },
|
|
9368
|
+
sources: { sdk: "SDK", user: "seu som", synth: "sintetizado" },
|
|
9172
9369
|
probe: "Fonte do som",
|
|
9173
9370
|
wall: "Parede (oclus\xE3o)",
|
|
9174
9371
|
scenarios: { pipeline: "Arquivo \u2192 decodifica \u2192 toca (round-robin, cauda)", criteria: "Crit\xE9rios C1\u2013C9 no som de calibra\xE7\xE3o", loop: "Loop de arquivo: emenda sem buraco (crossfade)", panel: "Painel: categorias, matriz, A/B e parede" }
|
|
@@ -9181,6 +9378,7 @@ var GameTestRoom = (() => {
|
|
|
9181
9378
|
category: "1 \xB7 Category",
|
|
9182
9379
|
sound: "1 \xB7 Sound",
|
|
9183
9380
|
play: "1 \xB7 \u25B6 Play",
|
|
9381
|
+
play_user: "1 \xB7 \u25B6 Play yours",
|
|
9184
9382
|
material: "2 \xB7 Material",
|
|
9185
9383
|
blow: "2 \xB7 Blow",
|
|
9186
9384
|
strike: "2 \xB7 \u25B6 Play blow",
|
|
@@ -9202,6 +9400,7 @@ var GameTestRoom = (() => {
|
|
|
9202
9400
|
approve: "5 \xB7 Approve (C10)"
|
|
9203
9401
|
},
|
|
9204
9402
|
hints: {
|
|
9403
|
+
play_user: "Plays your own take of this sound (from your packs, kept out of git), even where the SDK has a better one that plays first.",
|
|
9205
9404
|
sound: "A = file, S = synthesized, F = missing. A file plays the file; the rest plays the current sound.",
|
|
9206
9405
|
strike: "Plays impact_<material>_<blow>: the file if there is one, else the current sound of that material.",
|
|
9207
9406
|
wall: "Puts the house wall between you and the source: the sound is muffled (C4).",
|
|
@@ -9236,138 +9435,16 @@ var GameTestRoom = (() => {
|
|
|
9236
9435
|
environments: { indoor: "indoor", outdoor: "outdoor" },
|
|
9237
9436
|
strengths: { light: "light", medium: "medium", heavy: "heavy" },
|
|
9238
9437
|
criteria: { C1: "C1 Sync", C2: "C2 Right sound", C3: "C3 Distance", C4: "C4 Position", C5: "C5 Variation", C6: "C6 Level", C7: "C7 Strength", C8: "C8 Tail", C9: "C9 Burst", C10: "C10 Listening" },
|
|
9239
|
-
metrics: { chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue" },
|
|
9438
|
+
metrics: { source: "1 \xB7 Source of what played", chosen: "1 \xB7 Chosen", matrix: "2 \xB7 Matrix", last: "Last played", ab: "4 \xB7 A \xD7 B", blind: "4 \xB7 X", verdicts: "4 \xB7 Preferences", state: "5 \xB7 Measurement", count: "1 \xB7 Catalogue" },
|
|
9240
9439
|
run: { idle: "idle", measuring: "measuring\u2026", done: "done", failed: "failed", recording: "recording\u2026", recorded: "recording downloaded" },
|
|
9241
9440
|
words: { none: "\u2014", hidden: "? (reveal)", prefers: "prefers", approved: "approved by the owner" },
|
|
9441
|
+
sources: { sdk: "SDK", user: "your sound", synth: "synthesized" },
|
|
9242
9442
|
probe: "Sound source",
|
|
9243
9443
|
wall: "Wall (occlusion)",
|
|
9244
9444
|
scenarios: { pipeline: "File \u2192 decode \u2192 play (round-robin, tail)", criteria: "Criteria C1\u2013C9 on the calibration sound", loop: "File loop: seamless joins (crossfade)", panel: "Panel: categories, matrix, A/B and wall" }
|
|
9245
9445
|
};
|
|
9246
9446
|
|
|
9247
9447
|
// ../game-audio/dist/index.js
|
|
9248
|
-
var SFX_TIERS = { light: 0, medium: 0.34, heavy: 0.67 };
|
|
9249
|
-
function splitTier(id) {
|
|
9250
|
-
const match = /^(.*)_(light|medium|heavy)$/.exec(id);
|
|
9251
|
-
return match ? { base: match[1], tier: match[2] } : { base: id };
|
|
9252
|
-
}
|
|
9253
|
-
var refsOf = (entries2, baseUrl) => (entries2 ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }));
|
|
9254
|
-
function sampleBankFromManifest(manifest, options) {
|
|
9255
|
-
const baseUrl = options.baseUrl ?? "";
|
|
9256
|
-
const samples = [];
|
|
9257
|
-
const tiersOf = /* @__PURE__ */ new Map();
|
|
9258
|
-
for (const sound of manifest.sounds) {
|
|
9259
|
-
const { base, tier } = splitTier(sound.id);
|
|
9260
|
-
if (tier) tiersOf.set(base, [...tiersOf.get(base) ?? [], sound]);
|
|
9261
|
-
}
|
|
9262
|
-
const bases = /* @__PURE__ */ new Map();
|
|
9263
|
-
for (const sound of manifest.sounds) {
|
|
9264
|
-
if (!splitTier(sound.id).tier) bases.set(sound.id, sound);
|
|
9265
|
-
}
|
|
9266
|
-
for (const [base, tiers] of tiersOf) {
|
|
9267
|
-
if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? "", layers: { close: tiers[0]?.layers.close ?? [] } });
|
|
9268
|
-
}
|
|
9269
|
-
for (const sound of bases.values()) {
|
|
9270
|
-
const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound);
|
|
9271
|
-
const close = refsOf(sound.layers.close, baseUrl);
|
|
9272
|
-
if (!numbers || close.length === 0) continue;
|
|
9273
|
-
const tiers = (tiersOf.get(sound.id) ?? []).map((tier) => {
|
|
9274
|
-
const name = splitTier(tier.id).tier;
|
|
9275
|
-
const tierFar = refsOf(tier.layers.far, baseUrl);
|
|
9276
|
-
return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...tierFar.length > 0 ? { far: tierFar } : {} };
|
|
9277
|
-
}).sort((a, b) => a.from - b.from);
|
|
9278
|
-
const far = refsOf(sound.layers.far, baseUrl);
|
|
9279
|
-
const indoor = refsOf(sound.layers.tail_in, baseUrl);
|
|
9280
|
-
const outdoor = refsOf(sound.layers.tail_out, baseUrl);
|
|
9281
|
-
const files = [sound, ...tiersOf.get(sound.id) ?? []].flatMap((entry) => Object.values(entry.layers).flatMap((entries2) => entries2 ?? []));
|
|
9282
|
-
samples.push({
|
|
9283
|
-
id: sound.id,
|
|
9284
|
-
bus: numbers.bus,
|
|
9285
|
-
close,
|
|
9286
|
-
...far.length > 0 ? { far } : {},
|
|
9287
|
-
...tiers.length > 0 ? { tiers } : {},
|
|
9288
|
-
...numbers.crossover ? { crossover: numbers.crossover } : {},
|
|
9289
|
-
...indoor.length > 0 || outdoor.length > 0 ? { tail: { ...indoor.length > 0 ? { indoor } : {}, ...outdoor.length > 0 ? { outdoor } : {}, ...numbers.tailGain === void 0 ? {} : { gain: numbers.tailGain } } } : {},
|
|
9290
|
-
...numbers.pitch === void 0 ? {} : { pitch: numbers.pitch },
|
|
9291
|
-
...numbers.gain === void 0 ? {} : { gain: numbers.gain },
|
|
9292
|
-
...numbers.falloff ? { falloff: numbers.falloff } : {},
|
|
9293
|
-
...numbers.cutoffK === void 0 ? {} : { cutoffK: numbers.cutoffK },
|
|
9294
|
-
...numbers.group ? { group: numbers.group } : {},
|
|
9295
|
-
...numbers.priority === void 0 ? {} : { priority: numbers.priority },
|
|
9296
|
-
...numbers.fallback ? { fallback: numbers.fallback } : {},
|
|
9297
|
-
sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`)
|
|
9298
|
-
});
|
|
9299
|
-
}
|
|
9300
|
-
return { id: options.id, samples };
|
|
9301
|
-
}
|
|
9302
|
-
var KIT_CATEGORY_BUS = {
|
|
9303
|
-
armas: "weapons",
|
|
9304
|
-
impactos: "world",
|
|
9305
|
-
"explosoes-fogo": "world",
|
|
9306
|
-
personagem: "world",
|
|
9307
|
-
veiculos: "world",
|
|
9308
|
-
"itens-portas": "world",
|
|
9309
|
-
ambiente: "ambience"
|
|
9310
|
-
};
|
|
9311
|
-
var VOICE_IDS = /^(player_(hurt|death|effort|breath)|scream|zombie_)/;
|
|
9312
|
-
var KIT_SAMPLE_ALIASES = {
|
|
9313
|
-
// a house door: the latch giving, the hinge, the leaf meeting the frame, a locked one shaken; a drawer on its runners
|
|
9314
|
-
latch: "metal_latch",
|
|
9315
|
-
creak_wood: "door_creak",
|
|
9316
|
-
shut_wood: "door_wood_shut",
|
|
9317
|
-
rattle: "door_locked_rattle",
|
|
9318
|
-
// a drawer stays on its recipe: the recorded runs (1 to 1.9 s) outlast a drawer's pull
|
|
9319
|
-
// an item taken in the hand (game-destruction-three grab_* keys)
|
|
9320
|
-
grab_hard: "item_pickup_generic",
|
|
9321
|
-
grab_soft: "item_pickup_leather"
|
|
9322
|
-
};
|
|
9323
|
-
function kitSampleDefaults(sound) {
|
|
9324
|
-
const bus = VOICE_IDS.test(sound.id) ? "voices" : KIT_CATEGORY_BUS[sound.category];
|
|
9325
|
-
if (!bus) return void 0;
|
|
9326
|
-
return { bus, pitch: sound.category === "ambiente" || /_loop/.test(sound.id) ? 0 : 0.04 };
|
|
9327
|
-
}
|
|
9328
|
-
function withAliases(manifest, aliases) {
|
|
9329
|
-
const byId = new Map(manifest.sounds.map((sound) => [sound.id, sound]));
|
|
9330
|
-
const extra = [];
|
|
9331
|
-
for (const [alias, target] of Object.entries(aliases)) {
|
|
9332
|
-
const sound = byId.get(target);
|
|
9333
|
-
if (sound && !byId.has(alias)) extra.push({ ...sound, id: alias });
|
|
9334
|
-
}
|
|
9335
|
-
return { ...manifest, sounds: [...manifest.sounds, ...extra] };
|
|
9336
|
-
}
|
|
9337
|
-
function kitSampleBank(manifest, options = {}) {
|
|
9338
|
-
return sampleBankFromManifest(withAliases(manifest, options.aliases ?? KIT_SAMPLE_ALIASES), {
|
|
9339
|
-
id: options.id ?? "kit_samples",
|
|
9340
|
-
baseUrl: options.baseUrl ?? "",
|
|
9341
|
-
defaults: kitSampleDefaults
|
|
9342
|
-
});
|
|
9343
|
-
}
|
|
9344
|
-
var isFileUrl = (url2) => {
|
|
9345
|
-
const page = globalThis.location?.href;
|
|
9346
|
-
try {
|
|
9347
|
-
return new URL(url2, page).protocol === "file:";
|
|
9348
|
-
} catch {
|
|
9349
|
-
return false;
|
|
9350
|
-
}
|
|
9351
|
-
};
|
|
9352
|
-
var fetchJson = async (url2) => {
|
|
9353
|
-
if (isFileUrl(url2)) throw new Error(`${url2}: file:// is not fetched`);
|
|
9354
|
-
const response = await fetch(url2);
|
|
9355
|
-
if (!response.ok) throw new Error(`${url2}: ${response.status}`);
|
|
9356
|
-
return await response.json();
|
|
9357
|
-
};
|
|
9358
|
-
async function loadKitSamples(engine, options = {}) {
|
|
9359
|
-
const baseUrl = options.baseUrl ?? "";
|
|
9360
|
-
let manifest;
|
|
9361
|
-
try {
|
|
9362
|
-
manifest = await (options.fetchManifest ?? fetchJson)(`${baseUrl}manifest.json`);
|
|
9363
|
-
} catch {
|
|
9364
|
-
return null;
|
|
9365
|
-
}
|
|
9366
|
-
const bank = kitSampleBank(manifest, options);
|
|
9367
|
-
engine.register(bank);
|
|
9368
|
-
if (options.preload && engine.loadSamples) void engine.loadSamples(options.preload).catch(() => void 0);
|
|
9369
|
-
return bank;
|
|
9370
|
-
}
|
|
9371
9448
|
var ATTACK = 2e-3;
|
|
9372
9449
|
function lengthOf(d, attack) {
|
|
9373
9450
|
if (typeof d === "number") return attack + d;
|
|
@@ -22848,7 +22925,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
22848
22925
|
var rendererCount = 0;
|
|
22849
22926
|
var COLLAPSE_CLOUD_KG = 1e3;
|
|
22850
22927
|
var CHIP_DECAL_EDGE = 0.05;
|
|
22851
|
-
var OPAQUE_CRACK = 0.1;
|
|
22852
22928
|
var WOOD_RIM = 1.5;
|
|
22853
22929
|
var IMPACT_TAGS = ["metal", "glass", "wood"];
|
|
22854
22930
|
var GLOW_FROM_C = 430;
|
|
@@ -23772,14 +23848,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
23772
23848
|
const pv = b?.parts.get(ev.part);
|
|
23773
23849
|
if (!b || !pv) return;
|
|
23774
23850
|
const def = this.world.materials.get(pv.material);
|
|
23775
|
-
|
|
23776
|
-
|
|
23777
|
-
|
|
23778
|
-
const
|
|
23779
|
-
|
|
23780
|
-
const color = glass2 ? 15267071 : new this.THREE.Color(own).multiplyScalar(0.45).getHex();
|
|
23781
|
-
const length3 = glass2 ? ev.crack.length : Math.min(ev.crack.length, OPAQUE_CRACK);
|
|
23782
|
-
this.visuals.addCrack(mv, wp, this.worldDir(b, ev.crack.normal), ev.crack.rays, length3, color, hashNumbers(ev.time, ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]));
|
|
23851
|
+
if (def?.visual?.transparent) {
|
|
23852
|
+
const wp = new this.THREE.Vector3(ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]);
|
|
23853
|
+
const mv = this.nearestMesh(pv, wp);
|
|
23854
|
+
const seed = hashNumbers(ev.time, ev.worldPoint[0], ev.worldPoint[1], ev.worldPoint[2]);
|
|
23855
|
+
if (mv) this.visuals.addCrack(mv, wp, this.worldDir(b, ev.crack.normal), ev.crack.rays, ev.crack.length, 15267071, seed);
|
|
23783
23856
|
}
|
|
23784
23857
|
this.impactSound(pv.material, ev.worldPoint, 0.5, ev.blow);
|
|
23785
23858
|
}
|
|
@@ -53203,7 +53276,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53203
53276
|
const audio = options.audio === false ? null : options.audio ?? createAudioEngine({ deferredStart: {} });
|
|
53204
53277
|
const destructionSound = audio ? createDestructionSound(audio) : null;
|
|
53205
53278
|
if (audio && options.samplesBaseUrl !== null) {
|
|
53206
|
-
void loadKitSamples(audio, { baseUrl: options.samplesBaseUrl ?? "./sfx/" }).then((bank) => {
|
|
53279
|
+
void loadKitSamples(audio, { baseUrl: options.samplesBaseUrl ?? "./sfx/" }).then(async (bank) => {
|
|
53280
|
+
if (options.userSamplesBaseUrl !== null) {
|
|
53281
|
+
const own = await loadUserSamples(audio, { baseUrl: options.userSamplesBaseUrl ?? "./sfx-local/" });
|
|
53282
|
+
if (own) log.add({ channel: "event", type: "user_sounds", text: `sons do dono: ${own.playing.length} tocando, ${own.behindKit.length} atr\xE1s do SDK`, data: { playing: own.playing, behindKit: own.behindKit } });
|
|
53283
|
+
}
|
|
53207
53284
|
if (!bank || typeof window === "undefined") return;
|
|
53208
53285
|
const preload = () => {
|
|
53209
53286
|
window.removeEventListener("keydown", preload, true);
|