@novely/core 0.49.0 → 0.51.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 +100 -23
- package/dist/index.js +542 -483
- package/dist/index.js.map +1 -1
- package/package.json +10 -13
- package/dist/index.global.js +0 -2867
- package/dist/index.global.js.map +0 -1
package/dist/index.global.js
DELETED
|
@@ -1,2867 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var Novely = (() => {
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
-
|
|
21
|
-
// src/index.ts
|
|
22
|
-
var src_exports = {};
|
|
23
|
-
__export(src_exports, {
|
|
24
|
-
EN: () => EN,
|
|
25
|
-
JP: () => JP,
|
|
26
|
-
KK: () => KK,
|
|
27
|
-
RU: () => RU,
|
|
28
|
-
asset: () => asset,
|
|
29
|
-
extendAction: () => extendAction,
|
|
30
|
-
localStorageStorage: () => localStorageStorage,
|
|
31
|
-
novely: () => novely
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// ../../node_modules/.pnpm/dequal@2.0.3/node_modules/dequal/lite/index.mjs
|
|
35
|
-
var has = Object.prototype.hasOwnProperty;
|
|
36
|
-
function dequal(foo, bar) {
|
|
37
|
-
var ctor, len;
|
|
38
|
-
if (foo === bar) return true;
|
|
39
|
-
if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
|
|
40
|
-
if (ctor === Date) return foo.getTime() === bar.getTime();
|
|
41
|
-
if (ctor === RegExp) return foo.toString() === bar.toString();
|
|
42
|
-
if (ctor === Array) {
|
|
43
|
-
if ((len = foo.length) === bar.length) {
|
|
44
|
-
while (len-- && dequal(foo[len], bar[len])) ;
|
|
45
|
-
}
|
|
46
|
-
return len === -1;
|
|
47
|
-
}
|
|
48
|
-
if (!ctor || typeof foo === "object") {
|
|
49
|
-
len = 0;
|
|
50
|
-
for (ctor in foo) {
|
|
51
|
-
if (has.call(foo, ctor) && ++len && !has.call(bar, ctor)) return false;
|
|
52
|
-
if (!(ctor in bar) || !dequal(foo[ctor], bar[ctor])) return false;
|
|
53
|
-
}
|
|
54
|
-
return Object.keys(bar).length === len;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return foo !== foo && bar !== bar;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ../../node_modules/.pnpm/es-toolkit@1.23.0/node_modules/es-toolkit/dist/function/debounce.mjs
|
|
61
|
-
function debounce(func, debounceMs, { signal, edges } = {}) {
|
|
62
|
-
let pendingThis = void 0;
|
|
63
|
-
let pendingArgs = null;
|
|
64
|
-
const leading = edges != null && edges.includes("leading");
|
|
65
|
-
const trailing = edges == null || edges.includes("trailing");
|
|
66
|
-
const invoke = () => {
|
|
67
|
-
if (pendingArgs !== null) {
|
|
68
|
-
func.apply(pendingThis, pendingArgs);
|
|
69
|
-
pendingThis = void 0;
|
|
70
|
-
pendingArgs = null;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
const onTimerEnd = () => {
|
|
74
|
-
if (trailing) {
|
|
75
|
-
invoke();
|
|
76
|
-
}
|
|
77
|
-
cancel();
|
|
78
|
-
};
|
|
79
|
-
let timeoutId = null;
|
|
80
|
-
const schedule = () => {
|
|
81
|
-
if (timeoutId != null) {
|
|
82
|
-
clearTimeout(timeoutId);
|
|
83
|
-
}
|
|
84
|
-
timeoutId = setTimeout(() => {
|
|
85
|
-
timeoutId = null;
|
|
86
|
-
onTimerEnd();
|
|
87
|
-
}, debounceMs);
|
|
88
|
-
};
|
|
89
|
-
const cancelTimer = () => {
|
|
90
|
-
if (timeoutId !== null) {
|
|
91
|
-
clearTimeout(timeoutId);
|
|
92
|
-
timeoutId = null;
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
const cancel = () => {
|
|
96
|
-
cancelTimer();
|
|
97
|
-
pendingThis = void 0;
|
|
98
|
-
pendingArgs = null;
|
|
99
|
-
};
|
|
100
|
-
const flush = () => {
|
|
101
|
-
cancelTimer();
|
|
102
|
-
invoke();
|
|
103
|
-
};
|
|
104
|
-
const debounced = function(...args) {
|
|
105
|
-
if (signal?.aborted) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
pendingThis = this;
|
|
109
|
-
pendingArgs = args;
|
|
110
|
-
const isFirstCall = timeoutId == null;
|
|
111
|
-
schedule();
|
|
112
|
-
if (leading && isFirstCall) {
|
|
113
|
-
invoke();
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
debounced.schedule = schedule;
|
|
117
|
-
debounced.cancel = cancel;
|
|
118
|
-
debounced.flush = flush;
|
|
119
|
-
signal?.addEventListener("abort", cancel, { once: true });
|
|
120
|
-
return debounced;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ../../node_modules/.pnpm/es-toolkit@1.23.0/node_modules/es-toolkit/dist/function/once.mjs
|
|
124
|
-
function once(func) {
|
|
125
|
-
let called = false;
|
|
126
|
-
let cache;
|
|
127
|
-
return function() {
|
|
128
|
-
if (called) {
|
|
129
|
-
return cache;
|
|
130
|
-
}
|
|
131
|
-
const result = func();
|
|
132
|
-
called = true;
|
|
133
|
-
cache = result;
|
|
134
|
-
return result;
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ../../node_modules/.pnpm/es-toolkit@1.23.0/node_modules/es-toolkit/dist/function/throttle.mjs
|
|
139
|
-
function throttle(func, throttleMs, { signal, edges = ["leading", "trailing"] } = {}) {
|
|
140
|
-
let pendingAt = null;
|
|
141
|
-
const debounced = debounce(func, throttleMs, { signal, edges });
|
|
142
|
-
const throttled = function(...args) {
|
|
143
|
-
if (pendingAt == null) {
|
|
144
|
-
pendingAt = Date.now();
|
|
145
|
-
} else {
|
|
146
|
-
if (Date.now() - pendingAt >= throttleMs) {
|
|
147
|
-
pendingAt = Date.now();
|
|
148
|
-
debounced.cancel();
|
|
149
|
-
debounced(...args);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
debounced(...args);
|
|
153
|
-
};
|
|
154
|
-
throttled.cancel = debounced.cancel;
|
|
155
|
-
throttled.flush = debounced.flush;
|
|
156
|
-
return throttled;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// ../../node_modules/.pnpm/es-toolkit@1.23.0/node_modules/es-toolkit/dist/function/memoize.mjs
|
|
160
|
-
function memoize(fn, options = {}) {
|
|
161
|
-
const { cache = /* @__PURE__ */ new Map(), getCacheKey } = options;
|
|
162
|
-
const memoizedFn = function(arg) {
|
|
163
|
-
const key = getCacheKey ? getCacheKey(arg) : arg;
|
|
164
|
-
if (cache.has(key)) {
|
|
165
|
-
return cache.get(key);
|
|
166
|
-
}
|
|
167
|
-
const result = fn.call(this, arg);
|
|
168
|
-
cache.set(key, result);
|
|
169
|
-
return result;
|
|
170
|
-
};
|
|
171
|
-
memoizedFn.cache = cache;
|
|
172
|
-
return memoizedFn;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ../../node_modules/.pnpm/es-toolkit@1.23.0/node_modules/es-toolkit/dist/predicate/isPlainObject.mjs
|
|
176
|
-
function isPlainObject(value) {
|
|
177
|
-
if (typeof value !== "object") {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
if (value == null) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
if (Object.getPrototypeOf(value) === null) {
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
if (value.toString() !== "[object Object]") {
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
let proto = value;
|
|
190
|
-
while (Object.getPrototypeOf(proto) !== null) {
|
|
191
|
-
proto = Object.getPrototypeOf(proto);
|
|
192
|
-
}
|
|
193
|
-
return Object.getPrototypeOf(value) === proto;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// ../../node_modules/.pnpm/es-toolkit@1.23.0/node_modules/es-toolkit/dist/object/merge.mjs
|
|
197
|
-
function merge(target, source) {
|
|
198
|
-
const sourceKeys = Object.keys(source);
|
|
199
|
-
for (let i = 0; i < sourceKeys.length; i++) {
|
|
200
|
-
const key = sourceKeys[i];
|
|
201
|
-
const sourceValue = source[key];
|
|
202
|
-
const targetValue = target[key];
|
|
203
|
-
if (Array.isArray(sourceValue)) {
|
|
204
|
-
if (Array.isArray(targetValue)) {
|
|
205
|
-
target[key] = merge(targetValue, sourceValue);
|
|
206
|
-
} else {
|
|
207
|
-
target[key] = merge([], sourceValue);
|
|
208
|
-
}
|
|
209
|
-
} else if (isPlainObject(sourceValue)) {
|
|
210
|
-
if (isPlainObject(targetValue)) {
|
|
211
|
-
target[key] = merge(targetValue, sourceValue);
|
|
212
|
-
} else {
|
|
213
|
-
target[key] = merge({}, sourceValue);
|
|
214
|
-
}
|
|
215
|
-
} else if (targetValue === void 0 || sourceValue !== void 0) {
|
|
216
|
-
target[key] = sourceValue;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return target;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// ../../node_modules/.pnpm/esm-env@1.0.0/node_modules/esm-env/prod-ssr.js
|
|
223
|
-
var DEV = false;
|
|
224
|
-
|
|
225
|
-
// ../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/full/index.mjs
|
|
226
|
-
function set(obj, key, val) {
|
|
227
|
-
if (typeof val.value === "object") val.value = klona(val.value);
|
|
228
|
-
if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") {
|
|
229
|
-
Object.defineProperty(obj, key, val);
|
|
230
|
-
} else obj[key] = val.value;
|
|
231
|
-
}
|
|
232
|
-
function klona(x) {
|
|
233
|
-
if (typeof x !== "object") return x;
|
|
234
|
-
var i = 0, k, list, tmp, str = Object.prototype.toString.call(x);
|
|
235
|
-
if (str === "[object Object]") {
|
|
236
|
-
tmp = Object.create(x.__proto__ || null);
|
|
237
|
-
} else if (str === "[object Array]") {
|
|
238
|
-
tmp = Array(x.length);
|
|
239
|
-
} else if (str === "[object Set]") {
|
|
240
|
-
tmp = /* @__PURE__ */ new Set();
|
|
241
|
-
x.forEach(function(val) {
|
|
242
|
-
tmp.add(klona(val));
|
|
243
|
-
});
|
|
244
|
-
} else if (str === "[object Map]") {
|
|
245
|
-
tmp = /* @__PURE__ */ new Map();
|
|
246
|
-
x.forEach(function(val, key) {
|
|
247
|
-
tmp.set(klona(key), klona(val));
|
|
248
|
-
});
|
|
249
|
-
} else if (str === "[object Date]") {
|
|
250
|
-
tmp = /* @__PURE__ */ new Date(+x);
|
|
251
|
-
} else if (str === "[object RegExp]") {
|
|
252
|
-
tmp = new RegExp(x.source, x.flags);
|
|
253
|
-
} else if (str === "[object DataView]") {
|
|
254
|
-
tmp = new x.constructor(klona(x.buffer));
|
|
255
|
-
} else if (str === "[object ArrayBuffer]") {
|
|
256
|
-
tmp = x.slice(0);
|
|
257
|
-
} else if (str.slice(-6) === "Array]") {
|
|
258
|
-
tmp = new x.constructor(x);
|
|
259
|
-
}
|
|
260
|
-
if (tmp) {
|
|
261
|
-
for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) {
|
|
262
|
-
set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
|
|
263
|
-
}
|
|
264
|
-
for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
|
|
265
|
-
if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue;
|
|
266
|
-
set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return tmp || x;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// ../../node_modules/.pnpm/yocto-queue@1.1.1/node_modules/yocto-queue/index.js
|
|
273
|
-
var Node = class {
|
|
274
|
-
value;
|
|
275
|
-
next;
|
|
276
|
-
constructor(value) {
|
|
277
|
-
this.value = value;
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
var Queue = class {
|
|
281
|
-
#head;
|
|
282
|
-
#tail;
|
|
283
|
-
#size;
|
|
284
|
-
constructor() {
|
|
285
|
-
this.clear();
|
|
286
|
-
}
|
|
287
|
-
enqueue(value) {
|
|
288
|
-
const node = new Node(value);
|
|
289
|
-
if (this.#head) {
|
|
290
|
-
this.#tail.next = node;
|
|
291
|
-
this.#tail = node;
|
|
292
|
-
} else {
|
|
293
|
-
this.#head = node;
|
|
294
|
-
this.#tail = node;
|
|
295
|
-
}
|
|
296
|
-
this.#size++;
|
|
297
|
-
}
|
|
298
|
-
dequeue() {
|
|
299
|
-
const current = this.#head;
|
|
300
|
-
if (!current) {
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
this.#head = this.#head.next;
|
|
304
|
-
this.#size--;
|
|
305
|
-
return current.value;
|
|
306
|
-
}
|
|
307
|
-
peek() {
|
|
308
|
-
if (!this.#head) {
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
return this.#head.value;
|
|
312
|
-
}
|
|
313
|
-
clear() {
|
|
314
|
-
this.#head = void 0;
|
|
315
|
-
this.#tail = void 0;
|
|
316
|
-
this.#size = 0;
|
|
317
|
-
}
|
|
318
|
-
get size() {
|
|
319
|
-
return this.#size;
|
|
320
|
-
}
|
|
321
|
-
*[Symbol.iterator]() {
|
|
322
|
-
let current = this.#head;
|
|
323
|
-
while (current) {
|
|
324
|
-
yield current.value;
|
|
325
|
-
current = current.next;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
// ../../node_modules/.pnpm/p-limit@6.1.0/node_modules/p-limit/index.js
|
|
331
|
-
function pLimit(concurrency) {
|
|
332
|
-
validateConcurrency(concurrency);
|
|
333
|
-
const queue = new Queue();
|
|
334
|
-
let activeCount = 0;
|
|
335
|
-
const resumeNext = () => {
|
|
336
|
-
if (activeCount < concurrency && queue.size > 0) {
|
|
337
|
-
queue.dequeue()();
|
|
338
|
-
activeCount++;
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
const next = () => {
|
|
342
|
-
activeCount--;
|
|
343
|
-
resumeNext();
|
|
344
|
-
};
|
|
345
|
-
const run = async (function_, resolve, arguments_) => {
|
|
346
|
-
const result = (async () => function_(...arguments_))();
|
|
347
|
-
resolve(result);
|
|
348
|
-
try {
|
|
349
|
-
await result;
|
|
350
|
-
} catch {
|
|
351
|
-
}
|
|
352
|
-
next();
|
|
353
|
-
};
|
|
354
|
-
const enqueue = (function_, resolve, arguments_) => {
|
|
355
|
-
new Promise((internalResolve) => {
|
|
356
|
-
queue.enqueue(internalResolve);
|
|
357
|
-
}).then(
|
|
358
|
-
run.bind(void 0, function_, resolve, arguments_)
|
|
359
|
-
);
|
|
360
|
-
(async () => {
|
|
361
|
-
await Promise.resolve();
|
|
362
|
-
if (activeCount < concurrency) {
|
|
363
|
-
resumeNext();
|
|
364
|
-
}
|
|
365
|
-
})();
|
|
366
|
-
};
|
|
367
|
-
const generator = (function_, ...arguments_) => new Promise((resolve) => {
|
|
368
|
-
enqueue(function_, resolve, arguments_);
|
|
369
|
-
});
|
|
370
|
-
Object.defineProperties(generator, {
|
|
371
|
-
activeCount: {
|
|
372
|
-
get: () => activeCount
|
|
373
|
-
},
|
|
374
|
-
pendingCount: {
|
|
375
|
-
get: () => queue.size
|
|
376
|
-
},
|
|
377
|
-
clearQueue: {
|
|
378
|
-
value() {
|
|
379
|
-
queue.clear();
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
concurrency: {
|
|
383
|
-
get: () => concurrency,
|
|
384
|
-
set(newConcurrency) {
|
|
385
|
-
validateConcurrency(newConcurrency);
|
|
386
|
-
concurrency = newConcurrency;
|
|
387
|
-
queueMicrotask(() => {
|
|
388
|
-
while (activeCount < concurrency && queue.size > 0) {
|
|
389
|
-
resumeNext();
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
return generator;
|
|
396
|
-
}
|
|
397
|
-
function validateConcurrency(concurrency) {
|
|
398
|
-
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
|
|
399
|
-
throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// src/constants.ts
|
|
404
|
-
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
405
|
-
var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
|
|
406
|
-
var BLOCK_STATEMENTS = /* @__PURE__ */ new Set(["choice", "condition", "block"]);
|
|
407
|
-
var AUDIO_ACTIONS = /* @__PURE__ */ new Set(["playMusic", "stopMusic", "playSound", "stopSound", "voice", "stopVoice"]);
|
|
408
|
-
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
409
|
-
var DEFAULT_TYPEWRITER_SPEED = "Medium";
|
|
410
|
-
var HOWLER_SUPPORTED_FILE_FORMATS = /* @__PURE__ */ new Set([
|
|
411
|
-
"mp3",
|
|
412
|
-
"mpeg",
|
|
413
|
-
"opus",
|
|
414
|
-
"ogg",
|
|
415
|
-
"oga",
|
|
416
|
-
"wav",
|
|
417
|
-
"aac",
|
|
418
|
-
"caf",
|
|
419
|
-
"m4a",
|
|
420
|
-
"m4b",
|
|
421
|
-
"mp4",
|
|
422
|
-
"weba",
|
|
423
|
-
"webm",
|
|
424
|
-
"dolby",
|
|
425
|
-
"flac"
|
|
426
|
-
]);
|
|
427
|
-
var SUPPORTED_IMAGE_FILE_FORMATS = /* @__PURE__ */ new Set([
|
|
428
|
-
"apng",
|
|
429
|
-
"avif",
|
|
430
|
-
"gif",
|
|
431
|
-
"jpg",
|
|
432
|
-
"jpeg",
|
|
433
|
-
"jfif",
|
|
434
|
-
"pjpeg",
|
|
435
|
-
"pjp",
|
|
436
|
-
"png",
|
|
437
|
-
"svg",
|
|
438
|
-
"webp",
|
|
439
|
-
"bmp"
|
|
440
|
-
]);
|
|
441
|
-
var MAIN_CONTEXT_KEY = "$MAIN";
|
|
442
|
-
|
|
443
|
-
// src/utilities/assertions.ts
|
|
444
|
-
var isNumber = (val) => {
|
|
445
|
-
return typeof val === "number";
|
|
446
|
-
};
|
|
447
|
-
var isNull = (val) => {
|
|
448
|
-
return val === null;
|
|
449
|
-
};
|
|
450
|
-
var isString = (val) => {
|
|
451
|
-
return typeof val === "string";
|
|
452
|
-
};
|
|
453
|
-
var isFunction = (val) => {
|
|
454
|
-
return typeof val === "function";
|
|
455
|
-
};
|
|
456
|
-
var isPromise = (val) => {
|
|
457
|
-
return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
|
|
458
|
-
};
|
|
459
|
-
var isEmpty = (val) => {
|
|
460
|
-
return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
|
|
461
|
-
};
|
|
462
|
-
var isCSSImageURL = (url) => {
|
|
463
|
-
const startsWith = String.prototype.startsWith.bind(url);
|
|
464
|
-
return startsWith("http") || startsWith("/") || startsWith(".") || startsWith("data");
|
|
465
|
-
};
|
|
466
|
-
var isUserRequiredAction = ([action, ...meta]) => {
|
|
467
|
-
return Boolean(action === "custom" && meta[0] && meta[0].requireUserAction);
|
|
468
|
-
};
|
|
469
|
-
var isBlockStatement = (statement) => {
|
|
470
|
-
return BLOCK_STATEMENTS.has(statement);
|
|
471
|
-
};
|
|
472
|
-
var isBlockExitStatement = (statement) => {
|
|
473
|
-
return BLOCK_EXIT_STATEMENTS.has(statement);
|
|
474
|
-
};
|
|
475
|
-
var isSkippedDuringRestore = (item) => {
|
|
476
|
-
return SKIPPED_DURING_RESTORE.has(item);
|
|
477
|
-
};
|
|
478
|
-
var isAudioAction = (action) => {
|
|
479
|
-
return AUDIO_ACTIONS.has(action);
|
|
480
|
-
};
|
|
481
|
-
var isAction = (element) => {
|
|
482
|
-
return Array.isArray(element) && isString(element[0]);
|
|
483
|
-
};
|
|
484
|
-
var isImageAsset = (asset2) => {
|
|
485
|
-
return isString(asset2) && isCSSImageURL(asset2);
|
|
486
|
-
};
|
|
487
|
-
var isBlockingAction = (action) => {
|
|
488
|
-
return isUserRequiredAction(action) || isSkippedDuringRestore(action[0]) && action[0] !== "vibrate";
|
|
489
|
-
};
|
|
490
|
-
var isAsset = (suspect) => {
|
|
491
|
-
return suspect !== null && typeof suspect === "object" && "source" in suspect && "type" in suspect;
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
// src/utilities/match-action.ts
|
|
495
|
-
var matchAction = (callbacks, values) => {
|
|
496
|
-
const { getContext, onBeforeActionCall, push, forward } = callbacks;
|
|
497
|
-
const match = (action, props, { ctx, data }) => {
|
|
498
|
-
const context = typeof ctx === "string" ? getContext(ctx) : ctx;
|
|
499
|
-
onBeforeActionCall({
|
|
500
|
-
action,
|
|
501
|
-
props,
|
|
502
|
-
ctx: context
|
|
503
|
-
});
|
|
504
|
-
return values[action](
|
|
505
|
-
{
|
|
506
|
-
ctx: context,
|
|
507
|
-
data,
|
|
508
|
-
push() {
|
|
509
|
-
if (context.meta.preview) return;
|
|
510
|
-
push(context);
|
|
511
|
-
},
|
|
512
|
-
forward() {
|
|
513
|
-
if (context.meta.preview) return;
|
|
514
|
-
forward(context);
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
props
|
|
518
|
-
);
|
|
519
|
-
};
|
|
520
|
-
return {
|
|
521
|
-
match,
|
|
522
|
-
nativeActions: Object.keys(values)
|
|
523
|
-
};
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
// src/utilities/ungrupped.ts
|
|
527
|
-
var getLanguage = (languages) => {
|
|
528
|
-
let { language } = navigator;
|
|
529
|
-
if (languages.includes(language)) {
|
|
530
|
-
return language;
|
|
531
|
-
} else if (languages.includes(language = language.slice(0, 2))) {
|
|
532
|
-
return language;
|
|
533
|
-
} else if (language = languages.find((value) => navigator.languages.includes(value))) {
|
|
534
|
-
return language;
|
|
535
|
-
}
|
|
536
|
-
return languages[0];
|
|
537
|
-
};
|
|
538
|
-
var noop = () => {
|
|
539
|
-
};
|
|
540
|
-
var mapSet = (set2, fn) => {
|
|
541
|
-
return [...set2].map(fn);
|
|
542
|
-
};
|
|
543
|
-
var capitalize = (str) => {
|
|
544
|
-
return str[0].toUpperCase() + str.slice(1);
|
|
545
|
-
};
|
|
546
|
-
var getIntlLanguageDisplayName = memoize((lang) => {
|
|
547
|
-
try {
|
|
548
|
-
const intl = new Intl.DisplayNames([lang], {
|
|
549
|
-
type: "language"
|
|
550
|
-
});
|
|
551
|
-
return intl.of(lang) || lang;
|
|
552
|
-
} catch {
|
|
553
|
-
return lang;
|
|
554
|
-
}
|
|
555
|
-
});
|
|
556
|
-
var unwrapAsset = (asset2) => {
|
|
557
|
-
return isAsset(asset2) ? asset2.source : asset2;
|
|
558
|
-
};
|
|
559
|
-
var handleAudioAsset = (asset2) => {
|
|
560
|
-
if (DEV && isAsset(asset2) && asset2.type !== "audio") {
|
|
561
|
-
throw new Error("Attempt to use non-audio asset in audio action", { cause: asset2 });
|
|
562
|
-
}
|
|
563
|
-
return unwrapAsset(asset2);
|
|
564
|
-
};
|
|
565
|
-
var handleImageAsset = (asset2) => {
|
|
566
|
-
if (DEV && isAsset(asset2) && asset2.type !== "image") {
|
|
567
|
-
throw new Error("Attempt to use non-image asset in action that requires image assets", { cause: asset2 });
|
|
568
|
-
}
|
|
569
|
-
return unwrapAsset(asset2);
|
|
570
|
-
};
|
|
571
|
-
var getCharactersData = (characters) => {
|
|
572
|
-
const entries = Object.entries(characters);
|
|
573
|
-
const mapped = entries.map(([key, value]) => [key, { name: value.name, emotions: Object.keys(value.emotions) }]);
|
|
574
|
-
return Object.fromEntries(mapped);
|
|
575
|
-
};
|
|
576
|
-
var toArray = (target) => {
|
|
577
|
-
return Array.isArray(target) ? target : [target];
|
|
578
|
-
};
|
|
579
|
-
var getLanguageFromStore = (store2) => {
|
|
580
|
-
return store2.get().meta[0];
|
|
581
|
-
};
|
|
582
|
-
var getVolumeFromStore = (store2) => {
|
|
583
|
-
const { meta } = store2.get();
|
|
584
|
-
return {
|
|
585
|
-
music: meta[2],
|
|
586
|
-
sound: meta[3],
|
|
587
|
-
voice: meta[4]
|
|
588
|
-
};
|
|
589
|
-
};
|
|
590
|
-
|
|
591
|
-
// src/utilities/actions-processing.ts
|
|
592
|
-
var isExitImpossible = (path) => {
|
|
593
|
-
const blockStatements = path.filter(([item]) => isBlockStatement(item));
|
|
594
|
-
const blockExitStatements = path.filter(([item]) => isBlockExitStatement(item));
|
|
595
|
-
if (blockStatements.length === 0 && blockExitStatements.length === 0) {
|
|
596
|
-
return true;
|
|
597
|
-
}
|
|
598
|
-
if (blockStatements.length > blockExitStatements.length) {
|
|
599
|
-
return false;
|
|
600
|
-
}
|
|
601
|
-
return !blockExitStatements.every(([name], i) => name && name.startsWith(blockStatements[i][0]));
|
|
602
|
-
};
|
|
603
|
-
var createReferFunction = ({ story, onUnknownSceneHit }) => {
|
|
604
|
-
const refer = async (path) => {
|
|
605
|
-
const { promise: ready, resolve: setReady } = Promise.withResolvers();
|
|
606
|
-
let current = story;
|
|
607
|
-
let precurrent = story;
|
|
608
|
-
const blocks = [];
|
|
609
|
-
const refer2 = async () => {
|
|
610
|
-
for (const [type, val] of path) {
|
|
611
|
-
if (type === "jump") {
|
|
612
|
-
if (!current[val]) {
|
|
613
|
-
setReady(true);
|
|
614
|
-
await onUnknownSceneHit(val);
|
|
615
|
-
}
|
|
616
|
-
if (DEV && !story[val]) {
|
|
617
|
-
throw new Error(`Attempt to jump to unknown scene "${val}"`);
|
|
618
|
-
}
|
|
619
|
-
if (DEV && story[val].length === 0) {
|
|
620
|
-
throw new Error(`Attempt to jump to empty scene "${val}"`);
|
|
621
|
-
}
|
|
622
|
-
precurrent = story;
|
|
623
|
-
current = current[val];
|
|
624
|
-
} else if (type === null) {
|
|
625
|
-
precurrent = current;
|
|
626
|
-
current = current[val];
|
|
627
|
-
} else if (type === "choice") {
|
|
628
|
-
blocks.push(precurrent);
|
|
629
|
-
current = current[val + 1][1];
|
|
630
|
-
} else if (type === "condition") {
|
|
631
|
-
blocks.push(precurrent);
|
|
632
|
-
current = current[2][val];
|
|
633
|
-
} else if (type === "block") {
|
|
634
|
-
blocks.push(precurrent);
|
|
635
|
-
current = story[val];
|
|
636
|
-
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
637
|
-
current = blocks.pop();
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
setReady(false);
|
|
641
|
-
return current;
|
|
642
|
-
};
|
|
643
|
-
const value = refer2();
|
|
644
|
-
const found = await ready;
|
|
645
|
-
return {
|
|
646
|
-
found,
|
|
647
|
-
value
|
|
648
|
-
};
|
|
649
|
-
};
|
|
650
|
-
const referGuarded = async (path) => {
|
|
651
|
-
return await (await refer(path)).value;
|
|
652
|
-
};
|
|
653
|
-
return {
|
|
654
|
-
refer,
|
|
655
|
-
referGuarded
|
|
656
|
-
};
|
|
657
|
-
};
|
|
658
|
-
var exitPath = async ({ path, refer, onExitImpossible }) => {
|
|
659
|
-
const last = path.at(-1);
|
|
660
|
-
const ignore = [];
|
|
661
|
-
let wasExitImpossible = false;
|
|
662
|
-
if (!isAction(await refer(path))) {
|
|
663
|
-
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
664
|
-
last[1]--;
|
|
665
|
-
} else {
|
|
666
|
-
path.pop();
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
if (isExitImpossible(path)) {
|
|
670
|
-
const referred = await refer(path);
|
|
671
|
-
if (isAction(referred) && isSkippedDuringRestore(referred[0])) {
|
|
672
|
-
onExitImpossible?.();
|
|
673
|
-
}
|
|
674
|
-
wasExitImpossible = true;
|
|
675
|
-
return {
|
|
676
|
-
exitImpossible: wasExitImpossible
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
for (let i = path.length - 1; i > 0; i--) {
|
|
680
|
-
const [name] = path[i];
|
|
681
|
-
if (isBlockExitStatement(name)) {
|
|
682
|
-
ignore.push(name);
|
|
683
|
-
}
|
|
684
|
-
if (!isBlockStatement(name)) continue;
|
|
685
|
-
if (ignore.at(-1)?.startsWith(name)) {
|
|
686
|
-
ignore.pop();
|
|
687
|
-
continue;
|
|
688
|
-
}
|
|
689
|
-
path.push([`${name}:exit`]);
|
|
690
|
-
const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
|
|
691
|
-
if (prev) path.push([null, prev[1] + 1]);
|
|
692
|
-
if (!isAction(await refer(path))) {
|
|
693
|
-
path.pop();
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
|
-
break;
|
|
697
|
-
}
|
|
698
|
-
return {
|
|
699
|
-
exitImpossible: wasExitImpossible
|
|
700
|
-
};
|
|
701
|
-
};
|
|
702
|
-
var nextPath = (path) => {
|
|
703
|
-
const last = path.at(-1);
|
|
704
|
-
if (last && (isNull(last[0]) || last[0] === "jump") && isNumber(last[1])) {
|
|
705
|
-
last[1]++;
|
|
706
|
-
} else {
|
|
707
|
-
path.push([null, 0]);
|
|
708
|
-
}
|
|
709
|
-
return path;
|
|
710
|
-
};
|
|
711
|
-
var collectActionsBeforeBlockingAction = async ({
|
|
712
|
-
path,
|
|
713
|
-
refer,
|
|
714
|
-
clone
|
|
715
|
-
}) => {
|
|
716
|
-
const collection = [];
|
|
717
|
-
let action = await refer(path);
|
|
718
|
-
while (true) {
|
|
719
|
-
if (action == void 0) {
|
|
720
|
-
const { exitImpossible } = await exitPath({
|
|
721
|
-
path,
|
|
722
|
-
refer
|
|
723
|
-
});
|
|
724
|
-
if (exitImpossible) {
|
|
725
|
-
break;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
if (!action) {
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
731
|
-
if (isBlockingAction(action)) {
|
|
732
|
-
const [name, ...props] = action;
|
|
733
|
-
if (name === "choice") {
|
|
734
|
-
const choiceProps = props;
|
|
735
|
-
for (let i = 0; i < choiceProps.length; i++) {
|
|
736
|
-
const branchContent = choiceProps[i];
|
|
737
|
-
if (!Array.isArray(branchContent)) continue;
|
|
738
|
-
const virtualPath = clone(path);
|
|
739
|
-
virtualPath.push(["choice", i], [null, 0]);
|
|
740
|
-
const innerActions = await collectActionsBeforeBlockingAction({
|
|
741
|
-
path: virtualPath,
|
|
742
|
-
refer,
|
|
743
|
-
clone
|
|
744
|
-
});
|
|
745
|
-
collection.push(...innerActions);
|
|
746
|
-
}
|
|
747
|
-
} else if (name === "condition") {
|
|
748
|
-
const conditionProps = props;
|
|
749
|
-
const conditions = Object.keys(conditionProps[1]);
|
|
750
|
-
for (const condition of conditions) {
|
|
751
|
-
const virtualPath = clone(path);
|
|
752
|
-
virtualPath.push(["condition", condition], [null, 0]);
|
|
753
|
-
const innerActions = await collectActionsBeforeBlockingAction({
|
|
754
|
-
path: virtualPath,
|
|
755
|
-
refer,
|
|
756
|
-
clone
|
|
757
|
-
});
|
|
758
|
-
collection.push(...innerActions);
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
break;
|
|
762
|
-
}
|
|
763
|
-
collection.push(action);
|
|
764
|
-
if (action[0] === "jump") {
|
|
765
|
-
path = [
|
|
766
|
-
["jump", action[1]],
|
|
767
|
-
[null, 0]
|
|
768
|
-
];
|
|
769
|
-
} else if (action[0] == "block") {
|
|
770
|
-
path.push(["block", action[1]], [null, 0]);
|
|
771
|
-
} else {
|
|
772
|
-
nextPath(path);
|
|
773
|
-
}
|
|
774
|
-
action = await refer(path);
|
|
775
|
-
}
|
|
776
|
-
return collection;
|
|
777
|
-
};
|
|
778
|
-
var findLastPathItemBeforeItemOfType = (path, name) => {
|
|
779
|
-
const item = path.findLast(([_name, _value], i, array) => {
|
|
780
|
-
const next = array[i + 1];
|
|
781
|
-
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
782
|
-
});
|
|
783
|
-
return item;
|
|
784
|
-
};
|
|
785
|
-
var getOppositeAction = (action) => {
|
|
786
|
-
const MAP = {
|
|
787
|
-
showCharacter: "hideCharacter",
|
|
788
|
-
playSound: "stopSound",
|
|
789
|
-
playMusic: "stopMusic",
|
|
790
|
-
voice: "stopVoice"
|
|
791
|
-
};
|
|
792
|
-
return MAP[action];
|
|
793
|
-
};
|
|
794
|
-
var getActionsFromPath = async ({ story, path, filter, referGuarded }) => {
|
|
795
|
-
let current = story;
|
|
796
|
-
let precurrent;
|
|
797
|
-
let ignoreNestedBefore = null;
|
|
798
|
-
let index = 0;
|
|
799
|
-
let skipPreserve = void 0;
|
|
800
|
-
const skip = /* @__PURE__ */ new Set();
|
|
801
|
-
const max = path.reduce((acc, [type, val]) => {
|
|
802
|
-
if (isNull(type) && isNumber(val)) {
|
|
803
|
-
return acc + 1;
|
|
804
|
-
}
|
|
805
|
-
return acc;
|
|
806
|
-
}, 0);
|
|
807
|
-
const queue = [];
|
|
808
|
-
const blocks = [];
|
|
809
|
-
await referGuarded(path);
|
|
810
|
-
for (const [type, val] of path) {
|
|
811
|
-
if (type === "jump") {
|
|
812
|
-
precurrent = story;
|
|
813
|
-
current = current[val];
|
|
814
|
-
} else if (type === null) {
|
|
815
|
-
precurrent = current;
|
|
816
|
-
if (isNumber(val)) {
|
|
817
|
-
index++;
|
|
818
|
-
let startIndex = 0;
|
|
819
|
-
if (ignoreNestedBefore) {
|
|
820
|
-
const prev = findLastPathItemBeforeItemOfType(path.slice(0, index), ignoreNestedBefore);
|
|
821
|
-
if (prev) {
|
|
822
|
-
startIndex = prev[1];
|
|
823
|
-
ignoreNestedBefore = null;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
for (let i = startIndex; i <= val; i++) {
|
|
827
|
-
const item = current[i];
|
|
828
|
-
if (!isAction(item)) continue;
|
|
829
|
-
const [action] = item;
|
|
830
|
-
const last = index === max && i === val;
|
|
831
|
-
const shouldSkip = isSkippedDuringRestore(action) || isUserRequiredAction(item);
|
|
832
|
-
if (shouldSkip) {
|
|
833
|
-
skip.add(item);
|
|
834
|
-
}
|
|
835
|
-
if (shouldSkip && last) {
|
|
836
|
-
skipPreserve = item;
|
|
837
|
-
}
|
|
838
|
-
if (filter && shouldSkip && !last) {
|
|
839
|
-
continue;
|
|
840
|
-
} else {
|
|
841
|
-
queue.push(item);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
current = current[val];
|
|
846
|
-
} else if (type === "choice") {
|
|
847
|
-
blocks.push(precurrent);
|
|
848
|
-
current = current[val + 1][1];
|
|
849
|
-
} else if (type === "condition") {
|
|
850
|
-
blocks.push(precurrent);
|
|
851
|
-
current = current[2][val];
|
|
852
|
-
} else if (type === "block") {
|
|
853
|
-
blocks.push(precurrent);
|
|
854
|
-
current = story[val];
|
|
855
|
-
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
856
|
-
current = blocks.pop();
|
|
857
|
-
ignoreNestedBefore = type.slice(0, -5);
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
return {
|
|
861
|
-
queue,
|
|
862
|
-
skip,
|
|
863
|
-
skipPreserve
|
|
864
|
-
};
|
|
865
|
-
};
|
|
866
|
-
var createQueueProcessor = (queue, options) => {
|
|
867
|
-
const processedQueue = [];
|
|
868
|
-
const keep = /* @__PURE__ */ new Set();
|
|
869
|
-
const characters = /* @__PURE__ */ new Set();
|
|
870
|
-
const audio2 = {
|
|
871
|
-
music: /* @__PURE__ */ new Set(),
|
|
872
|
-
sounds: /* @__PURE__ */ new Set()
|
|
873
|
-
};
|
|
874
|
-
const next = (i) => queue.slice(i + 1);
|
|
875
|
-
for (const [i, item] of queue.entries()) {
|
|
876
|
-
const [action, ...params] = item;
|
|
877
|
-
if (options.skip.has(item) && item !== options.skipPreserve) {
|
|
878
|
-
continue;
|
|
879
|
-
}
|
|
880
|
-
keep.add(action);
|
|
881
|
-
if (action === "function" || action === "custom") {
|
|
882
|
-
if (action === "custom") {
|
|
883
|
-
const fn = params[0];
|
|
884
|
-
if ("callOnlyLatest" in fn && fn.callOnlyLatest) {
|
|
885
|
-
const notLatest = next(i).some(([name, func]) => {
|
|
886
|
-
if (name !== "custom") return;
|
|
887
|
-
const isIdenticalId = Boolean(func.id && fn.id && func.id === fn.id);
|
|
888
|
-
const isIdenticalByReference = func === fn;
|
|
889
|
-
const isIdenticalByCode = String(func) === String(fn);
|
|
890
|
-
return isIdenticalId || isIdenticalByReference || isIdenticalByCode;
|
|
891
|
-
});
|
|
892
|
-
if (notLatest) continue;
|
|
893
|
-
} else if ("skipOnRestore" in fn && fn.skipOnRestore) {
|
|
894
|
-
if (fn.skipOnRestore(next(i))) {
|
|
895
|
-
continue;
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
processedQueue.push(item);
|
|
900
|
-
} else if (action === "playSound") {
|
|
901
|
-
const closing = getOppositeAction(action);
|
|
902
|
-
const skip = next(i).some((item2) => {
|
|
903
|
-
if (isUserRequiredAction(item2) || isSkippedDuringRestore(item2[0])) {
|
|
904
|
-
return true;
|
|
905
|
-
}
|
|
906
|
-
const [_action, target] = item2;
|
|
907
|
-
if (target !== params[0]) {
|
|
908
|
-
return false;
|
|
909
|
-
}
|
|
910
|
-
return _action === closing || _action === action;
|
|
911
|
-
});
|
|
912
|
-
if (skip) continue;
|
|
913
|
-
audio2.sounds.add(unwrapAsset(params[0]));
|
|
914
|
-
processedQueue.push(item);
|
|
915
|
-
} else if (action === "showCharacter" || action === "playMusic" || action === "voice") {
|
|
916
|
-
const closing = getOppositeAction(action);
|
|
917
|
-
const skip = next(i).some(([_action, target]) => {
|
|
918
|
-
if (target !== params[0] && action !== "voice") {
|
|
919
|
-
return false;
|
|
920
|
-
}
|
|
921
|
-
const musicWillBePaused = action === "playMusic" && _action === "pauseMusic";
|
|
922
|
-
return musicWillBePaused || _action === closing || _action === action;
|
|
923
|
-
});
|
|
924
|
-
if (skip) continue;
|
|
925
|
-
if (action === "showCharacter") {
|
|
926
|
-
characters.add(params[0]);
|
|
927
|
-
} else if (action === "playMusic") {
|
|
928
|
-
audio2.music.add(unwrapAsset(params[0]));
|
|
929
|
-
}
|
|
930
|
-
processedQueue.push(item);
|
|
931
|
-
} else if (action === "showBackground" || action === "preload") {
|
|
932
|
-
const skip = next(i).some(([_action]) => action === _action);
|
|
933
|
-
if (skip) continue;
|
|
934
|
-
processedQueue.push(item);
|
|
935
|
-
} else if (action === "animateCharacter") {
|
|
936
|
-
const skip = next(i).some(([_action, character], j, array) => {
|
|
937
|
-
if (action === _action && character === params[0]) {
|
|
938
|
-
return true;
|
|
939
|
-
}
|
|
940
|
-
const next2 = array.slice(j);
|
|
941
|
-
const characterWillAnimate = next2.some(([__action, __character]) => action === __action);
|
|
942
|
-
const hasBlockingActions = next2.some((item2) => options.skip.has(item2));
|
|
943
|
-
const differentCharacterWillAnimate = !hasBlockingActions && next2.some(([__action, __character]) => __action === action && __character !== params[0]);
|
|
944
|
-
return characterWillAnimate && hasBlockingActions || differentCharacterWillAnimate;
|
|
945
|
-
});
|
|
946
|
-
if (skip) continue;
|
|
947
|
-
processedQueue.push(item);
|
|
948
|
-
} else {
|
|
949
|
-
processedQueue.push(item);
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
const run = async (match) => {
|
|
953
|
-
for (const item of processedQueue) {
|
|
954
|
-
const result = match(item);
|
|
955
|
-
if (isPromise(result)) {
|
|
956
|
-
await result;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
processedQueue.length = 0;
|
|
960
|
-
};
|
|
961
|
-
return {
|
|
962
|
-
run,
|
|
963
|
-
keep: {
|
|
964
|
-
keep,
|
|
965
|
-
characters,
|
|
966
|
-
audio: audio2
|
|
967
|
-
}
|
|
968
|
-
};
|
|
969
|
-
};
|
|
970
|
-
|
|
971
|
-
// src/utilities/controlled-promise.ts
|
|
972
|
-
var createControlledPromise = () => {
|
|
973
|
-
const object = {
|
|
974
|
-
resolve: null,
|
|
975
|
-
reject: null,
|
|
976
|
-
promise: null,
|
|
977
|
-
cancel: null
|
|
978
|
-
};
|
|
979
|
-
const init = () => {
|
|
980
|
-
const promise = new Promise((resolve, reject) => {
|
|
981
|
-
object.reject = reject;
|
|
982
|
-
object.resolve = (value) => {
|
|
983
|
-
resolve({ cancelled: false, value });
|
|
984
|
-
};
|
|
985
|
-
object.cancel = () => {
|
|
986
|
-
resolve({ cancelled: true, value: null });
|
|
987
|
-
init();
|
|
988
|
-
};
|
|
989
|
-
});
|
|
990
|
-
object.promise = promise;
|
|
991
|
-
};
|
|
992
|
-
return init(), object;
|
|
993
|
-
};
|
|
994
|
-
|
|
995
|
-
// src/utilities/resources.ts
|
|
996
|
-
var getUrlFileExtension = (address) => {
|
|
997
|
-
try {
|
|
998
|
-
const { pathname } = new URL(address, location.href);
|
|
999
|
-
return pathname.split(".").at(-1).split("!")[0].split(":")[0];
|
|
1000
|
-
} catch (error) {
|
|
1001
|
-
if (DEV) {
|
|
1002
|
-
console.error(new Error(`Could not construct URL "${address}".`, { cause: error }));
|
|
1003
|
-
}
|
|
1004
|
-
return "";
|
|
1005
|
-
}
|
|
1006
|
-
};
|
|
1007
|
-
var fetchContentType = async (url, request) => {
|
|
1008
|
-
try {
|
|
1009
|
-
const response = await request(url, {
|
|
1010
|
-
method: "HEAD"
|
|
1011
|
-
});
|
|
1012
|
-
return response.headers.get("Content-Type") || "";
|
|
1013
|
-
} catch (error) {
|
|
1014
|
-
if (DEV) {
|
|
1015
|
-
console.error(new Error(`Failed to fetch file at "${url}"`, { cause: error }));
|
|
1016
|
-
}
|
|
1017
|
-
return "";
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
var getResourseType = memoize(
|
|
1021
|
-
async ({ url, request }) => {
|
|
1022
|
-
if (!isCSSImageURL(url)) {
|
|
1023
|
-
return "other";
|
|
1024
|
-
}
|
|
1025
|
-
const extension = getUrlFileExtension(url);
|
|
1026
|
-
if (HOWLER_SUPPORTED_FILE_FORMATS.has(extension)) {
|
|
1027
|
-
return "audio";
|
|
1028
|
-
}
|
|
1029
|
-
if (SUPPORTED_IMAGE_FILE_FORMATS.has(extension)) {
|
|
1030
|
-
return "image";
|
|
1031
|
-
}
|
|
1032
|
-
const contentType = await fetchContentType(url, request);
|
|
1033
|
-
if (contentType.includes("audio")) {
|
|
1034
|
-
return "audio";
|
|
1035
|
-
}
|
|
1036
|
-
if (contentType.includes("image")) {
|
|
1037
|
-
return "image";
|
|
1038
|
-
}
|
|
1039
|
-
return "other";
|
|
1040
|
-
},
|
|
1041
|
-
{
|
|
1042
|
-
getCacheKey: ({ url }) => url
|
|
1043
|
-
}
|
|
1044
|
-
);
|
|
1045
|
-
|
|
1046
|
-
// src/shared.ts
|
|
1047
|
-
var STACK_MAP = /* @__PURE__ */ new Map();
|
|
1048
|
-
var CUSTOM_ACTION_MAP = /* @__PURE__ */ new Map();
|
|
1049
|
-
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
1050
|
-
var ASSETS_TO_PRELOAD = /* @__PURE__ */ new Set();
|
|
1051
|
-
|
|
1052
|
-
// src/utilities/stack.ts
|
|
1053
|
-
var getStack = memoize(
|
|
1054
|
-
(_) => {
|
|
1055
|
-
return [];
|
|
1056
|
-
},
|
|
1057
|
-
{
|
|
1058
|
-
cache: STACK_MAP,
|
|
1059
|
-
getCacheKey: (ctx) => ctx.id
|
|
1060
|
-
}
|
|
1061
|
-
);
|
|
1062
|
-
var createUseStackFunction = (renderer) => {
|
|
1063
|
-
const useStack = (context) => {
|
|
1064
|
-
const ctx = typeof context === "string" ? renderer.getContext(context) : context;
|
|
1065
|
-
const stack = getStack(ctx);
|
|
1066
|
-
return {
|
|
1067
|
-
get previous() {
|
|
1068
|
-
return stack.previous;
|
|
1069
|
-
},
|
|
1070
|
-
get value() {
|
|
1071
|
-
return stack.at(-1);
|
|
1072
|
-
},
|
|
1073
|
-
set value(value) {
|
|
1074
|
-
stack[stack.length - 1] = value;
|
|
1075
|
-
},
|
|
1076
|
-
back() {
|
|
1077
|
-
stack.previous = stack.length > 1 ? stack.pop() : this.value;
|
|
1078
|
-
ctx.meta.goingBack = true;
|
|
1079
|
-
},
|
|
1080
|
-
push(value) {
|
|
1081
|
-
stack.push(value);
|
|
1082
|
-
},
|
|
1083
|
-
clear() {
|
|
1084
|
-
stack.previous = void 0;
|
|
1085
|
-
stack.length = 0;
|
|
1086
|
-
stack.length = 1;
|
|
1087
|
-
}
|
|
1088
|
-
};
|
|
1089
|
-
};
|
|
1090
|
-
return useStack;
|
|
1091
|
-
};
|
|
1092
|
-
|
|
1093
|
-
// src/utilities/story.ts
|
|
1094
|
-
var flatActions = (item) => {
|
|
1095
|
-
return item.flatMap((data) => {
|
|
1096
|
-
const type = data[0];
|
|
1097
|
-
if (Array.isArray(type)) return flatActions(data);
|
|
1098
|
-
return [data];
|
|
1099
|
-
});
|
|
1100
|
-
};
|
|
1101
|
-
var flatStory = (story) => {
|
|
1102
|
-
for (const key in story) {
|
|
1103
|
-
story[key] = flatActions(story[key]);
|
|
1104
|
-
}
|
|
1105
|
-
return story;
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
|
-
// src/browser.ts
|
|
1109
|
-
var setupBrowserVisibilityChangeListeners = ({ onChange }) => {
|
|
1110
|
-
if (typeof document === "undefined") return noop;
|
|
1111
|
-
const onVisibilityChange = () => {
|
|
1112
|
-
if (document.visibilityState === "hidden") {
|
|
1113
|
-
onChange();
|
|
1114
|
-
}
|
|
1115
|
-
};
|
|
1116
|
-
addEventListener("visibilitychange", onVisibilityChange);
|
|
1117
|
-
addEventListener("beforeunload", onChange);
|
|
1118
|
-
return () => {
|
|
1119
|
-
removeEventListener("visibilitychange", onVisibilityChange);
|
|
1120
|
-
removeEventListener("beforeunload", onChange);
|
|
1121
|
-
};
|
|
1122
|
-
};
|
|
1123
|
-
|
|
1124
|
-
// src/custom-action.ts
|
|
1125
|
-
var createCustomActionNode = (id) => {
|
|
1126
|
-
const div = document.createElement("div");
|
|
1127
|
-
div.setAttribute("data-id", id);
|
|
1128
|
-
return div;
|
|
1129
|
-
};
|
|
1130
|
-
var getCustomActionHolder = (ctx, fn) => {
|
|
1131
|
-
const cached = CUSTOM_ACTION_MAP.get(ctx.id + fn.key);
|
|
1132
|
-
if (cached) {
|
|
1133
|
-
return cached;
|
|
1134
|
-
}
|
|
1135
|
-
const holder = {
|
|
1136
|
-
cleanup: noop,
|
|
1137
|
-
node: null,
|
|
1138
|
-
fn,
|
|
1139
|
-
localData: {}
|
|
1140
|
-
};
|
|
1141
|
-
CUSTOM_ACTION_MAP.set(ctx.id + fn.key, holder);
|
|
1142
|
-
return holder;
|
|
1143
|
-
};
|
|
1144
|
-
var handleCustomAction = (ctx, fn, {
|
|
1145
|
-
lang,
|
|
1146
|
-
state,
|
|
1147
|
-
setMountElement,
|
|
1148
|
-
setClear,
|
|
1149
|
-
remove: renderersRemove,
|
|
1150
|
-
getStack: getStack2,
|
|
1151
|
-
templateReplace
|
|
1152
|
-
}) => {
|
|
1153
|
-
const holder = getCustomActionHolder(ctx, fn);
|
|
1154
|
-
const flags = {
|
|
1155
|
-
...ctx.meta
|
|
1156
|
-
};
|
|
1157
|
-
const getDomNodes = (insert = true) => {
|
|
1158
|
-
if (holder.node || !insert) {
|
|
1159
|
-
return {
|
|
1160
|
-
element: holder.node,
|
|
1161
|
-
root: ctx.root
|
|
1162
|
-
};
|
|
1163
|
-
}
|
|
1164
|
-
holder.node = insert ? createCustomActionNode(fn.key) : null;
|
|
1165
|
-
setMountElement(holder.node);
|
|
1166
|
-
return {
|
|
1167
|
-
element: holder.node,
|
|
1168
|
-
root: ctx.root
|
|
1169
|
-
};
|
|
1170
|
-
};
|
|
1171
|
-
const clear = (func) => {
|
|
1172
|
-
setClear(
|
|
1173
|
-
holder.cleanup = () => {
|
|
1174
|
-
func();
|
|
1175
|
-
holder.node = null;
|
|
1176
|
-
holder.cleanup = noop;
|
|
1177
|
-
setMountElement(null);
|
|
1178
|
-
setClear(noop);
|
|
1179
|
-
}
|
|
1180
|
-
);
|
|
1181
|
-
};
|
|
1182
|
-
const data = (updatedData) => {
|
|
1183
|
-
if (updatedData) {
|
|
1184
|
-
return holder.localData = updatedData;
|
|
1185
|
-
}
|
|
1186
|
-
return holder.localData;
|
|
1187
|
-
};
|
|
1188
|
-
const remove = () => {
|
|
1189
|
-
holder.cleanup();
|
|
1190
|
-
renderersRemove();
|
|
1191
|
-
};
|
|
1192
|
-
const stack = getStack2(ctx);
|
|
1193
|
-
const getPath = () => {
|
|
1194
|
-
return stack.value[0];
|
|
1195
|
-
};
|
|
1196
|
-
return fn({
|
|
1197
|
-
flags,
|
|
1198
|
-
lang,
|
|
1199
|
-
state,
|
|
1200
|
-
data,
|
|
1201
|
-
templateReplace,
|
|
1202
|
-
clear,
|
|
1203
|
-
remove,
|
|
1204
|
-
rendererContext: ctx,
|
|
1205
|
-
getDomNodes,
|
|
1206
|
-
getPath,
|
|
1207
|
-
contextKey: ctx.id
|
|
1208
|
-
});
|
|
1209
|
-
};
|
|
1210
|
-
|
|
1211
|
-
// src/preloading.ts
|
|
1212
|
-
var ACTION_NAME_TO_VOLUME_MAP = {
|
|
1213
|
-
playMusic: "music",
|
|
1214
|
-
playSound: "sound",
|
|
1215
|
-
voice: "voice"
|
|
1216
|
-
};
|
|
1217
|
-
var enqueueAssetForPreloading = (asset2) => {
|
|
1218
|
-
if (!PRELOADED_ASSETS.has(asset2)) {
|
|
1219
|
-
ASSETS_TO_PRELOAD.add(asset2);
|
|
1220
|
-
}
|
|
1221
|
-
};
|
|
1222
|
-
var handleAssetsPreloading = async ({
|
|
1223
|
-
request,
|
|
1224
|
-
limiter,
|
|
1225
|
-
preloadAudioBlocking,
|
|
1226
|
-
preloadImageBlocking
|
|
1227
|
-
}) => {
|
|
1228
|
-
const list = mapSet(ASSETS_TO_PRELOAD, (asset2) => {
|
|
1229
|
-
return limiter(async () => {
|
|
1230
|
-
const type = await getResourseType({
|
|
1231
|
-
url: asset2,
|
|
1232
|
-
request
|
|
1233
|
-
});
|
|
1234
|
-
switch (type) {
|
|
1235
|
-
case "audio": {
|
|
1236
|
-
await preloadAudioBlocking(asset2);
|
|
1237
|
-
break;
|
|
1238
|
-
}
|
|
1239
|
-
case "image": {
|
|
1240
|
-
await preloadImageBlocking(asset2);
|
|
1241
|
-
break;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
ASSETS_TO_PRELOAD.delete(asset2);
|
|
1245
|
-
PRELOADED_ASSETS.add(asset2);
|
|
1246
|
-
});
|
|
1247
|
-
});
|
|
1248
|
-
await Promise.allSettled(list);
|
|
1249
|
-
ASSETS_TO_PRELOAD.clear();
|
|
1250
|
-
};
|
|
1251
|
-
var huntAssets = ({ volume, lang, mode, characters, action, props, handle }) => {
|
|
1252
|
-
if (action === "showBackground") {
|
|
1253
|
-
if (isString(props[0])) {
|
|
1254
|
-
handle(handleAudioAsset(props[0]));
|
|
1255
|
-
}
|
|
1256
|
-
if (props[0] && typeof props[0] === "object") {
|
|
1257
|
-
for (const value of Object.values(props[0])) {
|
|
1258
|
-
if (isImageAsset(value)) {
|
|
1259
|
-
handle(value);
|
|
1260
|
-
} else if (isAsset(value)) {
|
|
1261
|
-
const unwrapped = handleImageAsset(value);
|
|
1262
|
-
if (isImageAsset(unwrapped)) {
|
|
1263
|
-
handle(unwrapped);
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
return;
|
|
1269
|
-
}
|
|
1270
|
-
const getVolumeFor = (action2) => {
|
|
1271
|
-
if (action2 in ACTION_NAME_TO_VOLUME_MAP) {
|
|
1272
|
-
return volume[ACTION_NAME_TO_VOLUME_MAP[action2]];
|
|
1273
|
-
}
|
|
1274
|
-
return 0;
|
|
1275
|
-
};
|
|
1276
|
-
if (isAudioAction(action) && isString(props[0])) {
|
|
1277
|
-
if (getVolumeFor(action) > 0) {
|
|
1278
|
-
handle(handleAudioAsset(props[0]));
|
|
1279
|
-
}
|
|
1280
|
-
return;
|
|
1281
|
-
}
|
|
1282
|
-
if (action === "voice" && typeof props[0] === "object") {
|
|
1283
|
-
if (getVolumeFor("voice") == 0) {
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
|
-
for (const [language, value] of Object.entries(props[0])) {
|
|
1287
|
-
if (mode === "blocking") {
|
|
1288
|
-
value && handle(handleAudioAsset(value));
|
|
1289
|
-
} else if (language === lang) {
|
|
1290
|
-
value && handle(handleAudioAsset(value));
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
return;
|
|
1294
|
-
}
|
|
1295
|
-
if (action === "showCharacter" && isString(props[0]) && isString(props[1])) {
|
|
1296
|
-
const images = toArray(characters[props[0]].emotions[props[1]]);
|
|
1297
|
-
for (const asset2 of images) {
|
|
1298
|
-
handle(handleImageAsset(asset2));
|
|
1299
|
-
}
|
|
1300
|
-
return;
|
|
1301
|
-
}
|
|
1302
|
-
if (action === "custom" && props[0].assets) {
|
|
1303
|
-
for (const asset2 of props[0].assets) {
|
|
1304
|
-
isAsset(asset2) ? handle(asset2.source) : handle(asset2);
|
|
1305
|
-
}
|
|
1306
|
-
return;
|
|
1307
|
-
}
|
|
1308
|
-
if (action === "choice") {
|
|
1309
|
-
for (let i = 1; i < props.length; i++) {
|
|
1310
|
-
const data = props[i];
|
|
1311
|
-
if (Array.isArray(data)) {
|
|
1312
|
-
handle(handleImageAsset(data[5]));
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
};
|
|
1317
|
-
|
|
1318
|
-
// src/storage.ts
|
|
1319
|
-
var localStorageStorage = (options) => {
|
|
1320
|
-
return {
|
|
1321
|
-
async get() {
|
|
1322
|
-
const fallback = { saves: [], data: {}, meta: [] };
|
|
1323
|
-
try {
|
|
1324
|
-
const value = localStorage.getItem(options.key);
|
|
1325
|
-
return value ? JSON.parse(value) : fallback;
|
|
1326
|
-
} catch {
|
|
1327
|
-
return fallback;
|
|
1328
|
-
}
|
|
1329
|
-
},
|
|
1330
|
-
async set(data) {
|
|
1331
|
-
try {
|
|
1332
|
-
localStorage.setItem(options.key, JSON.stringify(data));
|
|
1333
|
-
} catch {
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
};
|
|
1337
|
-
};
|
|
1338
|
-
|
|
1339
|
-
// src/store.ts
|
|
1340
|
-
var store = (current, subscribers = /* @__PURE__ */ new Set()) => {
|
|
1341
|
-
const subscribe = (cb) => {
|
|
1342
|
-
subscribers.add(cb), cb(current);
|
|
1343
|
-
return () => {
|
|
1344
|
-
subscribers.delete(cb);
|
|
1345
|
-
};
|
|
1346
|
-
};
|
|
1347
|
-
const push = (value) => {
|
|
1348
|
-
for (const cb of subscribers) cb(value);
|
|
1349
|
-
};
|
|
1350
|
-
const update = (fn) => {
|
|
1351
|
-
push(current = fn(current));
|
|
1352
|
-
};
|
|
1353
|
-
const set2 = (val) => {
|
|
1354
|
-
update(() => val);
|
|
1355
|
-
};
|
|
1356
|
-
const get = () => {
|
|
1357
|
-
return current;
|
|
1358
|
-
};
|
|
1359
|
-
return { subscribe, update, set: set2, get };
|
|
1360
|
-
};
|
|
1361
|
-
|
|
1362
|
-
// src/translation.ts
|
|
1363
|
-
var RGX = /{{(.*?)}}/g;
|
|
1364
|
-
var split = (input, delimeters) => {
|
|
1365
|
-
const output = [];
|
|
1366
|
-
for (const delimeter of delimeters) {
|
|
1367
|
-
if (!input) break;
|
|
1368
|
-
const [start, end] = input.split(delimeter, 2);
|
|
1369
|
-
output.push(start);
|
|
1370
|
-
input = end;
|
|
1371
|
-
}
|
|
1372
|
-
output.push(input);
|
|
1373
|
-
return output;
|
|
1374
|
-
};
|
|
1375
|
-
var flattenAllowedContent = (c, state) => {
|
|
1376
|
-
if (Array.isArray(c)) {
|
|
1377
|
-
return c.map((item) => flattenAllowedContent(item, state)).join("<br>");
|
|
1378
|
-
}
|
|
1379
|
-
if (typeof c === "function") {
|
|
1380
|
-
return flattenAllowedContent(c(state), state);
|
|
1381
|
-
}
|
|
1382
|
-
return c;
|
|
1383
|
-
};
|
|
1384
|
-
var replace = (input, data, pluralization, actions, pr) => {
|
|
1385
|
-
return input.replaceAll(RGX, (x, key, y) => {
|
|
1386
|
-
x = 0;
|
|
1387
|
-
y = data;
|
|
1388
|
-
const [pathstr, plural, action] = split(key.trim(), ["@", "%"]);
|
|
1389
|
-
if (!pathstr) {
|
|
1390
|
-
return "";
|
|
1391
|
-
}
|
|
1392
|
-
const path = pathstr.split(".");
|
|
1393
|
-
while (y && x < path.length) y = y[path[x++]];
|
|
1394
|
-
if (plural && pluralization && y && pr) {
|
|
1395
|
-
y = pluralization[plural][pr.select(y)];
|
|
1396
|
-
}
|
|
1397
|
-
const actionHandler = actions && action ? actions[action] : void 0;
|
|
1398
|
-
if (actionHandler) y = actionHandler(y);
|
|
1399
|
-
return y == null ? "" : y;
|
|
1400
|
-
});
|
|
1401
|
-
};
|
|
1402
|
-
|
|
1403
|
-
// src/utilities/actions.ts
|
|
1404
|
-
var VIRTUAL_ACTIONS = ["say"];
|
|
1405
|
-
var buildActionObject = ({
|
|
1406
|
-
rendererActions,
|
|
1407
|
-
nativeActions,
|
|
1408
|
-
characters,
|
|
1409
|
-
preloadAssets,
|
|
1410
|
-
storageData
|
|
1411
|
-
}) => {
|
|
1412
|
-
const allActions = [...nativeActions, ...VIRTUAL_ACTIONS];
|
|
1413
|
-
const object = { ...rendererActions };
|
|
1414
|
-
for (let action of allActions) {
|
|
1415
|
-
object[action] = (...props) => {
|
|
1416
|
-
if (action === "say") {
|
|
1417
|
-
action = "dialog";
|
|
1418
|
-
const [character] = props;
|
|
1419
|
-
if (DEV && !characters[character]) {
|
|
1420
|
-
throw new Error(`Attempt to call Say action with unknown character "${character}"`);
|
|
1421
|
-
}
|
|
1422
|
-
} else if (action === "choice") {
|
|
1423
|
-
if (props.slice(1).every((choice) => !Array.isArray(choice))) {
|
|
1424
|
-
for (let i = 1; i < props.length; i++) {
|
|
1425
|
-
const choice = props[i];
|
|
1426
|
-
props[i] = [
|
|
1427
|
-
choice.title,
|
|
1428
|
-
flatActions(choice.children),
|
|
1429
|
-
choice.active,
|
|
1430
|
-
choice.visible,
|
|
1431
|
-
choice.onSelect,
|
|
1432
|
-
choice.image
|
|
1433
|
-
];
|
|
1434
|
-
}
|
|
1435
|
-
} else {
|
|
1436
|
-
for (let i = 1; i < props.length; i++) {
|
|
1437
|
-
const choice = props[i];
|
|
1438
|
-
if (Array.isArray(choice)) {
|
|
1439
|
-
choice[1] = flatActions(choice[1]);
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
} else if (action === "condition") {
|
|
1444
|
-
const actions = props[1];
|
|
1445
|
-
for (const key in actions) {
|
|
1446
|
-
actions[key] = flatActions(actions[key]);
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
if (preloadAssets === "blocking") {
|
|
1450
|
-
huntAssets({
|
|
1451
|
-
action,
|
|
1452
|
-
props,
|
|
1453
|
-
mode: preloadAssets,
|
|
1454
|
-
characters,
|
|
1455
|
-
lang: getLanguageFromStore(storageData),
|
|
1456
|
-
volume: getVolumeFromStore(storageData),
|
|
1457
|
-
handle: enqueueAssetForPreloading
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
return [action, ...props];
|
|
1461
|
-
};
|
|
1462
|
-
}
|
|
1463
|
-
return object;
|
|
1464
|
-
};
|
|
1465
|
-
|
|
1466
|
-
// src/novely.ts
|
|
1467
|
-
var novely = ({
|
|
1468
|
-
characters,
|
|
1469
|
-
characterAssetSizes = {},
|
|
1470
|
-
defaultEmotions = {},
|
|
1471
|
-
storage = localStorageStorage({ key: "novely-game-storage" }),
|
|
1472
|
-
storageDelay = Promise.resolve(),
|
|
1473
|
-
renderer: createRenderer,
|
|
1474
|
-
initialScreen = "mainmenu",
|
|
1475
|
-
translation,
|
|
1476
|
-
state: defaultState = {},
|
|
1477
|
-
data: defaultData = {},
|
|
1478
|
-
autosaves = true,
|
|
1479
|
-
migrations = [],
|
|
1480
|
-
throttleTimeout = 799,
|
|
1481
|
-
getLanguage: getLanguage2 = getLanguage,
|
|
1482
|
-
overrideLanguage = false,
|
|
1483
|
-
askBeforeExit = true,
|
|
1484
|
-
preloadAssets = "lazy",
|
|
1485
|
-
parallelAssetsDownloadLimit = 15,
|
|
1486
|
-
fetch: request = fetch,
|
|
1487
|
-
cloneFunction: clone = klona,
|
|
1488
|
-
saveOnUnload = true,
|
|
1489
|
-
startKey = "start",
|
|
1490
|
-
defaultTypewriterSpeed = DEFAULT_TYPEWRITER_SPEED,
|
|
1491
|
-
storyOptions = { mode: "static" }
|
|
1492
|
-
}) => {
|
|
1493
|
-
const languages = Object.keys(translation);
|
|
1494
|
-
const limitScript = pLimit(1);
|
|
1495
|
-
const limitAssetsDownload = pLimit(parallelAssetsDownloadLimit);
|
|
1496
|
-
const story = {};
|
|
1497
|
-
const times = /* @__PURE__ */ new Set();
|
|
1498
|
-
const dataLoaded = createControlledPromise();
|
|
1499
|
-
let initialScreenWasShown = false;
|
|
1500
|
-
let destroyed = false;
|
|
1501
|
-
if (storyOptions.mode === "dynamic") {
|
|
1502
|
-
storyOptions.preloadSaves ??= 4;
|
|
1503
|
-
}
|
|
1504
|
-
const storyLoad = storyOptions.mode === "static" ? noop : storyOptions.load;
|
|
1505
|
-
const onUnknownSceneHit = memoize(async (scene) => {
|
|
1506
|
-
const part = await storyLoad(scene);
|
|
1507
|
-
if (part) {
|
|
1508
|
-
await script(part);
|
|
1509
|
-
}
|
|
1510
|
-
});
|
|
1511
|
-
const intime = (value) => {
|
|
1512
|
-
return times.add(value), value;
|
|
1513
|
-
};
|
|
1514
|
-
const scriptBase = async (part) => {
|
|
1515
|
-
if (destroyed) return;
|
|
1516
|
-
Object.assign(story, flatStory(part));
|
|
1517
|
-
if (!initialScreenWasShown) {
|
|
1518
|
-
renderer.ui.showLoading();
|
|
1519
|
-
}
|
|
1520
|
-
if (preloadAssets === "blocking" && ASSETS_TO_PRELOAD.size > 0) {
|
|
1521
|
-
renderer.ui.showLoading();
|
|
1522
|
-
await handleAssetsPreloading({
|
|
1523
|
-
...renderer.misc,
|
|
1524
|
-
limiter: limitAssetsDownload,
|
|
1525
|
-
request
|
|
1526
|
-
});
|
|
1527
|
-
}
|
|
1528
|
-
await dataLoaded.promise;
|
|
1529
|
-
renderer.ui.hideLoading();
|
|
1530
|
-
if (!initialScreenWasShown) {
|
|
1531
|
-
initialScreenWasShown = true;
|
|
1532
|
-
if (initialScreen === "game") {
|
|
1533
|
-
restore(void 0);
|
|
1534
|
-
} else {
|
|
1535
|
-
renderer.ui.showScreen(initialScreen);
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
};
|
|
1539
|
-
const script = (part) => {
|
|
1540
|
-
return limitScript(() => scriptBase(part));
|
|
1541
|
-
};
|
|
1542
|
-
const getDefaultSave = (state) => {
|
|
1543
|
-
return [
|
|
1544
|
-
[
|
|
1545
|
-
["jump", startKey],
|
|
1546
|
-
[null, 0]
|
|
1547
|
-
],
|
|
1548
|
-
state,
|
|
1549
|
-
[intime(Date.now()), "auto"],
|
|
1550
|
-
[]
|
|
1551
|
-
];
|
|
1552
|
-
};
|
|
1553
|
-
const getLanguageWithoutParameters = () => {
|
|
1554
|
-
const language = getLanguage2(languages, getLanguage);
|
|
1555
|
-
if (languages.includes(language)) {
|
|
1556
|
-
return language;
|
|
1557
|
-
}
|
|
1558
|
-
if (DEV) {
|
|
1559
|
-
throw new Error(
|
|
1560
|
-
`Attempt to use unsupported language "${language}". Supported languages: ${languages.join(", ")}.`
|
|
1561
|
-
);
|
|
1562
|
-
}
|
|
1563
|
-
throw 0;
|
|
1564
|
-
};
|
|
1565
|
-
const initialData = {
|
|
1566
|
-
saves: [],
|
|
1567
|
-
data: clone(defaultData),
|
|
1568
|
-
meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED, 1, 1, 1]
|
|
1569
|
-
};
|
|
1570
|
-
const storageData = store(initialData);
|
|
1571
|
-
const coreData = store({
|
|
1572
|
-
dataLoaded: false
|
|
1573
|
-
});
|
|
1574
|
-
const onDataLoadedPromise = async ({ cancelled }) => {
|
|
1575
|
-
if (cancelled) {
|
|
1576
|
-
dataLoaded.promise.then(onDataLoadedPromise);
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
|
-
const preload = () => {
|
|
1580
|
-
const saves = [...storageData.get().saves].reverse();
|
|
1581
|
-
const sliced = saves.slice(0, storyOptions.mode === "dynamic" ? storyOptions.preloadSaves : 0);
|
|
1582
|
-
for (const [path] of sliced) {
|
|
1583
|
-
referGuarded(path);
|
|
1584
|
-
}
|
|
1585
|
-
};
|
|
1586
|
-
if (preloadAssets === "blocking") {
|
|
1587
|
-
await preload();
|
|
1588
|
-
} else {
|
|
1589
|
-
void preload();
|
|
1590
|
-
}
|
|
1591
|
-
coreData.update((data2) => {
|
|
1592
|
-
data2.dataLoaded = true;
|
|
1593
|
-
return data2;
|
|
1594
|
-
});
|
|
1595
|
-
};
|
|
1596
|
-
dataLoaded.promise.then(onDataLoadedPromise);
|
|
1597
|
-
const onStorageDataChange = (value) => {
|
|
1598
|
-
if (!coreData.get().dataLoaded) return;
|
|
1599
|
-
const data2 = clone(value);
|
|
1600
|
-
for (const save2 of data2.saves) {
|
|
1601
|
-
save2[3] = [];
|
|
1602
|
-
}
|
|
1603
|
-
storage.set(data2);
|
|
1604
|
-
};
|
|
1605
|
-
const throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);
|
|
1606
|
-
const throttledEmergencyOnStorageDataChange = throttle(() => {
|
|
1607
|
-
if (saveOnUnload === true || saveOnUnload === "prod" && !DEV) {
|
|
1608
|
-
onStorageDataChange(storageData.get());
|
|
1609
|
-
}
|
|
1610
|
-
}, 10);
|
|
1611
|
-
storageData.subscribe(throttledOnStorageDataChange);
|
|
1612
|
-
const getStoredData = async () => {
|
|
1613
|
-
let stored = await storage.get();
|
|
1614
|
-
for (const migration of migrations) {
|
|
1615
|
-
stored = migration(stored);
|
|
1616
|
-
if (DEV && !stored) {
|
|
1617
|
-
throw new Error("Migrations should return a value.");
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
if (overrideLanguage || !stored.meta[0]) {
|
|
1621
|
-
stored.meta[0] = getLanguageWithoutParameters();
|
|
1622
|
-
}
|
|
1623
|
-
stored.meta[1] ||= defaultTypewriterSpeed;
|
|
1624
|
-
stored.meta[2] ??= 1;
|
|
1625
|
-
stored.meta[3] ??= 1;
|
|
1626
|
-
stored.meta[4] ??= 1;
|
|
1627
|
-
if (isEmpty(stored.data)) {
|
|
1628
|
-
stored.data = defaultData;
|
|
1629
|
-
}
|
|
1630
|
-
dataLoaded.resolve();
|
|
1631
|
-
storageData.set(stored);
|
|
1632
|
-
};
|
|
1633
|
-
storageDelay.then(getStoredData);
|
|
1634
|
-
const initial = getDefaultSave(clone(defaultState));
|
|
1635
|
-
const unsubscribeFromBrowserVisibilityChange = setupBrowserVisibilityChangeListeners({
|
|
1636
|
-
onChange: throttledEmergencyOnStorageDataChange
|
|
1637
|
-
});
|
|
1638
|
-
const save = (type) => {
|
|
1639
|
-
if (!coreData.get().dataLoaded) return;
|
|
1640
|
-
if (!autosaves && type === "auto") return;
|
|
1641
|
-
const stack = useStack(MAIN_CONTEXT_KEY);
|
|
1642
|
-
const current = clone(stack.value);
|
|
1643
|
-
storageData.update((prev) => {
|
|
1644
|
-
const replace2 = () => {
|
|
1645
|
-
prev.saves[prev.saves.length - 1] = current;
|
|
1646
|
-
return prev;
|
|
1647
|
-
};
|
|
1648
|
-
const add = () => {
|
|
1649
|
-
prev.saves.push(current);
|
|
1650
|
-
return prev;
|
|
1651
|
-
};
|
|
1652
|
-
const last = prev.saves.at(-1);
|
|
1653
|
-
if (!last) return add();
|
|
1654
|
-
current[2][0] = intime(Date.now());
|
|
1655
|
-
current[2][1] = type;
|
|
1656
|
-
current[3] = [];
|
|
1657
|
-
const isIdentical = dequal(last[0], current[0]) && dequal(last[1], current[1]);
|
|
1658
|
-
const isLastMadeInCurrentSession = times.has(last[2][0]);
|
|
1659
|
-
if (isLastMadeInCurrentSession && last[2][1] === "auto" && type === "manual") {
|
|
1660
|
-
return replace2();
|
|
1661
|
-
}
|
|
1662
|
-
if (last[2][1] === "manual" && type === "auto" && isIdentical) {
|
|
1663
|
-
return prev;
|
|
1664
|
-
}
|
|
1665
|
-
if (isLastMadeInCurrentSession && last[2][1] === "auto" && type === "auto") {
|
|
1666
|
-
return replace2();
|
|
1667
|
-
}
|
|
1668
|
-
return add();
|
|
1669
|
-
});
|
|
1670
|
-
};
|
|
1671
|
-
const newGame = () => {
|
|
1672
|
-
if (!coreData.get().dataLoaded) return;
|
|
1673
|
-
const save2 = getDefaultSave(clone(defaultState));
|
|
1674
|
-
if (autosaves) {
|
|
1675
|
-
storageData.update((prev) => {
|
|
1676
|
-
return prev.saves.push(save2), prev;
|
|
1677
|
-
});
|
|
1678
|
-
}
|
|
1679
|
-
const context = renderer.getContext(MAIN_CONTEXT_KEY);
|
|
1680
|
-
const stack = useStack(context);
|
|
1681
|
-
stack.value = save2;
|
|
1682
|
-
context.meta.restoring = context.meta.goingBack = false;
|
|
1683
|
-
renderer.ui.showScreen("game");
|
|
1684
|
-
render(context);
|
|
1685
|
-
};
|
|
1686
|
-
const set2 = (save2, ctx) => {
|
|
1687
|
-
const stack = useStack(ctx || MAIN_CONTEXT_KEY);
|
|
1688
|
-
stack.value = save2;
|
|
1689
|
-
return restore(save2);
|
|
1690
|
-
};
|
|
1691
|
-
let interacted = 0;
|
|
1692
|
-
const restore = async (save2) => {
|
|
1693
|
-
if (isEmpty(story)) {
|
|
1694
|
-
if (DEV) {
|
|
1695
|
-
throw new Error(
|
|
1696
|
-
"Story is empty. You should call an `enine.script` function [https://novely.pages.dev/guide/story.html]"
|
|
1697
|
-
);
|
|
1698
|
-
}
|
|
1699
|
-
return;
|
|
1700
|
-
}
|
|
1701
|
-
if (!coreData.get().dataLoaded) return;
|
|
1702
|
-
let latest = save2 || storageData.get().saves.at(-1);
|
|
1703
|
-
if (!latest) {
|
|
1704
|
-
latest = clone(initial);
|
|
1705
|
-
storageData.update((prev) => {
|
|
1706
|
-
prev.saves.push(latest);
|
|
1707
|
-
return prev;
|
|
1708
|
-
});
|
|
1709
|
-
}
|
|
1710
|
-
const context = renderer.getContext(MAIN_CONTEXT_KEY);
|
|
1711
|
-
const stack = useStack(context);
|
|
1712
|
-
context.meta.restoring = true;
|
|
1713
|
-
const previous = stack.previous;
|
|
1714
|
-
const [path] = stack.value = latest;
|
|
1715
|
-
renderer.ui.showScreen("game");
|
|
1716
|
-
const { found } = await refer(path);
|
|
1717
|
-
if (found) context.loading(true);
|
|
1718
|
-
const { queue, skip, skipPreserve } = await getActionsFromPath({
|
|
1719
|
-
story,
|
|
1720
|
-
path,
|
|
1721
|
-
filter: false,
|
|
1722
|
-
referGuarded
|
|
1723
|
-
});
|
|
1724
|
-
const {
|
|
1725
|
-
run,
|
|
1726
|
-
keep: { keep, characters: characters2, audio: audio2 }
|
|
1727
|
-
} = createQueueProcessor(queue, {
|
|
1728
|
-
skip,
|
|
1729
|
-
skipPreserve
|
|
1730
|
-
});
|
|
1731
|
-
if (previous) {
|
|
1732
|
-
const { queue: prevQueue } = await getActionsFromPath({
|
|
1733
|
-
story,
|
|
1734
|
-
path: previous[0],
|
|
1735
|
-
filter: false,
|
|
1736
|
-
referGuarded
|
|
1737
|
-
});
|
|
1738
|
-
for (let i = prevQueue.length - 1; i > queue.length - 1; i--) {
|
|
1739
|
-
const element = prevQueue[i];
|
|
1740
|
-
if (!isAction(element)) {
|
|
1741
|
-
continue;
|
|
1742
|
-
}
|
|
1743
|
-
const [action2, fn] = element;
|
|
1744
|
-
if (action2 === "custom") {
|
|
1745
|
-
getCustomActionHolder(context, fn).cleanup();
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
}
|
|
1749
|
-
if (context.meta.goingBack) {
|
|
1750
|
-
match("clear", [keep, characters2, audio2], {
|
|
1751
|
-
ctx: context,
|
|
1752
|
-
data: latest[1]
|
|
1753
|
-
});
|
|
1754
|
-
}
|
|
1755
|
-
context.loading(false);
|
|
1756
|
-
const lastQueueItem = queue.at(-1);
|
|
1757
|
-
const lastQueueItemRequiresUserAction = lastQueueItem && isBlockingAction(lastQueueItem);
|
|
1758
|
-
await run((item) => {
|
|
1759
|
-
if (!latest) return;
|
|
1760
|
-
if (lastQueueItem === item && lastQueueItemRequiresUserAction) {
|
|
1761
|
-
return;
|
|
1762
|
-
}
|
|
1763
|
-
const [action2, ...props] = item;
|
|
1764
|
-
return match(action2, props, {
|
|
1765
|
-
ctx: context,
|
|
1766
|
-
data: latest[1]
|
|
1767
|
-
});
|
|
1768
|
-
});
|
|
1769
|
-
if (!context.meta.goingBack) {
|
|
1770
|
-
context.meta.restoring = false;
|
|
1771
|
-
}
|
|
1772
|
-
await render(context);
|
|
1773
|
-
context.meta.restoring = context.meta.goingBack = false;
|
|
1774
|
-
};
|
|
1775
|
-
const { refer, referGuarded } = createReferFunction({
|
|
1776
|
-
story,
|
|
1777
|
-
onUnknownSceneHit
|
|
1778
|
-
});
|
|
1779
|
-
const exit = (force = false, saving = true) => {
|
|
1780
|
-
const ctx = renderer.getContext(MAIN_CONTEXT_KEY);
|
|
1781
|
-
const stack = useStack(ctx);
|
|
1782
|
-
const current = stack.value;
|
|
1783
|
-
const isSaved = () => {
|
|
1784
|
-
const { saves } = storageData.get();
|
|
1785
|
-
const [currentPath, currentData] = stack.value;
|
|
1786
|
-
return saves.some(
|
|
1787
|
-
([path, data2, [date, type2]]) => type2 === "manual" && times.has(date) && dequal(path, currentPath) && dequal(data2, currentData)
|
|
1788
|
-
);
|
|
1789
|
-
};
|
|
1790
|
-
if (interacted > 1 && !force && askBeforeExit && !isSaved()) {
|
|
1791
|
-
renderer.ui.showExitPrompt();
|
|
1792
|
-
return;
|
|
1793
|
-
}
|
|
1794
|
-
if (interacted > 0 && saving) {
|
|
1795
|
-
save("auto");
|
|
1796
|
-
}
|
|
1797
|
-
stack.clear();
|
|
1798
|
-
ctx.clear(EMPTY_SET, EMPTY_SET, { music: EMPTY_SET, sounds: EMPTY_SET }, noop);
|
|
1799
|
-
renderer.ui.showScreen("mainmenu");
|
|
1800
|
-
ctx.audio.destroy();
|
|
1801
|
-
const [time, type] = current[2];
|
|
1802
|
-
if (type === "auto" && interacted <= 1 && times.has(time)) {
|
|
1803
|
-
storageData.update((prev) => {
|
|
1804
|
-
prev.saves = prev.saves.filter((save2) => save2 !== current);
|
|
1805
|
-
return prev;
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
|
-
interactivity(false);
|
|
1809
|
-
times.clear();
|
|
1810
|
-
};
|
|
1811
|
-
const back = async () => {
|
|
1812
|
-
const stack = useStack(MAIN_CONTEXT_KEY);
|
|
1813
|
-
const valueBeforeBack = stack.value;
|
|
1814
|
-
stack.back();
|
|
1815
|
-
if (dequal(valueBeforeBack, stack.value) && !stack.previous) {
|
|
1816
|
-
return;
|
|
1817
|
-
}
|
|
1818
|
-
await restore(stack.value);
|
|
1819
|
-
};
|
|
1820
|
-
const t = (key, lang) => {
|
|
1821
|
-
return translation[lang].internal[key];
|
|
1822
|
-
};
|
|
1823
|
-
const preview = async (save2, name) => {
|
|
1824
|
-
if (isEmpty(story)) {
|
|
1825
|
-
return Promise.resolve({
|
|
1826
|
-
assets: []
|
|
1827
|
-
});
|
|
1828
|
-
}
|
|
1829
|
-
const [path, data2] = save2;
|
|
1830
|
-
const ctx = renderer.getContext(name);
|
|
1831
|
-
const { found } = await refer(path);
|
|
1832
|
-
if (found) ctx.loading(true);
|
|
1833
|
-
const { queue } = await getActionsFromPath({
|
|
1834
|
-
story,
|
|
1835
|
-
path,
|
|
1836
|
-
filter: true,
|
|
1837
|
-
referGuarded
|
|
1838
|
-
});
|
|
1839
|
-
ctx.loading(false);
|
|
1840
|
-
ctx.meta.restoring = true;
|
|
1841
|
-
ctx.meta.preview = true;
|
|
1842
|
-
const processor = createQueueProcessor(queue, {
|
|
1843
|
-
skip: EMPTY_SET
|
|
1844
|
-
});
|
|
1845
|
-
useStack(ctx).push(clone(save2));
|
|
1846
|
-
const assets = [];
|
|
1847
|
-
await processor.run(([action2, ...props]) => {
|
|
1848
|
-
if (isAudioAction(action2)) return;
|
|
1849
|
-
if (action2 === "vibrate") return;
|
|
1850
|
-
if (action2 === "end") return;
|
|
1851
|
-
huntAssets({
|
|
1852
|
-
action: action2,
|
|
1853
|
-
props,
|
|
1854
|
-
mode: preloadAssets,
|
|
1855
|
-
characters,
|
|
1856
|
-
lang: getLanguageFromStore(storageData),
|
|
1857
|
-
volume: getVolumeFromStore(storageData),
|
|
1858
|
-
handle: assets.push.bind(assets)
|
|
1859
|
-
});
|
|
1860
|
-
return match(action2, props, {
|
|
1861
|
-
ctx,
|
|
1862
|
-
data: data2
|
|
1863
|
-
});
|
|
1864
|
-
});
|
|
1865
|
-
return {
|
|
1866
|
-
assets
|
|
1867
|
-
};
|
|
1868
|
-
};
|
|
1869
|
-
const removeContext = (name) => {
|
|
1870
|
-
STACK_MAP.delete(name);
|
|
1871
|
-
};
|
|
1872
|
-
const getStateAtCtx = (context) => {
|
|
1873
|
-
return useStack(context).value[1];
|
|
1874
|
-
};
|
|
1875
|
-
const getStateFunction = (context) => {
|
|
1876
|
-
const stack = useStack(context);
|
|
1877
|
-
const state = (value) => {
|
|
1878
|
-
const _state = getStateAtCtx(context);
|
|
1879
|
-
if (!value) {
|
|
1880
|
-
return _state;
|
|
1881
|
-
}
|
|
1882
|
-
const prev = _state;
|
|
1883
|
-
const val = isFunction(value) ? value(prev) : merge(prev, value);
|
|
1884
|
-
stack.value[1] = val;
|
|
1885
|
-
return void 0;
|
|
1886
|
-
};
|
|
1887
|
-
return state;
|
|
1888
|
-
};
|
|
1889
|
-
const getLanguageDisplayName = (lang) => {
|
|
1890
|
-
const language = translation[lang];
|
|
1891
|
-
if (DEV && !language) {
|
|
1892
|
-
throw new Error(
|
|
1893
|
-
`Attempt to use unsupported language "${language}". Supported languages: ${languages.join(", ")}.`
|
|
1894
|
-
);
|
|
1895
|
-
}
|
|
1896
|
-
return capitalize(language.nameOverride || getIntlLanguageDisplayName(lang));
|
|
1897
|
-
};
|
|
1898
|
-
const clearCustomAction = (ctx, fn) => {
|
|
1899
|
-
getCustomActionHolder(ctx, fn).cleanup();
|
|
1900
|
-
};
|
|
1901
|
-
const getResourseTypeForRenderer = (url) => {
|
|
1902
|
-
return getResourseType({
|
|
1903
|
-
url,
|
|
1904
|
-
request
|
|
1905
|
-
});
|
|
1906
|
-
};
|
|
1907
|
-
const getCharacterColor = (c) => {
|
|
1908
|
-
return c in characters ? characters[c].color : "#000000";
|
|
1909
|
-
};
|
|
1910
|
-
const getCharacterAssets = (character, emotion) => {
|
|
1911
|
-
return toArray(characters[character].emotions[emotion]).map(handleImageAsset);
|
|
1912
|
-
};
|
|
1913
|
-
const getCharacterName = (character) => {
|
|
1914
|
-
const c = character;
|
|
1915
|
-
const cs = characters;
|
|
1916
|
-
const [lang] = storageData.get().meta;
|
|
1917
|
-
if (c && c in cs) {
|
|
1918
|
-
const block = cs[c].name;
|
|
1919
|
-
if (typeof block === "string") {
|
|
1920
|
-
return block;
|
|
1921
|
-
}
|
|
1922
|
-
if (lang in block) {
|
|
1923
|
-
return block[lang];
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
return String(c) || "";
|
|
1927
|
-
};
|
|
1928
|
-
const getDialogOverview = async () => {
|
|
1929
|
-
const { value: save2 } = useStack(MAIN_CONTEXT_KEY);
|
|
1930
|
-
const stateSnapshots = save2[3];
|
|
1931
|
-
if (stateSnapshots.length == 0) {
|
|
1932
|
-
return [];
|
|
1933
|
-
}
|
|
1934
|
-
const { queue } = await getActionsFromPath({
|
|
1935
|
-
story,
|
|
1936
|
-
path: save2[0],
|
|
1937
|
-
filter: false,
|
|
1938
|
-
referGuarded
|
|
1939
|
-
});
|
|
1940
|
-
const [lang] = storageData.get().meta;
|
|
1941
|
-
const dialogItems = [];
|
|
1942
|
-
for (let p = 0, a = stateSnapshots.length, i = queue.length - 1; a > 0 && i > 0; i--) {
|
|
1943
|
-
const action2 = queue[i];
|
|
1944
|
-
if (action2[0] === "dialog") {
|
|
1945
|
-
const [_, name, text] = action2;
|
|
1946
|
-
let voice = void 0;
|
|
1947
|
-
for (let j = i - 1; j > p && j > 0; j--) {
|
|
1948
|
-
const action3 = queue[j];
|
|
1949
|
-
if (isUserRequiredAction(action3) || isSkippedDuringRestore(action3[0])) break;
|
|
1950
|
-
if (action3[0] === "stopVoice") break;
|
|
1951
|
-
if (action3[0] === "voice") {
|
|
1952
|
-
voice = action3[1];
|
|
1953
|
-
break;
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
dialogItems.push({
|
|
1957
|
-
name,
|
|
1958
|
-
text,
|
|
1959
|
-
voice
|
|
1960
|
-
});
|
|
1961
|
-
p = i;
|
|
1962
|
-
a--;
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
const entries = dialogItems.reverse().map(({ name, text, voice }, i) => {
|
|
1966
|
-
const state = stateSnapshots[i];
|
|
1967
|
-
const audioSource = isString(voice) ? voice : isAsset(voice) ? voice : voice == void 0 ? voice : voice[lang];
|
|
1968
|
-
name = name ? getCharacterName(name) : "";
|
|
1969
|
-
return {
|
|
1970
|
-
name: templateReplace(name, state),
|
|
1971
|
-
text: templateReplace(text, state),
|
|
1972
|
-
voice: audioSource ? handleAudioAsset(audioSource) : ""
|
|
1973
|
-
};
|
|
1974
|
-
});
|
|
1975
|
-
return entries;
|
|
1976
|
-
};
|
|
1977
|
-
const renderer = createRenderer({
|
|
1978
|
-
mainContextKey: MAIN_CONTEXT_KEY,
|
|
1979
|
-
characters: getCharactersData(characters),
|
|
1980
|
-
characterAssetSizes,
|
|
1981
|
-
set: set2,
|
|
1982
|
-
restore,
|
|
1983
|
-
save,
|
|
1984
|
-
newGame,
|
|
1985
|
-
exit,
|
|
1986
|
-
back,
|
|
1987
|
-
t,
|
|
1988
|
-
preview,
|
|
1989
|
-
removeContext,
|
|
1990
|
-
getStateFunction,
|
|
1991
|
-
clearCustomAction,
|
|
1992
|
-
languages,
|
|
1993
|
-
storageData,
|
|
1994
|
-
coreData,
|
|
1995
|
-
getLanguageDisplayName,
|
|
1996
|
-
getCharacterColor,
|
|
1997
|
-
getCharacterAssets,
|
|
1998
|
-
getDialogOverview,
|
|
1999
|
-
getResourseType: getResourseTypeForRenderer
|
|
2000
|
-
});
|
|
2001
|
-
const useStack = createUseStackFunction(renderer);
|
|
2002
|
-
useStack(MAIN_CONTEXT_KEY).push(initial);
|
|
2003
|
-
const UIInstance = renderer.ui.start();
|
|
2004
|
-
const enmemory = (ctx) => {
|
|
2005
|
-
if (ctx.meta.restoring) return;
|
|
2006
|
-
const stack = useStack(ctx);
|
|
2007
|
-
const current = clone(stack.value);
|
|
2008
|
-
current[2][1] = "auto";
|
|
2009
|
-
stack.push(current);
|
|
2010
|
-
save("auto");
|
|
2011
|
-
};
|
|
2012
|
-
const next = (ctx) => {
|
|
2013
|
-
const stack = useStack(ctx);
|
|
2014
|
-
const path = stack.value[0];
|
|
2015
|
-
nextPath(path);
|
|
2016
|
-
};
|
|
2017
|
-
const matchActionOptions = {
|
|
2018
|
-
getContext: renderer.getContext,
|
|
2019
|
-
push(ctx) {
|
|
2020
|
-
if (ctx.meta.restoring) return;
|
|
2021
|
-
next(ctx);
|
|
2022
|
-
render(ctx);
|
|
2023
|
-
},
|
|
2024
|
-
forward(ctx) {
|
|
2025
|
-
if (!ctx.meta.preview) enmemory(ctx);
|
|
2026
|
-
matchActionOptions.push(ctx);
|
|
2027
|
-
if (!ctx.meta.preview) interactivity(true);
|
|
2028
|
-
},
|
|
2029
|
-
async onBeforeActionCall({ action: action2, props, ctx }) {
|
|
2030
|
-
if (preloadAssets !== "automatic") return;
|
|
2031
|
-
if (ctx.meta.preview || ctx.meta.restoring) return;
|
|
2032
|
-
if (!isBlockingAction([action2, ...props])) return;
|
|
2033
|
-
try {
|
|
2034
|
-
const collection = await collectActionsBeforeBlockingAction({
|
|
2035
|
-
path: nextPath(clone(useStack(ctx).value[0])),
|
|
2036
|
-
refer: referGuarded,
|
|
2037
|
-
clone
|
|
2038
|
-
});
|
|
2039
|
-
for (const [action3, ...props2] of collection) {
|
|
2040
|
-
huntAssets({
|
|
2041
|
-
action: action3,
|
|
2042
|
-
props: props2,
|
|
2043
|
-
mode: preloadAssets,
|
|
2044
|
-
characters,
|
|
2045
|
-
lang: getLanguageFromStore(storageData),
|
|
2046
|
-
volume: getVolumeFromStore(storageData),
|
|
2047
|
-
handle: enqueueAssetForPreloading
|
|
2048
|
-
});
|
|
2049
|
-
}
|
|
2050
|
-
handleAssetsPreloading({
|
|
2051
|
-
...renderer.misc,
|
|
2052
|
-
request,
|
|
2053
|
-
limiter: limitAssetsDownload
|
|
2054
|
-
});
|
|
2055
|
-
} catch (cause) {
|
|
2056
|
-
console.error(cause);
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
};
|
|
2060
|
-
const { match, nativeActions } = matchAction(matchActionOptions, {
|
|
2061
|
-
wait({ ctx, data: data2, push }, [time]) {
|
|
2062
|
-
if (ctx.meta.restoring) return;
|
|
2063
|
-
setTimeout(push, isFunction(time) ? time(data2) : time);
|
|
2064
|
-
},
|
|
2065
|
-
showBackground({ ctx, push }, [background]) {
|
|
2066
|
-
if (isString(background) || isAsset(background)) {
|
|
2067
|
-
ctx.background({
|
|
2068
|
-
all: handleImageAsset(background)
|
|
2069
|
-
});
|
|
2070
|
-
} else {
|
|
2071
|
-
ctx.background(
|
|
2072
|
-
Object.fromEntries(Object.entries(background).map(([media, asset2]) => [media, handleImageAsset(asset2)]))
|
|
2073
|
-
);
|
|
2074
|
-
}
|
|
2075
|
-
push();
|
|
2076
|
-
},
|
|
2077
|
-
playMusic({ ctx, push }, [source]) {
|
|
2078
|
-
ctx.audio.music(handleAudioAsset(source), "music").play(true);
|
|
2079
|
-
push();
|
|
2080
|
-
},
|
|
2081
|
-
pauseMusic({ ctx, push }, [source]) {
|
|
2082
|
-
ctx.audio.music(handleAudioAsset(source), "music").pause();
|
|
2083
|
-
push();
|
|
2084
|
-
},
|
|
2085
|
-
stopMusic({ ctx, push }, [source]) {
|
|
2086
|
-
ctx.audio.music(handleAudioAsset(source), "music").stop();
|
|
2087
|
-
push();
|
|
2088
|
-
},
|
|
2089
|
-
playSound({ ctx, push }, [source, loop]) {
|
|
2090
|
-
ctx.audio.music(handleAudioAsset(source), "sound").play(loop || false);
|
|
2091
|
-
push();
|
|
2092
|
-
},
|
|
2093
|
-
pauseSound({ ctx, push }, [source]) {
|
|
2094
|
-
ctx.audio.music(handleAudioAsset(source), "sound").pause();
|
|
2095
|
-
push();
|
|
2096
|
-
},
|
|
2097
|
-
stopSound({ ctx, push }, [source]) {
|
|
2098
|
-
ctx.audio.music(handleAudioAsset(source), "sound").stop();
|
|
2099
|
-
push();
|
|
2100
|
-
},
|
|
2101
|
-
voice({ ctx, push }, [source]) {
|
|
2102
|
-
const [lang] = storageData.get().meta;
|
|
2103
|
-
const audioSource = isString(source) ? source : isAsset(source) ? source : source[lang];
|
|
2104
|
-
if (!audioSource) {
|
|
2105
|
-
push();
|
|
2106
|
-
return;
|
|
2107
|
-
}
|
|
2108
|
-
ctx.audio.voice(handleAudioAsset(audioSource));
|
|
2109
|
-
push();
|
|
2110
|
-
},
|
|
2111
|
-
stopVoice({ ctx, push }) {
|
|
2112
|
-
ctx.audio.voiceStop();
|
|
2113
|
-
push();
|
|
2114
|
-
},
|
|
2115
|
-
showCharacter({ ctx, push }, [character, emotion, className, style]) {
|
|
2116
|
-
emotion ??= defaultEmotions[character];
|
|
2117
|
-
if (DEV && !emotion) {
|
|
2118
|
-
throw new Error(`Attemp to show character "${character}" without emotion provided.`);
|
|
2119
|
-
}
|
|
2120
|
-
if (!emotion) return;
|
|
2121
|
-
if (DEV && !characters[character].emotions[emotion]) {
|
|
2122
|
-
throw new Error(`Attempt to show character "${character}" with unknown emotion "${emotion}"`);
|
|
2123
|
-
}
|
|
2124
|
-
const handle = ctx.character(character);
|
|
2125
|
-
handle.append(className, style, ctx.meta.restoring);
|
|
2126
|
-
handle.emotion(emotion, true);
|
|
2127
|
-
push();
|
|
2128
|
-
},
|
|
2129
|
-
hideCharacter({ ctx, push }, [character, className, style, duration]) {
|
|
2130
|
-
ctx.character(character).remove(className, style, duration, ctx.meta.restoring).then(push);
|
|
2131
|
-
},
|
|
2132
|
-
dialog({ ctx, data: data2, forward }, [character, content, emotion]) {
|
|
2133
|
-
const name = getCharacterName(character);
|
|
2134
|
-
const stack = useStack(ctx);
|
|
2135
|
-
if (!ctx.meta.restoring && !ctx.meta.goingBack) {
|
|
2136
|
-
stack.value[3].push(clone(data2));
|
|
2137
|
-
}
|
|
2138
|
-
ctx.clearBlockingActions("dialog");
|
|
2139
|
-
ctx.dialog(templateReplace(content, data2), templateReplace(name, data2), character, emotion, forward);
|
|
2140
|
-
},
|
|
2141
|
-
function({ ctx, push }, [fn]) {
|
|
2142
|
-
const { restoring, goingBack, preview: preview2 } = ctx.meta;
|
|
2143
|
-
const result = fn({
|
|
2144
|
-
lang: getLanguageFromStore(storageData),
|
|
2145
|
-
goingBack,
|
|
2146
|
-
restoring,
|
|
2147
|
-
preview: preview2,
|
|
2148
|
-
state: getStateFunction(ctx)
|
|
2149
|
-
});
|
|
2150
|
-
if (!ctx.meta.restoring) {
|
|
2151
|
-
result ? result.then(push) : push();
|
|
2152
|
-
}
|
|
2153
|
-
return result;
|
|
2154
|
-
},
|
|
2155
|
-
choice({ ctx, data: data2 }, [question, ...choices]) {
|
|
2156
|
-
const isWithoutQuestion = Array.isArray(question);
|
|
2157
|
-
if (isWithoutQuestion) {
|
|
2158
|
-
choices.unshift(question);
|
|
2159
|
-
question = "";
|
|
2160
|
-
}
|
|
2161
|
-
const transformedChoices = choices.map(([content, _children, active, visible, onSelect, image]) => {
|
|
2162
|
-
const active$ = store(false);
|
|
2163
|
-
const visible$ = store(false);
|
|
2164
|
-
const lang = getLanguageFromStore(storageData);
|
|
2165
|
-
const getCheckValue = (fn) => {
|
|
2166
|
-
if (!fn) {
|
|
2167
|
-
return true;
|
|
2168
|
-
}
|
|
2169
|
-
return fn({
|
|
2170
|
-
lang,
|
|
2171
|
-
state: getStateAtCtx(ctx)
|
|
2172
|
-
});
|
|
2173
|
-
};
|
|
2174
|
-
const update = () => {
|
|
2175
|
-
active$.set(getCheckValue(active));
|
|
2176
|
-
visible$.set(getCheckValue(visible));
|
|
2177
|
-
};
|
|
2178
|
-
update();
|
|
2179
|
-
const onSelectGuarded = onSelect || noop;
|
|
2180
|
-
const onSelectWrapped = () => {
|
|
2181
|
-
onSelectGuarded({
|
|
2182
|
-
recompute: update
|
|
2183
|
-
});
|
|
2184
|
-
};
|
|
2185
|
-
const imageValue = image ? handleImageAsset(image) : "";
|
|
2186
|
-
return [templateReplace(content, data2), active$, visible$, onSelectWrapped, imageValue];
|
|
2187
|
-
});
|
|
2188
|
-
if (DEV && transformedChoices.length === 0) {
|
|
2189
|
-
throw new Error(
|
|
2190
|
-
`Running choice without variants to choose from, look at how to use Choice action properly [https://novely.pages.dev/guide/actions/choice#usage]`
|
|
2191
|
-
);
|
|
2192
|
-
}
|
|
2193
|
-
ctx.clearBlockingActions("choice");
|
|
2194
|
-
ctx.choices(templateReplace(question, data2), transformedChoices, (selected) => {
|
|
2195
|
-
if (!ctx.meta.preview) {
|
|
2196
|
-
enmemory(ctx);
|
|
2197
|
-
}
|
|
2198
|
-
const stack = useStack(ctx);
|
|
2199
|
-
const offset = isWithoutQuestion ? 0 : 1;
|
|
2200
|
-
if (DEV && !transformedChoices[selected]) {
|
|
2201
|
-
throw new Error("Choice children is empty, either add content there or make item not selectable");
|
|
2202
|
-
}
|
|
2203
|
-
stack.value[0].push(["choice", selected + offset], [null, 0]);
|
|
2204
|
-
render(ctx);
|
|
2205
|
-
interactivity(true);
|
|
2206
|
-
});
|
|
2207
|
-
},
|
|
2208
|
-
jump({ ctx, data: data2 }, [scene]) {
|
|
2209
|
-
const stack = useStack(ctx);
|
|
2210
|
-
stack.value[0] = [
|
|
2211
|
-
["jump", scene],
|
|
2212
|
-
[null, -1]
|
|
2213
|
-
];
|
|
2214
|
-
stack.value[3] = [];
|
|
2215
|
-
match("clear", [], {
|
|
2216
|
-
ctx,
|
|
2217
|
-
data: data2
|
|
2218
|
-
});
|
|
2219
|
-
},
|
|
2220
|
-
clear({ ctx, push }, [keep, characters2, audio2]) {
|
|
2221
|
-
ctx.vibrate(0);
|
|
2222
|
-
ctx.clear(
|
|
2223
|
-
keep || EMPTY_SET,
|
|
2224
|
-
characters2 || EMPTY_SET,
|
|
2225
|
-
audio2 || { music: EMPTY_SET, sounds: EMPTY_SET },
|
|
2226
|
-
push
|
|
2227
|
-
);
|
|
2228
|
-
},
|
|
2229
|
-
condition({ ctx, data: data2 }, [condition, variants]) {
|
|
2230
|
-
if (DEV && Object.values(variants).length === 0) {
|
|
2231
|
-
throw new Error(`Attempt to use Condition action with empty variants object`);
|
|
2232
|
-
}
|
|
2233
|
-
if (!ctx.meta.restoring) {
|
|
2234
|
-
const val = String(condition(data2));
|
|
2235
|
-
if (DEV && !variants[val]) {
|
|
2236
|
-
throw new Error(`Attempt to go to unknown variant "${val}"`);
|
|
2237
|
-
}
|
|
2238
|
-
if (DEV && variants[val].length === 0) {
|
|
2239
|
-
throw new Error(`Attempt to go to empty variant "${val}"`);
|
|
2240
|
-
}
|
|
2241
|
-
const stack = useStack(ctx);
|
|
2242
|
-
stack.value[0].push(["condition", val], [null, 0]);
|
|
2243
|
-
render(ctx);
|
|
2244
|
-
}
|
|
2245
|
-
},
|
|
2246
|
-
end({ ctx }) {
|
|
2247
|
-
if (ctx.meta.preview) return;
|
|
2248
|
-
exit(true, false);
|
|
2249
|
-
},
|
|
2250
|
-
input({ ctx, data: data2, forward }, [question, onInput, setup]) {
|
|
2251
|
-
ctx.clearBlockingActions("input");
|
|
2252
|
-
ctx.input(templateReplace(question, data2), onInput, setup || noop, forward);
|
|
2253
|
-
},
|
|
2254
|
-
custom({ ctx, push }, [fn]) {
|
|
2255
|
-
if (fn.requireUserAction) {
|
|
2256
|
-
ctx.clearBlockingActions(void 0);
|
|
2257
|
-
}
|
|
2258
|
-
const state = getStateFunction(ctx);
|
|
2259
|
-
const lang = getLanguageFromStore(storageData);
|
|
2260
|
-
const result = handleCustomAction(ctx, fn, {
|
|
2261
|
-
...ctx.custom(fn),
|
|
2262
|
-
state,
|
|
2263
|
-
lang,
|
|
2264
|
-
getStack: useStack,
|
|
2265
|
-
templateReplace
|
|
2266
|
-
});
|
|
2267
|
-
const next2 = () => {
|
|
2268
|
-
if (fn.requireUserAction && !ctx.meta.preview) {
|
|
2269
|
-
enmemory(ctx);
|
|
2270
|
-
interactivity(true);
|
|
2271
|
-
}
|
|
2272
|
-
push();
|
|
2273
|
-
};
|
|
2274
|
-
if (!ctx.meta.restoring || ctx.meta.goingBack) {
|
|
2275
|
-
if (isPromise(result)) {
|
|
2276
|
-
result.then(next2);
|
|
2277
|
-
} else {
|
|
2278
|
-
next2();
|
|
2279
|
-
}
|
|
2280
|
-
}
|
|
2281
|
-
return result;
|
|
2282
|
-
},
|
|
2283
|
-
vibrate({ ctx, push }, pattern) {
|
|
2284
|
-
ctx.vibrate(pattern);
|
|
2285
|
-
push();
|
|
2286
|
-
},
|
|
2287
|
-
next({ push }) {
|
|
2288
|
-
push();
|
|
2289
|
-
},
|
|
2290
|
-
animateCharacter({ ctx, push }, [character, className]) {
|
|
2291
|
-
const classes = className.split(" ");
|
|
2292
|
-
if (DEV && classes.length === 0) {
|
|
2293
|
-
throw new Error(
|
|
2294
|
-
"Attempt to use AnimateCharacter without classes. Classes should be provided [https://novely.pages.dev/guide/actions/animateCharacter.html]"
|
|
2295
|
-
);
|
|
2296
|
-
}
|
|
2297
|
-
if (ctx.meta.preview) return;
|
|
2298
|
-
ctx.character(character).animate(classes);
|
|
2299
|
-
push();
|
|
2300
|
-
},
|
|
2301
|
-
text({ ctx, data: data2, forward }, text) {
|
|
2302
|
-
const string = text.map((content) => templateReplace(content, data2)).join(" ");
|
|
2303
|
-
if (DEV && string.length === 0) {
|
|
2304
|
-
throw new Error(`Action Text was called with empty string or array`);
|
|
2305
|
-
}
|
|
2306
|
-
ctx.clearBlockingActions("text");
|
|
2307
|
-
ctx.text(string, forward);
|
|
2308
|
-
},
|
|
2309
|
-
async exit({ ctx, data: data2 }) {
|
|
2310
|
-
if (ctx.meta.restoring) return;
|
|
2311
|
-
const { exitImpossible } = await exitPath({
|
|
2312
|
-
path: useStack(ctx).value[0],
|
|
2313
|
-
refer: referGuarded,
|
|
2314
|
-
onExitImpossible: () => {
|
|
2315
|
-
match("end", [], {
|
|
2316
|
-
ctx,
|
|
2317
|
-
data: data2
|
|
2318
|
-
});
|
|
2319
|
-
}
|
|
2320
|
-
});
|
|
2321
|
-
if (exitImpossible) {
|
|
2322
|
-
ctx.clearBlockingActions(void 0);
|
|
2323
|
-
return;
|
|
2324
|
-
}
|
|
2325
|
-
render(ctx);
|
|
2326
|
-
},
|
|
2327
|
-
preload({ ctx, push }, [source]) {
|
|
2328
|
-
if (DEV && preloadAssets !== "lazy") {
|
|
2329
|
-
console.error(
|
|
2330
|
-
`You do not need a preload action becase "preloadAssets" strategy was set to "${preloadAssets}"`
|
|
2331
|
-
);
|
|
2332
|
-
}
|
|
2333
|
-
if (!ctx.meta.goingBack && !ctx.meta.restoring && !PRELOADED_ASSETS.has(source)) {
|
|
2334
|
-
PRELOADED_ASSETS.add(renderer.misc.preloadImage(source));
|
|
2335
|
-
}
|
|
2336
|
-
push();
|
|
2337
|
-
},
|
|
2338
|
-
block({ ctx }, [scene]) {
|
|
2339
|
-
if (DEV && !story[scene]) {
|
|
2340
|
-
throw new Error(`Attempt to call Block action with unknown scene "${scene}"`);
|
|
2341
|
-
}
|
|
2342
|
-
if (DEV && story[scene].length === 0) {
|
|
2343
|
-
throw new Error(`Attempt to call Block action with empty scene "${scene}"`);
|
|
2344
|
-
}
|
|
2345
|
-
if (!ctx.meta.restoring) {
|
|
2346
|
-
const stack = useStack(ctx);
|
|
2347
|
-
stack.value[0].push(["block", scene], [null, 0]);
|
|
2348
|
-
render(ctx);
|
|
2349
|
-
}
|
|
2350
|
-
}
|
|
2351
|
-
});
|
|
2352
|
-
const action = buildActionObject({
|
|
2353
|
-
rendererActions: renderer.actions,
|
|
2354
|
-
nativeActions,
|
|
2355
|
-
characters,
|
|
2356
|
-
preloadAssets,
|
|
2357
|
-
storageData
|
|
2358
|
-
});
|
|
2359
|
-
const render = async (ctx) => {
|
|
2360
|
-
const stack = useStack(ctx);
|
|
2361
|
-
const [path, state] = stack.value;
|
|
2362
|
-
const { found, value } = await refer(path);
|
|
2363
|
-
if (found) {
|
|
2364
|
-
ctx.loading(true);
|
|
2365
|
-
}
|
|
2366
|
-
const referred = await value;
|
|
2367
|
-
if (found) {
|
|
2368
|
-
ctx.loading(false);
|
|
2369
|
-
}
|
|
2370
|
-
if (isAction(referred)) {
|
|
2371
|
-
const [action2, ...props] = referred;
|
|
2372
|
-
match(action2, props, {
|
|
2373
|
-
ctx,
|
|
2374
|
-
data: state
|
|
2375
|
-
});
|
|
2376
|
-
} else if (Object.values(story).some((branch) => branch === referred)) {
|
|
2377
|
-
match("end", [], {
|
|
2378
|
-
ctx,
|
|
2379
|
-
data: state
|
|
2380
|
-
});
|
|
2381
|
-
} else {
|
|
2382
|
-
match("exit", [], {
|
|
2383
|
-
ctx,
|
|
2384
|
-
data: state
|
|
2385
|
-
});
|
|
2386
|
-
}
|
|
2387
|
-
};
|
|
2388
|
-
const interactivity = (value = false) => {
|
|
2389
|
-
interacted = value ? interacted + 1 : 0;
|
|
2390
|
-
};
|
|
2391
|
-
const templateReplace = (content, values) => {
|
|
2392
|
-
const {
|
|
2393
|
-
data: data2,
|
|
2394
|
-
meta: [lang]
|
|
2395
|
-
} = storageData.get();
|
|
2396
|
-
const obj = values || data2;
|
|
2397
|
-
const str = flattenAllowedContent(!isFunction(content) && !isString(content) ? content[lang] : content, obj);
|
|
2398
|
-
const t2 = translation[lang];
|
|
2399
|
-
const pluralRules = (t2.plural || t2.actions) && new Intl.PluralRules(t2.tag || lang);
|
|
2400
|
-
return replace(str, obj, t2.plural, t2.actions, pluralRules);
|
|
2401
|
-
};
|
|
2402
|
-
const data = (value) => {
|
|
2403
|
-
const _data = storageData.get().data;
|
|
2404
|
-
if (!value) return _data;
|
|
2405
|
-
const val = isFunction(value) ? value(_data) : merge(_data, value);
|
|
2406
|
-
storageData.update((prev) => {
|
|
2407
|
-
prev.data = val;
|
|
2408
|
-
return prev;
|
|
2409
|
-
});
|
|
2410
|
-
return void 0;
|
|
2411
|
-
};
|
|
2412
|
-
const typeEssentials = {
|
|
2413
|
-
l: null,
|
|
2414
|
-
s: null,
|
|
2415
|
-
d: null,
|
|
2416
|
-
c: null
|
|
2417
|
-
};
|
|
2418
|
-
const getCurrentStorageData = () => {
|
|
2419
|
-
return coreData.get().dataLoaded ? clone(storageData.get()) : null;
|
|
2420
|
-
};
|
|
2421
|
-
const setStorageData = (data2) => {
|
|
2422
|
-
if (destroyed) {
|
|
2423
|
-
if (DEV) {
|
|
2424
|
-
throw new Error(
|
|
2425
|
-
`function \`setStorageData\` was called after novely instance was destroyed. Data is not updater nor synced after destroy.`
|
|
2426
|
-
);
|
|
2427
|
-
}
|
|
2428
|
-
return;
|
|
2429
|
-
}
|
|
2430
|
-
storageData.set(data2);
|
|
2431
|
-
};
|
|
2432
|
-
return {
|
|
2433
|
-
/**
|
|
2434
|
-
* Function to set game script
|
|
2435
|
-
*
|
|
2436
|
-
* @example
|
|
2437
|
-
* ```ts
|
|
2438
|
-
* engine.script({
|
|
2439
|
-
* start: [
|
|
2440
|
-
* action.function(() => {})
|
|
2441
|
-
* ]
|
|
2442
|
-
* })
|
|
2443
|
-
* ```
|
|
2444
|
-
*/
|
|
2445
|
-
script,
|
|
2446
|
-
/**
|
|
2447
|
-
* Get actions
|
|
2448
|
-
*
|
|
2449
|
-
* @example
|
|
2450
|
-
* ```ts
|
|
2451
|
-
* engine.script({
|
|
2452
|
-
* start: [
|
|
2453
|
-
* action.function(() => {})
|
|
2454
|
-
* ]
|
|
2455
|
-
* })
|
|
2456
|
-
* ```
|
|
2457
|
-
*/
|
|
2458
|
-
action,
|
|
2459
|
-
/**
|
|
2460
|
-
* State bound to `$MAIN` game context
|
|
2461
|
-
* @deprecated Use `state` function provided from action arguments
|
|
2462
|
-
*/
|
|
2463
|
-
state: getStateFunction(MAIN_CONTEXT_KEY),
|
|
2464
|
-
/**
|
|
2465
|
-
* Store data between games
|
|
2466
|
-
*
|
|
2467
|
-
* @example
|
|
2468
|
-
* ```ts
|
|
2469
|
-
* engine.script({
|
|
2470
|
-
* start: [
|
|
2471
|
-
* action.function(() => {
|
|
2472
|
-
* // Paid content should be purchased only once
|
|
2473
|
-
* // So it will be available in any save
|
|
2474
|
-
* data({ paid_content_purchased: true })
|
|
2475
|
-
* })
|
|
2476
|
-
* ]
|
|
2477
|
-
* })
|
|
2478
|
-
* ```
|
|
2479
|
-
*/
|
|
2480
|
-
data,
|
|
2481
|
-
/**
|
|
2482
|
-
* Used in combination with type utilities
|
|
2483
|
-
*
|
|
2484
|
-
* @example
|
|
2485
|
-
* ```ts
|
|
2486
|
-
* import type { ConditionParams, StateFunction } from '@novely/core';
|
|
2487
|
-
*
|
|
2488
|
-
* const conditionCheck = (state: StateFunction<ConditionParams<typeof engine.typeEssintials>>) => {
|
|
2489
|
-
* return state.age >= 18;
|
|
2490
|
-
* }
|
|
2491
|
-
* ```
|
|
2492
|
-
*/
|
|
2493
|
-
typeEssentials,
|
|
2494
|
-
/**
|
|
2495
|
-
* Replaces content inside {{braces}} using global data
|
|
2496
|
-
* @example
|
|
2497
|
-
* ```ts
|
|
2498
|
-
* data({ name: 'Alexei' })
|
|
2499
|
-
*
|
|
2500
|
-
* templateReplace('{{name}} is our hero')
|
|
2501
|
-
* templateReplace({
|
|
2502
|
-
* en: (data) => 'Hello, ' + data.name
|
|
2503
|
-
* })
|
|
2504
|
-
* ```
|
|
2505
|
-
*/
|
|
2506
|
-
templateReplace(content) {
|
|
2507
|
-
return templateReplace(content);
|
|
2508
|
-
},
|
|
2509
|
-
/**
|
|
2510
|
-
* Same as `templateReplace` but uses state and requires explicitly providing it
|
|
2511
|
-
*/
|
|
2512
|
-
templateReplaceState(content, state) {
|
|
2513
|
-
return templateReplace(content, state);
|
|
2514
|
-
},
|
|
2515
|
-
/**
|
|
2516
|
-
* Cancel data loading, hide UI, ignore page change events
|
|
2517
|
-
* Data updates still will work in case Novely already was loaded
|
|
2518
|
-
*/
|
|
2519
|
-
destroy() {
|
|
2520
|
-
dataLoaded.cancel();
|
|
2521
|
-
UIInstance.unmount();
|
|
2522
|
-
unsubscribeFromBrowserVisibilityChange();
|
|
2523
|
-
destroyed = true;
|
|
2524
|
-
},
|
|
2525
|
-
/**
|
|
2526
|
-
* Funtion to get current storage data
|
|
2527
|
-
*
|
|
2528
|
-
* @example
|
|
2529
|
-
* ```ts
|
|
2530
|
-
* const currentStorageData = engine.getCurrentStorageData();
|
|
2531
|
-
* ```
|
|
2532
|
-
*/
|
|
2533
|
-
getCurrentStorageData,
|
|
2534
|
-
/**
|
|
2535
|
-
* Function to set storage data. Using this function is not recommended.
|
|
2536
|
-
*
|
|
2537
|
-
* @deprecated
|
|
2538
|
-
* @example
|
|
2539
|
-
* ```ts
|
|
2540
|
-
* const currentStorageData = engine.getCurrentStorageData();
|
|
2541
|
-
*
|
|
2542
|
-
* if (currentStorageData) {
|
|
2543
|
-
* // update music volume
|
|
2544
|
-
* currentStorageData.meta[2] = 1;
|
|
2545
|
-
*
|
|
2546
|
-
* setStorageData(currentStorageData)
|
|
2547
|
-
* }
|
|
2548
|
-
* ```
|
|
2549
|
-
*/
|
|
2550
|
-
setStorageData
|
|
2551
|
-
};
|
|
2552
|
-
};
|
|
2553
|
-
|
|
2554
|
-
// src/extend-actions.ts
|
|
2555
|
-
var extendAction = (base, extension) => {
|
|
2556
|
-
return {
|
|
2557
|
-
...extension,
|
|
2558
|
-
...base
|
|
2559
|
-
};
|
|
2560
|
-
};
|
|
2561
|
-
|
|
2562
|
-
// src/translations.ts
|
|
2563
|
-
var RU = {
|
|
2564
|
-
NewGame: "\u041D\u043E\u0432\u0430\u044F \u0438\u0433\u0440\u0430",
|
|
2565
|
-
HomeScreen: "\u0413\u043B\u0430\u0432\u043D\u044B\u0439 \u044D\u043A\u0440\u0430\u043D",
|
|
2566
|
-
ToTheGame: "\u041A \u0438\u0433\u0440\u0435",
|
|
2567
|
-
Language: "\u042F\u0437\u044B\u043A",
|
|
2568
|
-
NoSaves: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0439 \u043D\u0435\u0442",
|
|
2569
|
-
LoadSave: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C",
|
|
2570
|
-
Saves: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F",
|
|
2571
|
-
Settings: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438",
|
|
2572
|
-
Sumbit: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C",
|
|
2573
|
-
GoBack: "\u041D\u0430\u0437\u0430\u0434",
|
|
2574
|
-
DoSave: "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435",
|
|
2575
|
-
Auto: "\u0410\u0432\u0442\u043E",
|
|
2576
|
-
Stop: "\u0421\u0442\u043E\u043F",
|
|
2577
|
-
Exit: "\u0412\u044B\u0445\u043E\u0434",
|
|
2578
|
-
Automatic: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u043E\u0435",
|
|
2579
|
-
Manual: "\u0420\u0443\u0447\u043D\u043E\u0435",
|
|
2580
|
-
Remove: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
|
|
2581
|
-
LoadASaveFrom: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435 \u043E\u0442",
|
|
2582
|
-
DeleteASaveFrom: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435 \u043E\u0442",
|
|
2583
|
-
TextSpeed: "\u0421\u043A\u043E\u0440\u043E\u0441\u0442\u044C \u0442\u0435\u043A\u0441\u0442\u0430",
|
|
2584
|
-
TextSpeedSlow: "\u041C\u0435\u0434\u043B\u0435\u043D\u043D\u0430\u044F",
|
|
2585
|
-
TextSpeedMedium: "\u0421\u0440\u0435\u0434\u043D\u044F\u044F",
|
|
2586
|
-
TextSpeedFast: "\u0411\u044B\u0441\u0442\u0440\u0430\u044F",
|
|
2587
|
-
TextSpeedAuto: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0430\u044F",
|
|
2588
|
-
CompleteText: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442",
|
|
2589
|
-
GoForward: "\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0432\u043F\u0435\u0440\u0451\u0434",
|
|
2590
|
-
ExitDialogWarning: "\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B, \u0447\u0442\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0432\u044B\u0439\u0442\u0438? \u041F\u0440\u043E\u0433\u0440\u0435\u0441\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D.",
|
|
2591
|
-
ExitDialogExit: "\u0412\u044B\u0439\u0442\u0438",
|
|
2592
|
-
ExitDialogBack: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u0432 \u0438\u0433\u0440\u0443",
|
|
2593
|
-
OpenMenu: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E",
|
|
2594
|
-
CloseMenu: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E",
|
|
2595
|
-
MusicVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u043C\u0443\u0437\u044B\u043A\u0438",
|
|
2596
|
-
SoundVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0437\u0432\u0443\u043A\u043E\u0432",
|
|
2597
|
-
VoiceVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0440\u0435\u0447\u0438",
|
|
2598
|
-
Close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C",
|
|
2599
|
-
DialogOverview: "\u041E\u0431\u0437\u043E\u0440 \u0434\u0438\u0430\u043B\u043E\u0433\u0430"
|
|
2600
|
-
};
|
|
2601
|
-
var EN = {
|
|
2602
|
-
NewGame: "New Game",
|
|
2603
|
-
HomeScreen: "Home Screen",
|
|
2604
|
-
ToTheGame: "To the Game",
|
|
2605
|
-
Language: "Language",
|
|
2606
|
-
NoSaves: "No saves",
|
|
2607
|
-
LoadSave: "Load",
|
|
2608
|
-
Saves: "Saves",
|
|
2609
|
-
Settings: "Settings",
|
|
2610
|
-
Sumbit: "Submit",
|
|
2611
|
-
GoBack: "Go back",
|
|
2612
|
-
DoSave: "Save",
|
|
2613
|
-
Auto: "Auto",
|
|
2614
|
-
Stop: "Stop",
|
|
2615
|
-
Exit: "Exit",
|
|
2616
|
-
Automatic: "Automatic",
|
|
2617
|
-
Manual: "Manual",
|
|
2618
|
-
Remove: "Remove",
|
|
2619
|
-
LoadASaveFrom: "Load a save from",
|
|
2620
|
-
DeleteASaveFrom: "Delete a save from",
|
|
2621
|
-
TextSpeed: "Text Speed",
|
|
2622
|
-
TextSpeedSlow: "Slow",
|
|
2623
|
-
TextSpeedMedium: "Medium",
|
|
2624
|
-
TextSpeedFast: "Fast",
|
|
2625
|
-
TextSpeedAuto: "Auto",
|
|
2626
|
-
CompleteText: "Complete text",
|
|
2627
|
-
GoForward: "Go forward",
|
|
2628
|
-
ExitDialogWarning: "Are you sure you want to exit? Progress will be saved.",
|
|
2629
|
-
ExitDialogExit: "Exit",
|
|
2630
|
-
ExitDialogBack: "Return to game",
|
|
2631
|
-
OpenMenu: "Open menu",
|
|
2632
|
-
CloseMenu: "Close menu",
|
|
2633
|
-
MusicVolume: "Music volume",
|
|
2634
|
-
SoundVolume: "Sound volume",
|
|
2635
|
-
VoiceVolume: "Voice volume",
|
|
2636
|
-
Close: "Close",
|
|
2637
|
-
DialogOverview: "Dialog Overview"
|
|
2638
|
-
};
|
|
2639
|
-
var KK = {
|
|
2640
|
-
NewGame: "\u0416\u0430\u04A3\u0430 \u043E\u0439\u044B\u043D",
|
|
2641
|
-
HomeScreen: "\u041D\u0435\u0433\u0456\u0437\u0433\u0456 \u044D\u043A\u0440\u0430\u043D",
|
|
2642
|
-
ToTheGame: "\u041E\u0439\u044B\u043D\u0493\u0430",
|
|
2643
|
-
Language: "\u0422\u0456\u043B",
|
|
2644
|
-
NoSaves: "\u0421\u0430\u049B\u0442\u0430\u0443 \u0436\u043E\u049B",
|
|
2645
|
-
LoadSave: "\u0416\u04AF\u043A\u0442\u0435\u0443",
|
|
2646
|
-
Saves: "\u0421\u0430\u049B\u0442\u0430\u0443",
|
|
2647
|
-
Settings: "\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043B\u0435\u0440",
|
|
2648
|
-
Sumbit: "\u0420\u0430\u0441\u0442\u0430\u0443",
|
|
2649
|
-
GoBack: "\u0410\u0440\u0442\u049B\u0430",
|
|
2650
|
-
DoSave: "\u0421\u0430\u049B\u0442\u0430\u0443",
|
|
2651
|
-
Auto: "\u0410\u0432\u0442\u043E",
|
|
2652
|
-
Stop: "\u0422\u043E\u049B\u0442\u0430",
|
|
2653
|
-
Exit: "\u0428\u044B\u0493\u0443",
|
|
2654
|
-
Automatic: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0442\u044B",
|
|
2655
|
-
Manual: "\u049A\u043E\u043B\u043C\u0435\u043D",
|
|
2656
|
-
Remove: "\u0416\u043E\u044E",
|
|
2657
|
-
LoadASaveFrom: "\u0421\u0430\u049B\u0442\u0430\u0443\u0434\u044B \u0436\u04AF\u043A\u0442\u0435\u0443",
|
|
2658
|
-
DeleteASaveFrom: "\u0421\u0430\u049B\u0442\u0430\u0443\u0434\u044B \u0436\u043E\u044E",
|
|
2659
|
-
TextSpeed: "\u041C\u04D9\u0442\u0456\u043D \u0416\u044B\u043B\u0434\u0430\u043C\u0434\u044B\u0493\u044B",
|
|
2660
|
-
TextSpeedSlow: "\u0411\u0430\u044F\u0443",
|
|
2661
|
-
TextSpeedMedium: "\u041E\u0440\u0442\u0430\u0448\u0430",
|
|
2662
|
-
TextSpeedFast: "\u0416\u044B\u043B\u0434\u0430\u043C",
|
|
2663
|
-
TextSpeedAuto: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0442\u044B",
|
|
2664
|
-
CompleteText: "\u041C\u04D9\u0442\u0456\u043D\u0434\u0456 \u0430\u044F\u049B\u0442\u0430\u0443",
|
|
2665
|
-
GoForward: "\u0410\u043B\u0493\u0430 \u0436\u044B\u043B\u0436\u0443",
|
|
2666
|
-
ExitDialogWarning: "\u0421\u0456\u0437 \u0448\u044B\u049B\u049B\u044B\u04A3\u044B\u0437 \u043A\u0435\u043B\u0435\u0442\u0456\u043D\u0456\u043D\u0435 \u0441\u0435\u043D\u0456\u043C\u0434\u0456\u0441\u0456\u0437 \u0431\u0435? \u041F\u0440\u043E\u0433\u0440\u0435\u0441\u0441 \u0441\u0430\u049B\u0442\u0430\u043B\u0430\u0434\u044B",
|
|
2667
|
-
ExitDialogExit: "\u0428\u044B\u0493\u0443",
|
|
2668
|
-
ExitDialogBack: "\u041E\u0439\u044B\u043D\u0493\u0430 \u043E\u0440\u0430\u043B\u0443",
|
|
2669
|
-
OpenMenu: "\u041C\u04D9\u0437\u0456\u0440\u0434\u0456 \u0430\u0448\u044B\u04A3\u044B\u0437",
|
|
2670
|
-
CloseMenu: "\u041C\u04D9\u0437\u0456\u0440\u0434\u0456 \u0436\u0430\u0431\u0443",
|
|
2671
|
-
MusicVolume: "\u041C\u0443\u0437\u044B\u043A\u0430\u043D\u044B\u04A3 \u043A\u04E9\u043B\u0435\u043C\u0456",
|
|
2672
|
-
SoundVolume: "\u0414\u044B\u0431\u044B\u0441\u0442\u0430\u0440\u0434\u044B\u04A3 \u043A\u04E9\u043B\u0435\u043C\u0456",
|
|
2673
|
-
VoiceVolume: "\u0421\u04E9\u0439\u043B\u0435\u0443 \u043A\u04E9\u043B\u0435\u043C\u0456",
|
|
2674
|
-
Close: "\u0416\u0430\u0431\u0443",
|
|
2675
|
-
DialogOverview: "\u0414\u0438\u0430\u043B\u043E\u0433\u049B\u0430 \u0428\u043E\u043B\u0443"
|
|
2676
|
-
};
|
|
2677
|
-
var JP = {
|
|
2678
|
-
NewGame: "\u300C\u65B0\u3057\u3044\u30B2\u30FC\u30E0\u300D",
|
|
2679
|
-
HomeScreen: "\u30DB\u30FC\u30E0\u753B\u9762",
|
|
2680
|
-
ToTheGame: "\u300C\u30B2\u30FC\u30E0\u306B\u623B\u308B\u300D",
|
|
2681
|
-
Language: "\u8A00\u8A9E",
|
|
2682
|
-
NoSaves: "\u30CE\u30FC\u30BB\u30FC\u30D6",
|
|
2683
|
-
LoadSave: "\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9",
|
|
2684
|
-
Saves: "\u4FDD\u5B58",
|
|
2685
|
-
Settings: "\u8A2D\u5B9A",
|
|
2686
|
-
Sumbit: "\u78BA\u8A8D",
|
|
2687
|
-
GoBack: "\u300C\u623B\u308B\u300D",
|
|
2688
|
-
DoSave: "\u4FDD\u5B58",
|
|
2689
|
-
Auto: "\u30AA\u30FC\u30C8",
|
|
2690
|
-
Stop: "\u6B62\u307E\u308C",
|
|
2691
|
-
Exit: "\u51FA\u53E3",
|
|
2692
|
-
Automatic: "\u81EA\u52D5",
|
|
2693
|
-
Manual: "\u30DE\u30CB\u30E5\u30A2\u30EB",
|
|
2694
|
-
Remove: "\u524A\u9664",
|
|
2695
|
-
LoadASaveFrom: "\u30ED\u30FC\u30C9\u30BB\u30FC\u30D6\u304B\u3089",
|
|
2696
|
-
DeleteASaveFrom: "\u304B\u3089\u4FDD\u5B58\u3092\u524A\u9664",
|
|
2697
|
-
TextSpeed: "\u30C6\u30AD\u30B9\u30C8\u30B9\u30D4\u30FC\u30C9",
|
|
2698
|
-
TextSpeedSlow: "\u300C\u9045\u3044\u300D",
|
|
2699
|
-
TextSpeedMedium: "\u30DF\u30C7\u30A3\u30A2\u30E0",
|
|
2700
|
-
TextSpeedFast: "\u300C\u901F\u3044\u300D",
|
|
2701
|
-
TextSpeedAuto: "\u81EA\u52D5",
|
|
2702
|
-
CompleteText: "\u30C6\u30AD\u30B9\u30C8\u3092\u5B8C\u6210\u3055\u305B\u308B",
|
|
2703
|
-
GoForward: "\u5148\u306B\u884C\u304F",
|
|
2704
|
-
ExitDialogWarning: "\u672C\u5F53\u306B\u7D42\u4E86\u3057\u307E\u3059\u304B\uFF1F\u9032\u884C\u72B6\u6CC1\u306F\u4FDD\u5B58\u3055\u308C\u307E\u3059",
|
|
2705
|
-
ExitDialogExit: "\u7D42\u4E86",
|
|
2706
|
-
ExitDialogBack: "\u30B2\u30FC\u30E0\u306B\u623B\u308B",
|
|
2707
|
-
OpenMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u958B\u304F",
|
|
2708
|
-
CloseMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B",
|
|
2709
|
-
MusicVolume: "\u97F3\u697D\u306E\u30DC\u30EA\u30E5\u30FC\u30E0",
|
|
2710
|
-
SoundVolume: "\u97F3\u91CF",
|
|
2711
|
-
VoiceVolume: "\u30B9\u30D4\u30FC\u30C1\u306E\u91CF",
|
|
2712
|
-
Close: "\u9589\u3058\u308B",
|
|
2713
|
-
DialogOverview: "\u30C0\u30A4\u30A2\u30ED\u30B0\u306E\u6982\u8981"
|
|
2714
|
-
};
|
|
2715
|
-
|
|
2716
|
-
// src/audio-codecs.ts
|
|
2717
|
-
var cut = (str) => str.replace(/^no$/, "");
|
|
2718
|
-
var audio = new Audio();
|
|
2719
|
-
var canPlay = (type) => !!cut(audio.canPlayType(type));
|
|
2720
|
-
var canPlayMultiple = (...types) => types.some((type) => canPlay(type));
|
|
2721
|
-
var supportsMap = {
|
|
2722
|
-
mp3: canPlayMultiple("audio/mpeg;", "audio/mp3;"),
|
|
2723
|
-
mpeg: canPlay("audio/mpeg;"),
|
|
2724
|
-
opus: canPlay('audio/ogg; codecs="opus"'),
|
|
2725
|
-
ogg: canPlay('audio/ogg; codecs="vorbis"'),
|
|
2726
|
-
oga: canPlay('audio/ogg; codecs="vorbis"'),
|
|
2727
|
-
wav: canPlayMultiple('audio/wav; codecs="1"', "audio/wav;"),
|
|
2728
|
-
aac: canPlay("audio/aac;"),
|
|
2729
|
-
caf: canPlay("audio/x-caf;"),
|
|
2730
|
-
m4a: canPlayMultiple("audio/x-m4a;", "audio/m4a;", "audio/aac;"),
|
|
2731
|
-
m4b: canPlayMultiple("audio/x-m4b;", "audio/m4b;", "audio/aac;"),
|
|
2732
|
-
mp4: canPlayMultiple("audio/x-mp4;", "audio/mp4;", "audio/aac;"),
|
|
2733
|
-
weba: canPlay('audio/webm; codecs="vorbis"'),
|
|
2734
|
-
webm: canPlay('audio/webm; codecs="vorbis"'),
|
|
2735
|
-
dolby: canPlay('audio/mp4; codecs="ec-3"'),
|
|
2736
|
-
flac: canPlayMultiple("audio/x-flac;", "audio/flac;")
|
|
2737
|
-
};
|
|
2738
|
-
|
|
2739
|
-
// src/image-formats.ts
|
|
2740
|
-
var avif = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
|
|
2741
|
-
var jxl = "data:image/jxl;base64,/woIAAAMABKIAgC4AF3lEgAAFSqjjBu8nOv58kOHxbSN6wxttW1hSaLIODZJJ3BIEkkaoCUzGM6qJAE=";
|
|
2742
|
-
var webp = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
|
|
2743
|
-
var supportsFormat = (source) => {
|
|
2744
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
2745
|
-
const img = Object.assign(document.createElement("img"), {
|
|
2746
|
-
src: source
|
|
2747
|
-
});
|
|
2748
|
-
img.onload = img.onerror = () => {
|
|
2749
|
-
resolve(img.height === 2);
|
|
2750
|
-
};
|
|
2751
|
-
return promise;
|
|
2752
|
-
};
|
|
2753
|
-
var supportsMap2 = {
|
|
2754
|
-
avif: false,
|
|
2755
|
-
jxl: false,
|
|
2756
|
-
webp: false
|
|
2757
|
-
};
|
|
2758
|
-
var formatsMap = {
|
|
2759
|
-
avif,
|
|
2760
|
-
jxl,
|
|
2761
|
-
webp
|
|
2762
|
-
};
|
|
2763
|
-
var loadImageFormatsSupport = async () => {
|
|
2764
|
-
const promises = [];
|
|
2765
|
-
for (const [format, source] of Object.entries(formatsMap)) {
|
|
2766
|
-
const promise = supportsFormat(source).then((supported) => {
|
|
2767
|
-
supportsMap2[format] = supported;
|
|
2768
|
-
});
|
|
2769
|
-
promises.push(promise);
|
|
2770
|
-
}
|
|
2771
|
-
await Promise.all(promises);
|
|
2772
|
-
};
|
|
2773
|
-
loadImageFormatsSupport();
|
|
2774
|
-
|
|
2775
|
-
// src/asset.ts
|
|
2776
|
-
var generateRandomId = () => Math.random().toString(36);
|
|
2777
|
-
var getType = memoize(
|
|
2778
|
-
(extensions) => {
|
|
2779
|
-
if (extensions.every((extension) => HOWLER_SUPPORTED_FILE_FORMATS.has(extension))) {
|
|
2780
|
-
return "audio";
|
|
2781
|
-
}
|
|
2782
|
-
if (extensions.every((extension) => SUPPORTED_IMAGE_FILE_FORMATS.has(extension))) {
|
|
2783
|
-
return "image";
|
|
2784
|
-
}
|
|
2785
|
-
throw extensions;
|
|
2786
|
-
},
|
|
2787
|
-
{
|
|
2788
|
-
getCacheKey: (extensions) => extensions.join("~")
|
|
2789
|
-
}
|
|
2790
|
-
);
|
|
2791
|
-
var SUPPORT_MAPS = {
|
|
2792
|
-
image: supportsMap2,
|
|
2793
|
-
audio: supportsMap
|
|
2794
|
-
};
|
|
2795
|
-
var assetPrivate = memoize(
|
|
2796
|
-
(variants) => {
|
|
2797
|
-
if (DEV && variants.length === 0) {
|
|
2798
|
-
throw new Error(`Attempt to use "asset" function without arguments`);
|
|
2799
|
-
}
|
|
2800
|
-
const map = {};
|
|
2801
|
-
const extensions = [];
|
|
2802
|
-
for (const v of variants) {
|
|
2803
|
-
const e = getUrlFileExtension(v);
|
|
2804
|
-
map[e] = v;
|
|
2805
|
-
extensions.push(e);
|
|
2806
|
-
}
|
|
2807
|
-
const type = getType(extensions);
|
|
2808
|
-
const getSource = once(() => {
|
|
2809
|
-
const support = SUPPORT_MAPS[type];
|
|
2810
|
-
for (const extension of extensions) {
|
|
2811
|
-
if (extension in support) {
|
|
2812
|
-
if (support[extension]) {
|
|
2813
|
-
return map[extension];
|
|
2814
|
-
}
|
|
2815
|
-
} else {
|
|
2816
|
-
return map[extension];
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
if (DEV) {
|
|
2820
|
-
throw new Error(`No matching asset was found for ${variants.map((v) => `"${v}"`).join(", ")}`);
|
|
2821
|
-
}
|
|
2822
|
-
return "";
|
|
2823
|
-
});
|
|
2824
|
-
return {
|
|
2825
|
-
get source() {
|
|
2826
|
-
return getSource();
|
|
2827
|
-
},
|
|
2828
|
-
get type() {
|
|
2829
|
-
return type;
|
|
2830
|
-
},
|
|
2831
|
-
id: generateRandomId()
|
|
2832
|
-
};
|
|
2833
|
-
},
|
|
2834
|
-
{
|
|
2835
|
-
getCacheKey: (variants) => variants.join("~")
|
|
2836
|
-
}
|
|
2837
|
-
);
|
|
2838
|
-
var asset = (...variants) => {
|
|
2839
|
-
return assetPrivate(variants);
|
|
2840
|
-
};
|
|
2841
|
-
asset.image = (source) => {
|
|
2842
|
-
if (assetPrivate.cache.has(source)) {
|
|
2843
|
-
return assetPrivate.cache.get(source);
|
|
2844
|
-
}
|
|
2845
|
-
const asset2 = {
|
|
2846
|
-
type: "image",
|
|
2847
|
-
source,
|
|
2848
|
-
id: generateRandomId()
|
|
2849
|
-
};
|
|
2850
|
-
assetPrivate.cache.set(source, asset2);
|
|
2851
|
-
return asset2;
|
|
2852
|
-
};
|
|
2853
|
-
asset.audio = (source) => {
|
|
2854
|
-
if (assetPrivate.cache.has(source)) {
|
|
2855
|
-
return assetPrivate.cache.get(source);
|
|
2856
|
-
}
|
|
2857
|
-
const asset2 = {
|
|
2858
|
-
type: "audio",
|
|
2859
|
-
source,
|
|
2860
|
-
id: generateRandomId()
|
|
2861
|
-
};
|
|
2862
|
-
assetPrivate.cache.set(source, asset2);
|
|
2863
|
-
return asset2;
|
|
2864
|
-
};
|
|
2865
|
-
return __toCommonJS(src_exports);
|
|
2866
|
-
})();
|
|
2867
|
-
//# sourceMappingURL=index.global.js.map
|