@novely/core 0.45.2 → 0.46.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +21 -3
- package/dist/index.global.js +709 -535
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +600 -518
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -13,30 +13,30 @@ function set(obj, key, val) {
|
|
|
13
13
|
}
|
|
14
14
|
function klona(x) {
|
|
15
15
|
if (typeof x !== "object") return x;
|
|
16
|
-
var i = 0, k, list, tmp,
|
|
17
|
-
if (
|
|
16
|
+
var i = 0, k, list, tmp, str = Object.prototype.toString.call(x);
|
|
17
|
+
if (str === "[object Object]") {
|
|
18
18
|
tmp = Object.create(x.__proto__ || null);
|
|
19
|
-
} else if (
|
|
19
|
+
} else if (str === "[object Array]") {
|
|
20
20
|
tmp = Array(x.length);
|
|
21
|
-
} else if (
|
|
21
|
+
} else if (str === "[object Set]") {
|
|
22
22
|
tmp = /* @__PURE__ */ new Set();
|
|
23
23
|
x.forEach(function(val) {
|
|
24
24
|
tmp.add(klona(val));
|
|
25
25
|
});
|
|
26
|
-
} else if (
|
|
26
|
+
} else if (str === "[object Map]") {
|
|
27
27
|
tmp = /* @__PURE__ */ new Map();
|
|
28
28
|
x.forEach(function(val, key) {
|
|
29
29
|
tmp.set(klona(key), klona(val));
|
|
30
30
|
});
|
|
31
|
-
} else if (
|
|
31
|
+
} else if (str === "[object Date]") {
|
|
32
32
|
tmp = /* @__PURE__ */ new Date(+x);
|
|
33
|
-
} else if (
|
|
33
|
+
} else if (str === "[object RegExp]") {
|
|
34
34
|
tmp = new RegExp(x.source, x.flags);
|
|
35
|
-
} else if (
|
|
35
|
+
} else if (str === "[object DataView]") {
|
|
36
36
|
tmp = new x.constructor(klona(x.buffer));
|
|
37
|
-
} else if (
|
|
37
|
+
} else if (str === "[object ArrayBuffer]") {
|
|
38
38
|
tmp = x.slice(0);
|
|
39
|
-
} else if (
|
|
39
|
+
} else if (str.slice(-6) === "Array]") {
|
|
40
40
|
tmp = new x.constructor(x);
|
|
41
41
|
}
|
|
42
42
|
if (tmp) {
|
|
@@ -54,33 +54,6 @@ function klona(x) {
|
|
|
54
54
|
// src/novely.ts
|
|
55
55
|
import pLimit from "p-limit";
|
|
56
56
|
|
|
57
|
-
// src/asset.ts
|
|
58
|
-
import { memoize as memoize2, once } from "es-toolkit/function";
|
|
59
|
-
import { DEV as DEV2 } from "esm-env";
|
|
60
|
-
|
|
61
|
-
// src/audio-codecs.ts
|
|
62
|
-
var cut = (str2) => str2.replace(/^no$/, "");
|
|
63
|
-
var audio = new Audio();
|
|
64
|
-
var canPlay = (type) => !!cut(audio.canPlayType(type));
|
|
65
|
-
var canPlayMultiple = (...types) => types.some((type) => canPlay(type));
|
|
66
|
-
var supportsMap = {
|
|
67
|
-
mp3: canPlayMultiple("audio/mpeg;", "audio/mp3;"),
|
|
68
|
-
mpeg: canPlay("audio/mpeg;"),
|
|
69
|
-
opus: canPlay('audio/ogg; codecs="opus"'),
|
|
70
|
-
ogg: canPlay('audio/ogg; codecs="vorbis"'),
|
|
71
|
-
oga: canPlay('audio/ogg; codecs="vorbis"'),
|
|
72
|
-
wav: canPlayMultiple('audio/wav; codecs="1"', "audio/wav;"),
|
|
73
|
-
aac: canPlay("audio/aac;"),
|
|
74
|
-
caf: canPlay("audio/x-caf;"),
|
|
75
|
-
m4a: canPlayMultiple("audio/x-m4a;", "audio/m4a;", "audio/aac;"),
|
|
76
|
-
m4b: canPlayMultiple("audio/x-m4b;", "audio/m4b;", "audio/aac;"),
|
|
77
|
-
mp4: canPlayMultiple("audio/x-mp4;", "audio/mp4;", "audio/aac;"),
|
|
78
|
-
weba: canPlay('audio/webm; codecs="vorbis"'),
|
|
79
|
-
webm: canPlay('audio/webm; codecs="vorbis"'),
|
|
80
|
-
dolby: canPlay('audio/mp4; codecs="ec-3"'),
|
|
81
|
-
flac: canPlayMultiple("audio/x-flac;", "audio/flac;")
|
|
82
|
-
};
|
|
83
|
-
|
|
84
57
|
// src/constants.ts
|
|
85
58
|
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
86
59
|
var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
|
|
@@ -121,54 +94,60 @@ var SUPPORTED_IMAGE_FILE_FORMATS = /* @__PURE__ */ new Set([
|
|
|
121
94
|
]);
|
|
122
95
|
var MAIN_CONTEXT_KEY = "$MAIN";
|
|
123
96
|
|
|
124
|
-
// src/
|
|
125
|
-
var
|
|
126
|
-
|
|
127
|
-
var webp = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
|
|
128
|
-
var supportsFormat = (source) => {
|
|
129
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
130
|
-
const img = Object.assign(document.createElement("img"), {
|
|
131
|
-
src: source
|
|
132
|
-
});
|
|
133
|
-
img.onload = img.onerror = () => {
|
|
134
|
-
resolve(img.height === 2);
|
|
135
|
-
};
|
|
136
|
-
return promise;
|
|
97
|
+
// src/utilities/assertions.ts
|
|
98
|
+
var isNumber = (val) => {
|
|
99
|
+
return typeof val === "number";
|
|
137
100
|
};
|
|
138
|
-
var
|
|
139
|
-
|
|
140
|
-
jxl: false,
|
|
141
|
-
webp: false
|
|
101
|
+
var isNull = (val) => {
|
|
102
|
+
return val === null;
|
|
142
103
|
};
|
|
143
|
-
var
|
|
144
|
-
|
|
145
|
-
jxl,
|
|
146
|
-
webp
|
|
104
|
+
var isString = (val) => {
|
|
105
|
+
return typeof val === "string";
|
|
147
106
|
};
|
|
148
|
-
var
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
107
|
+
var isFunction = (val) => {
|
|
108
|
+
return typeof val === "function";
|
|
109
|
+
};
|
|
110
|
+
var isPromise = (val) => {
|
|
111
|
+
return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
|
|
112
|
+
};
|
|
113
|
+
var isEmpty = (val) => {
|
|
114
|
+
return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
|
|
115
|
+
};
|
|
116
|
+
var isCSSImageURL = (url) => {
|
|
117
|
+
const startsWith = String.prototype.startsWith.bind(url);
|
|
118
|
+
return startsWith("http") || startsWith("/") || startsWith(".") || startsWith("data");
|
|
119
|
+
};
|
|
120
|
+
var isUserRequiredAction = ([action, ...meta]) => {
|
|
121
|
+
return Boolean(action === "custom" && meta[0] && meta[0].requireUserAction);
|
|
122
|
+
};
|
|
123
|
+
var isBlockStatement = (statement) => {
|
|
124
|
+
return BLOCK_STATEMENTS.has(statement);
|
|
125
|
+
};
|
|
126
|
+
var isBlockExitStatement = (statement) => {
|
|
127
|
+
return BLOCK_EXIT_STATEMENTS.has(statement);
|
|
128
|
+
};
|
|
129
|
+
var isSkippedDuringRestore = (item) => {
|
|
130
|
+
return SKIPPED_DURING_RESTORE.has(item);
|
|
131
|
+
};
|
|
132
|
+
var isAudioAction = (action) => {
|
|
133
|
+
return AUDIO_ACTIONS.has(action);
|
|
134
|
+
};
|
|
135
|
+
var isAction = (element) => {
|
|
136
|
+
return Array.isArray(element) && isString(element[0]);
|
|
137
|
+
};
|
|
138
|
+
var isImageAsset = (asset2) => {
|
|
139
|
+
return isString(asset2) && isCSSImageURL(asset2);
|
|
140
|
+
};
|
|
141
|
+
var isBlockingAction = (action) => {
|
|
142
|
+
return isUserRequiredAction(action) || isSkippedDuringRestore(action[0]) && action[0] !== "vibrate";
|
|
143
|
+
};
|
|
144
|
+
var isAsset = (suspect) => {
|
|
145
|
+
return suspect !== null && typeof suspect === "object" && "source" in suspect && "type" in suspect;
|
|
157
146
|
};
|
|
158
|
-
loadImageFormatsSupport();
|
|
159
|
-
|
|
160
|
-
// src/utils.ts
|
|
161
|
-
import { memoize } from "es-toolkit/function";
|
|
162
|
-
import { DEV } from "esm-env";
|
|
163
|
-
|
|
164
|
-
// src/shared.ts
|
|
165
|
-
var STACK_MAP = /* @__PURE__ */ new Map();
|
|
166
|
-
var CUSTOM_ACTION_MAP = /* @__PURE__ */ new Map();
|
|
167
|
-
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
168
|
-
var ASSETS_TO_PRELOAD = /* @__PURE__ */ new Set();
|
|
169
147
|
|
|
170
|
-
// src/
|
|
171
|
-
var matchAction = (
|
|
148
|
+
// src/utilities/match-action.ts
|
|
149
|
+
var matchAction = (callbacks, values) => {
|
|
150
|
+
const { getContext, onBeforeActionCall, push, forward } = callbacks;
|
|
172
151
|
return (action, props, { ctx, data }) => {
|
|
173
152
|
const context = typeof ctx === "string" ? getContext(ctx) : ctx;
|
|
174
153
|
onBeforeActionCall({
|
|
@@ -193,32 +172,10 @@ var matchAction = ({ getContext, onBeforeActionCall, push, forward }, values) =>
|
|
|
193
172
|
);
|
|
194
173
|
};
|
|
195
174
|
};
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
return val === null;
|
|
201
|
-
};
|
|
202
|
-
var isString = (val) => {
|
|
203
|
-
return typeof val === "string";
|
|
204
|
-
};
|
|
205
|
-
var isFunction = (val) => {
|
|
206
|
-
return typeof val === "function";
|
|
207
|
-
};
|
|
208
|
-
var isPromise = (val) => {
|
|
209
|
-
return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
|
|
210
|
-
};
|
|
211
|
-
var isEmpty = (val) => {
|
|
212
|
-
return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
|
|
213
|
-
};
|
|
214
|
-
var isCSSImage = (str2) => {
|
|
215
|
-
const startsWith = String.prototype.startsWith.bind(str2);
|
|
216
|
-
return startsWith("http") || startsWith("/") || startsWith(".") || startsWith("data");
|
|
217
|
-
};
|
|
218
|
-
var str = String;
|
|
219
|
-
var isUserRequiredAction = ([action, ...meta]) => {
|
|
220
|
-
return Boolean(action === "custom" && meta[0] && meta[0].requireUserAction);
|
|
221
|
-
};
|
|
175
|
+
|
|
176
|
+
// src/utilities/ungrupped.ts
|
|
177
|
+
import { memoize } from "es-toolkit/function";
|
|
178
|
+
import { DEV } from "esm-env";
|
|
222
179
|
var getLanguage = (languages) => {
|
|
223
180
|
let { language } = navigator;
|
|
224
181
|
if (languages.includes(language)) {
|
|
@@ -230,65 +187,60 @@ var getLanguage = (languages) => {
|
|
|
230
187
|
}
|
|
231
188
|
return languages[0];
|
|
232
189
|
};
|
|
233
|
-
var
|
|
234
|
-
const object = {
|
|
235
|
-
resolve: null,
|
|
236
|
-
reject: null,
|
|
237
|
-
promise: null,
|
|
238
|
-
cancel: null
|
|
239
|
-
};
|
|
240
|
-
const init = () => {
|
|
241
|
-
const promise = new Promise((resolve, reject) => {
|
|
242
|
-
object.reject = reject;
|
|
243
|
-
object.resolve = (value) => {
|
|
244
|
-
resolve({ cancelled: false, value });
|
|
245
|
-
};
|
|
246
|
-
object.cancel = () => {
|
|
247
|
-
resolve({ cancelled: true, value: null });
|
|
248
|
-
init();
|
|
249
|
-
};
|
|
250
|
-
});
|
|
251
|
-
object.promise = promise;
|
|
252
|
-
};
|
|
253
|
-
return init(), object;
|
|
190
|
+
var noop = () => {
|
|
254
191
|
};
|
|
255
|
-
var
|
|
256
|
-
|
|
257
|
-
const next = array[i + 1];
|
|
258
|
-
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
259
|
-
});
|
|
260
|
-
return item;
|
|
192
|
+
var mapSet = (set2, fn) => {
|
|
193
|
+
return [...set2].map(fn);
|
|
261
194
|
};
|
|
262
|
-
var
|
|
263
|
-
return
|
|
195
|
+
var capitalize = (str) => {
|
|
196
|
+
return str[0].toUpperCase() + str.slice(1);
|
|
264
197
|
};
|
|
265
|
-
var
|
|
266
|
-
|
|
198
|
+
var getIntlLanguageDisplayName = memoize((lang) => {
|
|
199
|
+
try {
|
|
200
|
+
const intl = new Intl.DisplayNames([lang], {
|
|
201
|
+
type: "language"
|
|
202
|
+
});
|
|
203
|
+
return intl.of(lang) || lang;
|
|
204
|
+
} catch {
|
|
205
|
+
return lang;
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
var unwrapAsset = (asset2) => {
|
|
209
|
+
return isAsset(asset2) ? asset2.source : asset2;
|
|
267
210
|
};
|
|
268
|
-
var
|
|
269
|
-
|
|
211
|
+
var handleAudioAsset = (asset2) => {
|
|
212
|
+
if (DEV && isAsset(asset2) && asset2.type !== "audio") {
|
|
213
|
+
throw new Error("Attempt to use non-audio asset in audio action", { cause: asset2 });
|
|
214
|
+
}
|
|
215
|
+
return unwrapAsset(asset2);
|
|
270
216
|
};
|
|
271
|
-
var
|
|
272
|
-
|
|
217
|
+
var handleImageAsset = (asset2) => {
|
|
218
|
+
if (DEV && isAsset(asset2) && asset2.type !== "image") {
|
|
219
|
+
throw new Error("Attempt to use non-image asset in action that requires image assets", { cause: asset2 });
|
|
220
|
+
}
|
|
221
|
+
return unwrapAsset(asset2);
|
|
273
222
|
};
|
|
274
|
-
var
|
|
223
|
+
var getCharactersData = (characters) => {
|
|
224
|
+
const entries = Object.entries(characters);
|
|
225
|
+
const mapped = entries.map(([key, value]) => [key, { name: value.name, emotions: Object.keys(value.emotions) }]);
|
|
226
|
+
return Object.fromEntries(mapped);
|
|
275
227
|
};
|
|
276
|
-
var
|
|
277
|
-
return Array.isArray(
|
|
228
|
+
var toArray = (target) => {
|
|
229
|
+
return Array.isArray(target) ? target : [target];
|
|
278
230
|
};
|
|
279
|
-
var
|
|
280
|
-
return
|
|
281
|
-
const type = data[0];
|
|
282
|
-
if (Array.isArray(type)) return flatActions(data);
|
|
283
|
-
return [data];
|
|
284
|
-
});
|
|
231
|
+
var getLanguageFromStore = (store2) => {
|
|
232
|
+
return store2.get().meta[0];
|
|
285
233
|
};
|
|
286
|
-
var
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
234
|
+
var getVolumeFromStore = (store2) => {
|
|
235
|
+
const { meta } = store2.get();
|
|
236
|
+
return {
|
|
237
|
+
music: meta[2],
|
|
238
|
+
sound: meta[3],
|
|
239
|
+
voice: meta[4]
|
|
240
|
+
};
|
|
291
241
|
};
|
|
242
|
+
|
|
243
|
+
// src/utilities/actions-processing.ts
|
|
292
244
|
var isExitImpossible = (path) => {
|
|
293
245
|
const blockStatements = path.filter(([item]) => isBlockStatement(item));
|
|
294
246
|
const blockExitStatements = path.filter(([item]) => isBlockExitStatement(item));
|
|
@@ -300,14 +252,166 @@ var isExitImpossible = (path) => {
|
|
|
300
252
|
}
|
|
301
253
|
return !blockExitStatements.every(([name], i) => name && name.startsWith(blockStatements[i][0]));
|
|
302
254
|
};
|
|
303
|
-
var
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
255
|
+
var createReferFunction = (story) => {
|
|
256
|
+
const refer = (path) => {
|
|
257
|
+
let current = story;
|
|
258
|
+
let precurrent = story;
|
|
259
|
+
const blocks = [];
|
|
260
|
+
for (const [type, val] of path) {
|
|
261
|
+
if (type === "jump") {
|
|
262
|
+
precurrent = story;
|
|
263
|
+
current = current[val];
|
|
264
|
+
} else if (type === null) {
|
|
265
|
+
precurrent = current;
|
|
266
|
+
current = current[val];
|
|
267
|
+
} else if (type === "choice") {
|
|
268
|
+
blocks.push(precurrent);
|
|
269
|
+
current = current[val + 1][1];
|
|
270
|
+
} else if (type === "condition") {
|
|
271
|
+
blocks.push(precurrent);
|
|
272
|
+
current = current[2][val];
|
|
273
|
+
} else if (type === "block") {
|
|
274
|
+
blocks.push(precurrent);
|
|
275
|
+
current = story[val];
|
|
276
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
277
|
+
current = blocks.pop();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return current;
|
|
309
281
|
};
|
|
310
|
-
return
|
|
282
|
+
return refer;
|
|
283
|
+
};
|
|
284
|
+
var exitPath = ({ path, refer, onExitImpossible }) => {
|
|
285
|
+
const last = path.at(-1);
|
|
286
|
+
const ignore = [];
|
|
287
|
+
let wasExitImpossible = false;
|
|
288
|
+
if (!isAction(refer(path))) {
|
|
289
|
+
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
290
|
+
last[1]--;
|
|
291
|
+
} else {
|
|
292
|
+
path.pop();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (isExitImpossible(path)) {
|
|
296
|
+
const referred = refer(path);
|
|
297
|
+
if (isAction(referred) && isSkippedDuringRestore(referred[0])) {
|
|
298
|
+
onExitImpossible?.();
|
|
299
|
+
}
|
|
300
|
+
wasExitImpossible = true;
|
|
301
|
+
return {
|
|
302
|
+
exitImpossible: wasExitImpossible
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
for (let i = path.length - 1; i > 0; i--) {
|
|
306
|
+
const [name] = path[i];
|
|
307
|
+
if (isBlockExitStatement(name)) {
|
|
308
|
+
ignore.push(name);
|
|
309
|
+
}
|
|
310
|
+
if (!isBlockStatement(name)) continue;
|
|
311
|
+
if (ignore.at(-1)?.startsWith(name)) {
|
|
312
|
+
ignore.pop();
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
path.push([`${name}:exit`]);
|
|
316
|
+
const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
|
|
317
|
+
if (prev) path.push([null, prev[1] + 1]);
|
|
318
|
+
if (!isAction(refer(path))) {
|
|
319
|
+
path.pop();
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
exitImpossible: wasExitImpossible
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
var nextPath = (path) => {
|
|
329
|
+
const last = path.at(-1);
|
|
330
|
+
if (last && (isNull(last[0]) || last[0] === "jump") && isNumber(last[1])) {
|
|
331
|
+
last[1]++;
|
|
332
|
+
} else {
|
|
333
|
+
path.push([null, 0]);
|
|
334
|
+
}
|
|
335
|
+
return path;
|
|
336
|
+
};
|
|
337
|
+
var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
|
|
338
|
+
const collection = [];
|
|
339
|
+
let action = refer(path);
|
|
340
|
+
while (true) {
|
|
341
|
+
if (action == void 0) {
|
|
342
|
+
const { exitImpossible } = exitPath({
|
|
343
|
+
path,
|
|
344
|
+
refer
|
|
345
|
+
});
|
|
346
|
+
if (exitImpossible) {
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (!action) {
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
if (isBlockingAction(action)) {
|
|
354
|
+
const [name, ...props] = action;
|
|
355
|
+
if (name === "choice") {
|
|
356
|
+
const choiceProps = props;
|
|
357
|
+
for (let i = 0; i < choiceProps.length; i++) {
|
|
358
|
+
const branchContent = choiceProps[i];
|
|
359
|
+
if (!Array.isArray(branchContent)) continue;
|
|
360
|
+
const virtualPath = clone(path);
|
|
361
|
+
virtualPath.push(["choice", i], [null, 0]);
|
|
362
|
+
const innerActions = collectActionsBeforeBlockingAction({
|
|
363
|
+
path: virtualPath,
|
|
364
|
+
refer,
|
|
365
|
+
clone
|
|
366
|
+
});
|
|
367
|
+
collection.push(...innerActions);
|
|
368
|
+
}
|
|
369
|
+
} else if (name === "condition") {
|
|
370
|
+
const conditionProps = props;
|
|
371
|
+
const conditions = Object.keys(conditionProps[1]);
|
|
372
|
+
for (const condition of conditions) {
|
|
373
|
+
const virtualPath = clone(path);
|
|
374
|
+
virtualPath.push(["condition", condition], [null, 0]);
|
|
375
|
+
const innerActions = collectActionsBeforeBlockingAction({
|
|
376
|
+
path: virtualPath,
|
|
377
|
+
refer,
|
|
378
|
+
clone
|
|
379
|
+
});
|
|
380
|
+
collection.push(...innerActions);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
collection.push(action);
|
|
386
|
+
if (action[0] === "jump") {
|
|
387
|
+
path = [
|
|
388
|
+
["jump", action[1]],
|
|
389
|
+
[null, 0]
|
|
390
|
+
];
|
|
391
|
+
} else if (action[0] == "block") {
|
|
392
|
+
path.push(["block", action[1]], [null, 0]);
|
|
393
|
+
} else {
|
|
394
|
+
nextPath(path);
|
|
395
|
+
}
|
|
396
|
+
action = refer(path);
|
|
397
|
+
}
|
|
398
|
+
return collection;
|
|
399
|
+
};
|
|
400
|
+
var findLastPathItemBeforeItemOfType = (path, name) => {
|
|
401
|
+
const item = path.findLast(([_name, _value], i, array) => {
|
|
402
|
+
const next = array[i + 1];
|
|
403
|
+
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
404
|
+
});
|
|
405
|
+
return item;
|
|
406
|
+
};
|
|
407
|
+
var getOppositeAction = (action) => {
|
|
408
|
+
const MAP = {
|
|
409
|
+
showCharacter: "hideCharacter",
|
|
410
|
+
playSound: "stopSound",
|
|
411
|
+
playMusic: "stopMusic",
|
|
412
|
+
voice: "stopVoice"
|
|
413
|
+
};
|
|
414
|
+
return MAP[action];
|
|
311
415
|
};
|
|
312
416
|
var getActionsFromPath = (story, path, filter) => {
|
|
313
417
|
let current = story;
|
|
@@ -405,7 +509,7 @@ var createQueueProcessor = (queue, options) => {
|
|
|
405
509
|
const c1 = fn;
|
|
406
510
|
const isIdenticalID = Boolean(c0.id && c1.id && c0.id === c1.id);
|
|
407
511
|
const isIdenticalByReference = c0 === c1;
|
|
408
|
-
return isIdenticalID || isIdenticalByReference ||
|
|
512
|
+
return isIdenticalID || isIdenticalByReference || String(c0) === String(c1);
|
|
409
513
|
});
|
|
410
514
|
if (notLatest) continue;
|
|
411
515
|
} else if ("skipOnRestore" in fn && fn.skipOnRestore) {
|
|
@@ -472,59 +576,40 @@ var createQueueProcessor = (queue, options) => {
|
|
|
472
576
|
}
|
|
473
577
|
};
|
|
474
578
|
};
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
);
|
|
484
|
-
var createUseStackFunction = (renderer) => {
|
|
485
|
-
const useStack = (context) => {
|
|
486
|
-
const ctx = typeof context === "string" ? renderer.getContext(context) : context;
|
|
487
|
-
const stack = getStack(ctx);
|
|
488
|
-
return {
|
|
489
|
-
get previous() {
|
|
490
|
-
return stack.previous;
|
|
491
|
-
},
|
|
492
|
-
get value() {
|
|
493
|
-
return stack.at(-1);
|
|
494
|
-
},
|
|
495
|
-
set value(value) {
|
|
496
|
-
stack[stack.length - 1] = value;
|
|
497
|
-
},
|
|
498
|
-
back() {
|
|
499
|
-
if (stack.length > 1) {
|
|
500
|
-
stack.previous = stack.pop();
|
|
501
|
-
ctx.meta.goingBack = true;
|
|
502
|
-
}
|
|
503
|
-
},
|
|
504
|
-
push(value) {
|
|
505
|
-
stack.push(value);
|
|
506
|
-
},
|
|
507
|
-
clear() {
|
|
508
|
-
stack.previous = void 0;
|
|
509
|
-
stack.length = 0;
|
|
510
|
-
stack.length = 1;
|
|
511
|
-
}
|
|
512
|
-
};
|
|
579
|
+
|
|
580
|
+
// src/utilities/controlled-promise.ts
|
|
581
|
+
var createControlledPromise = () => {
|
|
582
|
+
const object = {
|
|
583
|
+
resolve: null,
|
|
584
|
+
reject: null,
|
|
585
|
+
promise: null,
|
|
586
|
+
cancel: null
|
|
513
587
|
};
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
};
|
|
519
|
-
|
|
520
|
-
|
|
588
|
+
const init = () => {
|
|
589
|
+
const promise = new Promise((resolve, reject) => {
|
|
590
|
+
object.reject = reject;
|
|
591
|
+
object.resolve = (value) => {
|
|
592
|
+
resolve({ cancelled: false, value });
|
|
593
|
+
};
|
|
594
|
+
object.cancel = () => {
|
|
595
|
+
resolve({ cancelled: true, value: null });
|
|
596
|
+
init();
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
object.promise = promise;
|
|
600
|
+
};
|
|
601
|
+
return init(), object;
|
|
521
602
|
};
|
|
603
|
+
|
|
604
|
+
// src/utilities/resources.ts
|
|
605
|
+
import { memoize as memoize2 } from "es-toolkit/function";
|
|
606
|
+
import { DEV as DEV2 } from "esm-env";
|
|
522
607
|
var getUrlFileExtension = (address) => {
|
|
523
608
|
try {
|
|
524
609
|
const { pathname } = new URL(address, location.href);
|
|
525
610
|
return pathname.split(".").at(-1).split("!")[0].split(":")[0];
|
|
526
611
|
} catch (error) {
|
|
527
|
-
if (
|
|
612
|
+
if (DEV2) {
|
|
528
613
|
console.error(new Error(`Could not construct URL "${address}".`, { cause: error }));
|
|
529
614
|
}
|
|
530
615
|
return "";
|
|
@@ -537,15 +622,15 @@ var fetchContentType = async (url, request) => {
|
|
|
537
622
|
});
|
|
538
623
|
return response.headers.get("Content-Type") || "";
|
|
539
624
|
} catch (error) {
|
|
540
|
-
if (
|
|
625
|
+
if (DEV2) {
|
|
541
626
|
console.error(new Error(`Failed to fetch file at "${url}"`, { cause: error }));
|
|
542
627
|
}
|
|
543
628
|
return "";
|
|
544
629
|
}
|
|
545
630
|
};
|
|
546
|
-
var getResourseType =
|
|
631
|
+
var getResourseType = memoize2(
|
|
547
632
|
async ({ url, request }) => {
|
|
548
|
-
if (!
|
|
633
|
+
if (!isCSSImageURL(url)) {
|
|
549
634
|
return "other";
|
|
550
635
|
}
|
|
551
636
|
const extension = getUrlFileExtension(url);
|
|
@@ -554,282 +639,86 @@ var getResourseType = memoize(
|
|
|
554
639
|
}
|
|
555
640
|
if (SUPPORTED_IMAGE_FILE_FORMATS.has(extension)) {
|
|
556
641
|
return "image";
|
|
557
|
-
}
|
|
558
|
-
const contentType = await fetchContentType(url, request);
|
|
559
|
-
if (contentType.includes("audio")) {
|
|
560
|
-
return "audio";
|
|
561
|
-
}
|
|
562
|
-
if (contentType.includes("image")) {
|
|
563
|
-
return "image";
|
|
564
|
-
}
|
|
565
|
-
return "other";
|
|
566
|
-
},
|
|
567
|
-
{
|
|
568
|
-
getCacheKey: ({ url }) => url
|
|
569
|
-
}
|
|
570
|
-
);
|
|
571
|
-
var capitalize = (str2) => {
|
|
572
|
-
return str2[0].toUpperCase() + str2.slice(1);
|
|
573
|
-
};
|
|
574
|
-
var getIntlLanguageDisplayName = memoize((lang) => {
|
|
575
|
-
try {
|
|
576
|
-
const intl = new Intl.DisplayNames([lang], {
|
|
577
|
-
type: "language"
|
|
578
|
-
});
|
|
579
|
-
return intl.of(lang) || lang;
|
|
580
|
-
} catch {
|
|
581
|
-
return lang;
|
|
582
|
-
}
|
|
583
|
-
});
|
|
584
|
-
var createReferFunction = (story) => {
|
|
585
|
-
const refer = (path) => {
|
|
586
|
-
let current = story;
|
|
587
|
-
let precurrent = story;
|
|
588
|
-
const blocks = [];
|
|
589
|
-
for (const [type, val] of path) {
|
|
590
|
-
if (type === "jump") {
|
|
591
|
-
precurrent = story;
|
|
592
|
-
current = current[val];
|
|
593
|
-
} else if (type === null) {
|
|
594
|
-
precurrent = current;
|
|
595
|
-
current = current[val];
|
|
596
|
-
} else if (type === "choice") {
|
|
597
|
-
blocks.push(precurrent);
|
|
598
|
-
current = current[val + 1][1];
|
|
599
|
-
} else if (type === "condition") {
|
|
600
|
-
blocks.push(precurrent);
|
|
601
|
-
current = current[2][val];
|
|
602
|
-
} else if (type === "block") {
|
|
603
|
-
blocks.push(precurrent);
|
|
604
|
-
current = story[val];
|
|
605
|
-
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
606
|
-
current = blocks.pop();
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
return current;
|
|
610
|
-
};
|
|
611
|
-
return refer;
|
|
612
|
-
};
|
|
613
|
-
var exitPath = ({ path, refer, onExitImpossible }) => {
|
|
614
|
-
const last = path.at(-1);
|
|
615
|
-
const ignore = [];
|
|
616
|
-
let wasExitImpossible = false;
|
|
617
|
-
if (!isAction(refer(path))) {
|
|
618
|
-
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
619
|
-
last[1]--;
|
|
620
|
-
} else {
|
|
621
|
-
path.pop();
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
if (isExitImpossible(path)) {
|
|
625
|
-
const referred = refer(path);
|
|
626
|
-
if (isAction(referred) && isSkippedDuringRestore(referred[0])) {
|
|
627
|
-
onExitImpossible?.();
|
|
628
|
-
}
|
|
629
|
-
wasExitImpossible = true;
|
|
630
|
-
return {
|
|
631
|
-
exitImpossible: wasExitImpossible
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
for (let i = path.length - 1; i > 0; i--) {
|
|
635
|
-
const [name] = path[i];
|
|
636
|
-
if (isBlockExitStatement(name)) {
|
|
637
|
-
ignore.push(name);
|
|
638
|
-
}
|
|
639
|
-
if (!isBlockStatement(name)) continue;
|
|
640
|
-
if (ignore.at(-1)?.startsWith(name)) {
|
|
641
|
-
ignore.pop();
|
|
642
|
-
continue;
|
|
643
|
-
}
|
|
644
|
-
path.push([`${name}:exit`]);
|
|
645
|
-
const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
|
|
646
|
-
if (prev) path.push([null, prev[1] + 1]);
|
|
647
|
-
if (!isAction(refer(path))) {
|
|
648
|
-
path.pop();
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
break;
|
|
652
|
-
}
|
|
653
|
-
return {
|
|
654
|
-
exitImpossible: wasExitImpossible
|
|
655
|
-
};
|
|
656
|
-
};
|
|
657
|
-
var nextPath = (path) => {
|
|
658
|
-
const last = path.at(-1);
|
|
659
|
-
if (last && (isNull(last[0]) || last[0] === "jump") && isNumber(last[1])) {
|
|
660
|
-
last[1]++;
|
|
661
|
-
} else {
|
|
662
|
-
path.push([null, 0]);
|
|
663
|
-
}
|
|
664
|
-
return path;
|
|
665
|
-
};
|
|
666
|
-
var isBlockingAction = (action) => {
|
|
667
|
-
return isUserRequiredAction(action) || isSkippedDuringRestore(action[0]) && action[0] !== "vibrate";
|
|
668
|
-
};
|
|
669
|
-
var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
|
|
670
|
-
const collection = [];
|
|
671
|
-
let action = refer(path);
|
|
672
|
-
while (true) {
|
|
673
|
-
if (action == void 0) {
|
|
674
|
-
const { exitImpossible } = exitPath({
|
|
675
|
-
path,
|
|
676
|
-
refer
|
|
677
|
-
});
|
|
678
|
-
if (exitImpossible) {
|
|
679
|
-
break;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
if (!action) {
|
|
683
|
-
break;
|
|
684
|
-
}
|
|
685
|
-
if (isBlockingAction(action)) {
|
|
686
|
-
const [name, ...props] = action;
|
|
687
|
-
if (name === "choice") {
|
|
688
|
-
const choiceProps = props;
|
|
689
|
-
for (let i = 0; i < choiceProps.length; i++) {
|
|
690
|
-
const branchContent = choiceProps[i];
|
|
691
|
-
if (!Array.isArray(branchContent)) continue;
|
|
692
|
-
const virtualPath = clone(path);
|
|
693
|
-
virtualPath.push(["choice", i], [null, 0]);
|
|
694
|
-
const innerActions = collectActionsBeforeBlockingAction({
|
|
695
|
-
path: virtualPath,
|
|
696
|
-
refer,
|
|
697
|
-
clone
|
|
698
|
-
});
|
|
699
|
-
collection.push(...innerActions);
|
|
700
|
-
}
|
|
701
|
-
} else if (name === "condition") {
|
|
702
|
-
const conditionProps = props;
|
|
703
|
-
const conditions = Object.keys(conditionProps[1]);
|
|
704
|
-
for (const condition of conditions) {
|
|
705
|
-
const virtualPath = clone(path);
|
|
706
|
-
virtualPath.push(["condition", condition], [null, 0]);
|
|
707
|
-
const innerActions = collectActionsBeforeBlockingAction({
|
|
708
|
-
path: virtualPath,
|
|
709
|
-
refer,
|
|
710
|
-
clone
|
|
711
|
-
});
|
|
712
|
-
collection.push(...innerActions);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
break;
|
|
716
|
-
}
|
|
717
|
-
collection.push(action);
|
|
718
|
-
if (action[0] === "jump") {
|
|
719
|
-
path = [
|
|
720
|
-
["jump", action[1]],
|
|
721
|
-
[null, 0]
|
|
722
|
-
];
|
|
723
|
-
} else if (action[0] == "block") {
|
|
724
|
-
path.push(["block", action[1]], [null, 0]);
|
|
725
|
-
} else {
|
|
726
|
-
nextPath(path);
|
|
727
|
-
}
|
|
728
|
-
action = refer(path);
|
|
729
|
-
}
|
|
730
|
-
return collection;
|
|
731
|
-
};
|
|
732
|
-
var unwrapAsset = (asset2) => {
|
|
733
|
-
return isAsset(asset2) ? asset2.source : asset2;
|
|
734
|
-
};
|
|
735
|
-
var handleAudioAsset = (asset2) => {
|
|
736
|
-
if (DEV && isAsset(asset2) && asset2.type !== "audio") {
|
|
737
|
-
throw new Error("Attempt to use non-audio asset in audio action", { cause: asset2 });
|
|
738
|
-
}
|
|
739
|
-
return unwrapAsset(asset2);
|
|
740
|
-
};
|
|
741
|
-
var handleImageAsset = (asset2) => {
|
|
742
|
-
if (DEV && isAsset(asset2) && asset2.type !== "image") {
|
|
743
|
-
throw new Error("Attempt to use non-image asset in action that requires image assets", { cause: asset2 });
|
|
744
|
-
}
|
|
745
|
-
return unwrapAsset(asset2);
|
|
746
|
-
};
|
|
747
|
-
var getCharactersData = (characters) => {
|
|
748
|
-
const entries = Object.entries(characters);
|
|
749
|
-
const mapped = entries.map(([key, value]) => [key, { name: value.name, emotions: Object.keys(value.emotions) }]);
|
|
750
|
-
return Object.fromEntries(mapped);
|
|
751
|
-
};
|
|
752
|
-
var toArray = (target) => {
|
|
753
|
-
return Array.isArray(target) ? target : [target];
|
|
754
|
-
};
|
|
755
|
-
var getLanguageFromStore = (store2) => {
|
|
756
|
-
return store2.get().meta[0];
|
|
757
|
-
};
|
|
758
|
-
var getVolumeFromStore = (store2) => {
|
|
759
|
-
const { meta } = store2.get();
|
|
760
|
-
return {
|
|
761
|
-
music: meta[2],
|
|
762
|
-
sound: meta[3],
|
|
763
|
-
voice: meta[4]
|
|
764
|
-
};
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
// src/asset.ts
|
|
768
|
-
var getType = memoize2(
|
|
769
|
-
(extensions) => {
|
|
770
|
-
if (extensions.every((extension) => HOWLER_SUPPORTED_FILE_FORMATS.has(extension))) {
|
|
642
|
+
}
|
|
643
|
+
const contentType = await fetchContentType(url, request);
|
|
644
|
+
if (contentType.includes("audio")) {
|
|
771
645
|
return "audio";
|
|
772
646
|
}
|
|
773
|
-
if (
|
|
647
|
+
if (contentType.includes("image")) {
|
|
774
648
|
return "image";
|
|
775
649
|
}
|
|
776
|
-
|
|
650
|
+
return "other";
|
|
777
651
|
},
|
|
778
652
|
{
|
|
779
|
-
getCacheKey: (
|
|
653
|
+
getCacheKey: ({ url }) => url
|
|
780
654
|
}
|
|
781
655
|
);
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
extensions.push(e);
|
|
797
|
-
}
|
|
798
|
-
const type = getType(extensions);
|
|
799
|
-
const getSource = once(() => {
|
|
800
|
-
const support = SUPPORT_MAPS[type];
|
|
801
|
-
for (const extension of extensions) {
|
|
802
|
-
if (extension in support) {
|
|
803
|
-
if (support[extension]) {
|
|
804
|
-
return map[extension];
|
|
805
|
-
}
|
|
806
|
-
} else {
|
|
807
|
-
return map[extension];
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
if (DEV2) {
|
|
811
|
-
throw new Error(`No matching asset was found for ${variants.map((v) => `"${v}"`).join(", ")}`);
|
|
812
|
-
}
|
|
813
|
-
return "";
|
|
814
|
-
});
|
|
815
|
-
return {
|
|
816
|
-
get source() {
|
|
817
|
-
return getSource();
|
|
818
|
-
},
|
|
819
|
-
get type() {
|
|
820
|
-
return type;
|
|
821
|
-
}
|
|
822
|
-
};
|
|
656
|
+
|
|
657
|
+
// src/utilities/stack.ts
|
|
658
|
+
import { memoize as memoize3 } from "es-toolkit/function";
|
|
659
|
+
|
|
660
|
+
// src/shared.ts
|
|
661
|
+
var STACK_MAP = /* @__PURE__ */ new Map();
|
|
662
|
+
var CUSTOM_ACTION_MAP = /* @__PURE__ */ new Map();
|
|
663
|
+
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
664
|
+
var ASSETS_TO_PRELOAD = /* @__PURE__ */ new Set();
|
|
665
|
+
|
|
666
|
+
// src/utilities/stack.ts
|
|
667
|
+
var getStack = memoize3(
|
|
668
|
+
(_) => {
|
|
669
|
+
return [];
|
|
823
670
|
},
|
|
824
671
|
{
|
|
825
|
-
|
|
672
|
+
cache: STACK_MAP,
|
|
673
|
+
getCacheKey: (ctx) => ctx.id
|
|
826
674
|
}
|
|
827
675
|
);
|
|
828
|
-
var
|
|
829
|
-
|
|
676
|
+
var createUseStackFunction = (renderer) => {
|
|
677
|
+
const useStack = (context) => {
|
|
678
|
+
const ctx = typeof context === "string" ? renderer.getContext(context) : context;
|
|
679
|
+
const stack = getStack(ctx);
|
|
680
|
+
return {
|
|
681
|
+
get previous() {
|
|
682
|
+
return stack.previous;
|
|
683
|
+
},
|
|
684
|
+
get value() {
|
|
685
|
+
return stack.at(-1);
|
|
686
|
+
},
|
|
687
|
+
set value(value) {
|
|
688
|
+
stack[stack.length - 1] = value;
|
|
689
|
+
},
|
|
690
|
+
back() {
|
|
691
|
+
if (stack.length > 1) {
|
|
692
|
+
stack.previous = stack.pop();
|
|
693
|
+
ctx.meta.goingBack = true;
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
push(value) {
|
|
697
|
+
stack.push(value);
|
|
698
|
+
},
|
|
699
|
+
clear() {
|
|
700
|
+
stack.previous = void 0;
|
|
701
|
+
stack.length = 0;
|
|
702
|
+
stack.length = 1;
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
};
|
|
706
|
+
return useStack;
|
|
830
707
|
};
|
|
831
|
-
|
|
832
|
-
|
|
708
|
+
|
|
709
|
+
// src/utilities/story.ts
|
|
710
|
+
var flatActions = (item) => {
|
|
711
|
+
return item.flatMap((data) => {
|
|
712
|
+
const type = data[0];
|
|
713
|
+
if (Array.isArray(type)) return flatActions(data);
|
|
714
|
+
return [data];
|
|
715
|
+
});
|
|
716
|
+
};
|
|
717
|
+
var flatStory = (story) => {
|
|
718
|
+
const entries = Object.entries(story).map(([name, items]) => {
|
|
719
|
+
return [name, flatActions(items)];
|
|
720
|
+
});
|
|
721
|
+
return Object.fromEntries(entries);
|
|
833
722
|
};
|
|
834
723
|
|
|
835
724
|
// src/browser.ts
|
|
@@ -1156,7 +1045,7 @@ var novely = ({
|
|
|
1156
1045
|
};
|
|
1157
1046
|
const scriptBase = async (part) => {
|
|
1158
1047
|
if (destroyed) return;
|
|
1159
|
-
Object.assign(story,
|
|
1048
|
+
Object.assign(story, flatStory(part));
|
|
1160
1049
|
let loadingIsShown = false;
|
|
1161
1050
|
if (!initialScreenWasShown) {
|
|
1162
1051
|
renderer.ui.showLoading();
|
|
@@ -1199,7 +1088,8 @@ var novely = ({
|
|
|
1199
1088
|
throw new Error(`Attempt to call Say action with unknown character "${character}"`);
|
|
1200
1089
|
}
|
|
1201
1090
|
} else if (action2 === "choice") {
|
|
1202
|
-
|
|
1091
|
+
const actions = props.slice(1);
|
|
1092
|
+
if (actions.every((choice) => !Array.isArray(choice))) {
|
|
1203
1093
|
for (let i = 1; i < props.length; i++) {
|
|
1204
1094
|
const choice = props[i];
|
|
1205
1095
|
props[i] = [
|
|
@@ -1211,6 +1101,13 @@ var novely = ({
|
|
|
1211
1101
|
choice.image
|
|
1212
1102
|
];
|
|
1213
1103
|
}
|
|
1104
|
+
} else {
|
|
1105
|
+
for (let i = 1; i < props.length; i++) {
|
|
1106
|
+
const choice = props[i];
|
|
1107
|
+
if (Array.isArray(choice) && choice.length === 2) {
|
|
1108
|
+
choice[1] = flatActions(choice[1]);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1214
1111
|
}
|
|
1215
1112
|
}
|
|
1216
1113
|
if (preloadAssets === "blocking") {
|
|
@@ -1235,7 +1132,8 @@ var novely = ({
|
|
|
1235
1132
|
[null, 0]
|
|
1236
1133
|
],
|
|
1237
1134
|
state,
|
|
1238
|
-
[intime(Date.now()), "auto"]
|
|
1135
|
+
[intime(Date.now()), "auto"],
|
|
1136
|
+
[]
|
|
1239
1137
|
];
|
|
1240
1138
|
};
|
|
1241
1139
|
const getLanguageWithoutParameters = () => {
|
|
@@ -1556,6 +1454,61 @@ var novely = ({
|
|
|
1556
1454
|
const getCharacterAssets = (character, emotion) => {
|
|
1557
1455
|
return toArray(characters[character].emotions[emotion]).map(handleImageAsset);
|
|
1558
1456
|
};
|
|
1457
|
+
const getCharacterName = (character) => {
|
|
1458
|
+
const c = character;
|
|
1459
|
+
const cs = characters;
|
|
1460
|
+
const [lang] = storageData.get().meta;
|
|
1461
|
+
if (c && c in cs) {
|
|
1462
|
+
const block = cs[c].name;
|
|
1463
|
+
if (typeof block === "string") {
|
|
1464
|
+
return block;
|
|
1465
|
+
}
|
|
1466
|
+
if (lang in block) {
|
|
1467
|
+
return block[lang];
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
return String(c) || "";
|
|
1471
|
+
};
|
|
1472
|
+
const getDialogOverview = () => {
|
|
1473
|
+
const { value: save2 } = useStack(MAIN_CONTEXT_KEY);
|
|
1474
|
+
const stateSnapshots = save2[3];
|
|
1475
|
+
const { queue } = getActionsFromPath(story, save2[0], false);
|
|
1476
|
+
const [lang] = storageData.get().meta;
|
|
1477
|
+
const dialogItem = [];
|
|
1478
|
+
for (let p = 0, i = 0; i < queue.length; i++) {
|
|
1479
|
+
const action2 = queue[i];
|
|
1480
|
+
if (action2[0] === "dialog") {
|
|
1481
|
+
const [_, name, text] = action2;
|
|
1482
|
+
let voice = void 0;
|
|
1483
|
+
for (let j = i - 1; j > p; j--) {
|
|
1484
|
+
const action3 = queue[j];
|
|
1485
|
+
if (isUserRequiredAction(action3) || isSkippedDuringRestore(action3[0])) break;
|
|
1486
|
+
if (action3[0] === "stopVoice") break;
|
|
1487
|
+
if (action3[0] === "voice") {
|
|
1488
|
+
voice = action3[1];
|
|
1489
|
+
break;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
dialogItem.push({
|
|
1493
|
+
name,
|
|
1494
|
+
text,
|
|
1495
|
+
voice
|
|
1496
|
+
});
|
|
1497
|
+
p = i;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
const entries = dialogItem.map(({ name, text, voice }, i) => {
|
|
1501
|
+
const state = stateSnapshots[i];
|
|
1502
|
+
const audioSource = isString(voice) ? voice : isAsset(voice) ? voice : voice == void 0 ? voice : voice[lang];
|
|
1503
|
+
name = name ? getCharacterName(name) : "";
|
|
1504
|
+
return {
|
|
1505
|
+
name: templateReplace(name, state),
|
|
1506
|
+
text: templateReplace(text, state),
|
|
1507
|
+
voice: audioSource ? handleAudioAsset(audioSource) : ""
|
|
1508
|
+
};
|
|
1509
|
+
});
|
|
1510
|
+
return entries;
|
|
1511
|
+
};
|
|
1559
1512
|
const renderer = createRenderer({
|
|
1560
1513
|
mainContextKey: MAIN_CONTEXT_KEY,
|
|
1561
1514
|
characters: getCharactersData(characters),
|
|
@@ -1577,6 +1530,7 @@ var novely = ({
|
|
|
1577
1530
|
getLanguageDisplayName,
|
|
1578
1531
|
getCharacterColor,
|
|
1579
1532
|
getCharacterAssets,
|
|
1533
|
+
getDialogOverview,
|
|
1580
1534
|
getResourseType: getResourseTypeForRenderer
|
|
1581
1535
|
});
|
|
1582
1536
|
const useStack = createUseStackFunction(renderer);
|
|
@@ -1639,9 +1593,9 @@ var novely = ({
|
|
|
1639
1593
|
}
|
|
1640
1594
|
};
|
|
1641
1595
|
const match = matchAction(matchActionOptions, {
|
|
1642
|
-
wait({ ctx, push }, [time]) {
|
|
1596
|
+
wait({ ctx, data: data2, push }, [time]) {
|
|
1643
1597
|
if (ctx.meta.restoring) return;
|
|
1644
|
-
setTimeout(push, isFunction(time) ? time(
|
|
1598
|
+
setTimeout(push, isFunction(time) ? time(data2) : time);
|
|
1645
1599
|
},
|
|
1646
1600
|
showBackground({ ctx, push }, [background]) {
|
|
1647
1601
|
if (isString(background) || isAsset(background)) {
|
|
@@ -1711,21 +1665,11 @@ var novely = ({
|
|
|
1711
1665
|
ctx.character(character).remove(className, style, duration, ctx.meta.restoring).then(push);
|
|
1712
1666
|
},
|
|
1713
1667
|
dialog({ ctx, data: data2, forward }, [character, content, emotion]) {
|
|
1714
|
-
const name = (
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
const block = cs[c].name;
|
|
1720
|
-
if (typeof block === "string") {
|
|
1721
|
-
return block;
|
|
1722
|
-
}
|
|
1723
|
-
if (lang in block) {
|
|
1724
|
-
return block[lang];
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
return c || "";
|
|
1728
|
-
})();
|
|
1668
|
+
const name = getCharacterName(character);
|
|
1669
|
+
const stack = useStack(ctx);
|
|
1670
|
+
if (!ctx.meta.restoring && !ctx.meta.goingBack) {
|
|
1671
|
+
stack.value[3].push(clone(data2));
|
|
1672
|
+
}
|
|
1729
1673
|
ctx.clearBlockingActions("dialog");
|
|
1730
1674
|
ctx.dialog(templateReplace(content, data2), templateReplace(name, data2), character, emotion, forward);
|
|
1731
1675
|
},
|
|
@@ -1752,19 +1696,19 @@ var novely = ({
|
|
|
1752
1696
|
const transformedChoices = choices.map(([content, _children, active, visible, onSelect, image]) => {
|
|
1753
1697
|
const active$ = store(false);
|
|
1754
1698
|
const visible$ = store(false);
|
|
1755
|
-
const
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
});
|
|
1762
|
-
const visibleValue = !visible || visible({
|
|
1699
|
+
const lang = getLanguageFromStore(storageData);
|
|
1700
|
+
const getCheckValue = (fn) => {
|
|
1701
|
+
if (!fn) {
|
|
1702
|
+
return true;
|
|
1703
|
+
}
|
|
1704
|
+
return fn({
|
|
1763
1705
|
lang,
|
|
1764
|
-
state
|
|
1706
|
+
state: getStateAtCtx(ctx)
|
|
1765
1707
|
});
|
|
1766
|
-
|
|
1767
|
-
|
|
1708
|
+
};
|
|
1709
|
+
const update = () => {
|
|
1710
|
+
active$.set(getCheckValue(active));
|
|
1711
|
+
visible$.set(getCheckValue(visible));
|
|
1768
1712
|
};
|
|
1769
1713
|
update();
|
|
1770
1714
|
const onSelectGuarded = onSelect || noop;
|
|
@@ -1808,6 +1752,7 @@ var novely = ({
|
|
|
1808
1752
|
["jump", scene],
|
|
1809
1753
|
[null, -1]
|
|
1810
1754
|
];
|
|
1755
|
+
stack.value[3] = [];
|
|
1811
1756
|
match("clear", [], {
|
|
1812
1757
|
ctx,
|
|
1813
1758
|
data: data2
|
|
@@ -1822,12 +1767,12 @@ var novely = ({
|
|
|
1822
1767
|
push
|
|
1823
1768
|
);
|
|
1824
1769
|
},
|
|
1825
|
-
condition({ ctx }, [condition, variants]) {
|
|
1770
|
+
condition({ ctx, data: data2 }, [condition, variants]) {
|
|
1826
1771
|
if (DEV3 && Object.values(variants).length === 0) {
|
|
1827
1772
|
throw new Error(`Attempt to use Condition action with empty variants object`);
|
|
1828
1773
|
}
|
|
1829
1774
|
if (!ctx.meta.restoring) {
|
|
1830
|
-
const val = String(condition(
|
|
1775
|
+
const val = String(condition(data2));
|
|
1831
1776
|
if (DEV3 && !variants[val]) {
|
|
1832
1777
|
throw new Error(`Attempt to go to unknown variant "${val}"`);
|
|
1833
1778
|
}
|
|
@@ -1946,22 +1891,23 @@ var novely = ({
|
|
|
1946
1891
|
});
|
|
1947
1892
|
const render = (ctx) => {
|
|
1948
1893
|
const stack = useStack(ctx);
|
|
1949
|
-
const
|
|
1894
|
+
const [path, state] = stack.value;
|
|
1895
|
+
const referred = refer(path);
|
|
1950
1896
|
if (isAction(referred)) {
|
|
1951
1897
|
const [action2, ...props] = referred;
|
|
1952
1898
|
match(action2, props, {
|
|
1953
1899
|
ctx,
|
|
1954
|
-
data:
|
|
1900
|
+
data: state
|
|
1955
1901
|
});
|
|
1956
1902
|
} else if (Object.values(story).some((branch) => branch === referred)) {
|
|
1957
1903
|
match("end", [], {
|
|
1958
1904
|
ctx,
|
|
1959
|
-
data:
|
|
1905
|
+
data: state
|
|
1960
1906
|
});
|
|
1961
1907
|
} else {
|
|
1962
1908
|
match("exit", [], {
|
|
1963
1909
|
ctx,
|
|
1964
|
-
data:
|
|
1910
|
+
data: state
|
|
1965
1911
|
});
|
|
1966
1912
|
}
|
|
1967
1913
|
};
|
|
@@ -1974,10 +1920,10 @@ var novely = ({
|
|
|
1974
1920
|
meta: [lang]
|
|
1975
1921
|
} = storageData.get();
|
|
1976
1922
|
const obj = values || data2;
|
|
1977
|
-
const
|
|
1923
|
+
const str = flattenAllowedContent(!isFunction(content) && !isString(content) ? content[lang] : content, obj);
|
|
1978
1924
|
const t2 = translation[lang];
|
|
1979
1925
|
const pluralRules = (t2.plural || t2.actions) && new Intl.PluralRules(t2.tag || lang);
|
|
1980
|
-
return replace(
|
|
1926
|
+
return replace(str, obj, t2.plural, t2.actions, pluralRules);
|
|
1981
1927
|
};
|
|
1982
1928
|
const data = (value) => {
|
|
1983
1929
|
const _data = storageData.get().data;
|
|
@@ -2174,7 +2120,9 @@ var RU = {
|
|
|
2174
2120
|
CloseMenu: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E",
|
|
2175
2121
|
MusicVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u043C\u0443\u0437\u044B\u043A\u0438",
|
|
2176
2122
|
SoundVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0437\u0432\u0443\u043A\u043E\u0432",
|
|
2177
|
-
VoiceVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0440\u0435\u0447\u0438"
|
|
2123
|
+
VoiceVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0440\u0435\u0447\u0438",
|
|
2124
|
+
Close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C",
|
|
2125
|
+
DialogOverview: "\u041E\u0431\u0437\u043E\u0440 \u0434\u0438\u0430\u043B\u043E\u0433\u0430"
|
|
2178
2126
|
};
|
|
2179
2127
|
var EN = {
|
|
2180
2128
|
NewGame: "New Game",
|
|
@@ -2210,7 +2158,9 @@ var EN = {
|
|
|
2210
2158
|
CloseMenu: "Close menu",
|
|
2211
2159
|
MusicVolume: "Music volume",
|
|
2212
2160
|
SoundVolume: "Sound volume",
|
|
2213
|
-
VoiceVolume: "Voice volume"
|
|
2161
|
+
VoiceVolume: "Voice volume",
|
|
2162
|
+
Close: "Close",
|
|
2163
|
+
DialogOverview: "Dialog Overview"
|
|
2214
2164
|
};
|
|
2215
2165
|
var KK = {
|
|
2216
2166
|
NewGame: "\u0416\u0430\u04A3\u0430 \u043E\u0439\u044B\u043D",
|
|
@@ -2246,7 +2196,9 @@ var KK = {
|
|
|
2246
2196
|
CloseMenu: "\u041C\u04D9\u0437\u0456\u0440\u0434\u0456 \u0436\u0430\u0431\u0443",
|
|
2247
2197
|
MusicVolume: "\u041C\u0443\u0437\u044B\u043A\u0430\u043D\u044B\u04A3 \u043A\u04E9\u043B\u0435\u043C\u0456",
|
|
2248
2198
|
SoundVolume: "\u0414\u044B\u0431\u044B\u0441\u0442\u0430\u0440\u0434\u044B\u04A3 \u043A\u04E9\u043B\u0435\u043C\u0456",
|
|
2249
|
-
VoiceVolume: "\u0421\u04E9\u0439\u043B\u0435\u0443 \u043A\u04E9\u043B\u0435\u043C\u0456"
|
|
2199
|
+
VoiceVolume: "\u0421\u04E9\u0439\u043B\u0435\u0443 \u043A\u04E9\u043B\u0435\u043C\u0456",
|
|
2200
|
+
Close: "\u0416\u0430\u0431\u0443",
|
|
2201
|
+
DialogOverview: "\u0414\u0438\u0430\u043B\u043E\u0433\u049B\u0430 \u0428\u043E\u043B\u0443"
|
|
2250
2202
|
};
|
|
2251
2203
|
var JP = {
|
|
2252
2204
|
NewGame: "\u300C\u65B0\u3057\u3044\u30B2\u30FC\u30E0\u300D",
|
|
@@ -2282,7 +2234,137 @@ var JP = {
|
|
|
2282
2234
|
CloseMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B",
|
|
2283
2235
|
MusicVolume: "\u97F3\u697D\u306E\u30DC\u30EA\u30E5\u30FC\u30E0",
|
|
2284
2236
|
SoundVolume: "\u97F3\u91CF",
|
|
2285
|
-
VoiceVolume: "\u30B9\u30D4\u30FC\u30C1\u306E\u91CF"
|
|
2237
|
+
VoiceVolume: "\u30B9\u30D4\u30FC\u30C1\u306E\u91CF",
|
|
2238
|
+
Close: "\u9589\u3058\u308B",
|
|
2239
|
+
DialogOverview: "\u30C0\u30A4\u30A2\u30ED\u30B0\u306E\u6982\u8981"
|
|
2240
|
+
};
|
|
2241
|
+
|
|
2242
|
+
// src/asset.ts
|
|
2243
|
+
import { memoize as memoize4, once } from "es-toolkit/function";
|
|
2244
|
+
import { DEV as DEV4 } from "esm-env";
|
|
2245
|
+
|
|
2246
|
+
// src/audio-codecs.ts
|
|
2247
|
+
var cut = (str) => str.replace(/^no$/, "");
|
|
2248
|
+
var audio = new Audio();
|
|
2249
|
+
var canPlay = (type) => !!cut(audio.canPlayType(type));
|
|
2250
|
+
var canPlayMultiple = (...types) => types.some((type) => canPlay(type));
|
|
2251
|
+
var supportsMap = {
|
|
2252
|
+
mp3: canPlayMultiple("audio/mpeg;", "audio/mp3;"),
|
|
2253
|
+
mpeg: canPlay("audio/mpeg;"),
|
|
2254
|
+
opus: canPlay('audio/ogg; codecs="opus"'),
|
|
2255
|
+
ogg: canPlay('audio/ogg; codecs="vorbis"'),
|
|
2256
|
+
oga: canPlay('audio/ogg; codecs="vorbis"'),
|
|
2257
|
+
wav: canPlayMultiple('audio/wav; codecs="1"', "audio/wav;"),
|
|
2258
|
+
aac: canPlay("audio/aac;"),
|
|
2259
|
+
caf: canPlay("audio/x-caf;"),
|
|
2260
|
+
m4a: canPlayMultiple("audio/x-m4a;", "audio/m4a;", "audio/aac;"),
|
|
2261
|
+
m4b: canPlayMultiple("audio/x-m4b;", "audio/m4b;", "audio/aac;"),
|
|
2262
|
+
mp4: canPlayMultiple("audio/x-mp4;", "audio/mp4;", "audio/aac;"),
|
|
2263
|
+
weba: canPlay('audio/webm; codecs="vorbis"'),
|
|
2264
|
+
webm: canPlay('audio/webm; codecs="vorbis"'),
|
|
2265
|
+
dolby: canPlay('audio/mp4; codecs="ec-3"'),
|
|
2266
|
+
flac: canPlayMultiple("audio/x-flac;", "audio/flac;")
|
|
2267
|
+
};
|
|
2268
|
+
|
|
2269
|
+
// src/image-formats.ts
|
|
2270
|
+
var avif = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
|
|
2271
|
+
var jxl = "data:image/jxl;base64,/woIAAAMABKIAgC4AF3lEgAAFSqjjBu8nOv58kOHxbSN6wxttW1hSaLIODZJJ3BIEkkaoCUzGM6qJAE=";
|
|
2272
|
+
var webp = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
|
|
2273
|
+
var supportsFormat = (source) => {
|
|
2274
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
2275
|
+
const img = Object.assign(document.createElement("img"), {
|
|
2276
|
+
src: source
|
|
2277
|
+
});
|
|
2278
|
+
img.onload = img.onerror = () => {
|
|
2279
|
+
resolve(img.height === 2);
|
|
2280
|
+
};
|
|
2281
|
+
return promise;
|
|
2282
|
+
};
|
|
2283
|
+
var supportsMap2 = {
|
|
2284
|
+
avif: false,
|
|
2285
|
+
jxl: false,
|
|
2286
|
+
webp: false
|
|
2287
|
+
};
|
|
2288
|
+
var formatsMap = {
|
|
2289
|
+
avif,
|
|
2290
|
+
jxl,
|
|
2291
|
+
webp
|
|
2292
|
+
};
|
|
2293
|
+
var loadImageFormatsSupport = async () => {
|
|
2294
|
+
const promises = [];
|
|
2295
|
+
for (const [format, source] of Object.entries(formatsMap)) {
|
|
2296
|
+
const promise = supportsFormat(source).then((supported) => {
|
|
2297
|
+
supportsMap2[format] = supported;
|
|
2298
|
+
});
|
|
2299
|
+
promises.push(promise);
|
|
2300
|
+
}
|
|
2301
|
+
await Promise.all(promises);
|
|
2302
|
+
};
|
|
2303
|
+
loadImageFormatsSupport();
|
|
2304
|
+
|
|
2305
|
+
// src/asset.ts
|
|
2306
|
+
var getType = memoize4(
|
|
2307
|
+
(extensions) => {
|
|
2308
|
+
if (extensions.every((extension) => HOWLER_SUPPORTED_FILE_FORMATS.has(extension))) {
|
|
2309
|
+
return "audio";
|
|
2310
|
+
}
|
|
2311
|
+
if (extensions.every((extension) => SUPPORTED_IMAGE_FILE_FORMATS.has(extension))) {
|
|
2312
|
+
return "image";
|
|
2313
|
+
}
|
|
2314
|
+
throw extensions;
|
|
2315
|
+
},
|
|
2316
|
+
{
|
|
2317
|
+
getCacheKey: (extensions) => extensions.join("~")
|
|
2318
|
+
}
|
|
2319
|
+
);
|
|
2320
|
+
var SUPPORT_MAPS = {
|
|
2321
|
+
image: supportsMap2,
|
|
2322
|
+
audio: supportsMap
|
|
2323
|
+
};
|
|
2324
|
+
var assetPrivate = memoize4(
|
|
2325
|
+
(variants) => {
|
|
2326
|
+
if (DEV4 && variants.length === 0) {
|
|
2327
|
+
throw new Error(`Attempt to use "asset" function without arguments`);
|
|
2328
|
+
}
|
|
2329
|
+
const map = {};
|
|
2330
|
+
const extensions = [];
|
|
2331
|
+
for (const v of variants) {
|
|
2332
|
+
const e = getUrlFileExtension(v);
|
|
2333
|
+
map[e] = v;
|
|
2334
|
+
extensions.push(e);
|
|
2335
|
+
}
|
|
2336
|
+
const type = getType(extensions);
|
|
2337
|
+
const getSource = once(() => {
|
|
2338
|
+
const support = SUPPORT_MAPS[type];
|
|
2339
|
+
for (const extension of extensions) {
|
|
2340
|
+
if (extension in support) {
|
|
2341
|
+
if (support[extension]) {
|
|
2342
|
+
return map[extension];
|
|
2343
|
+
}
|
|
2344
|
+
} else {
|
|
2345
|
+
return map[extension];
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
if (DEV4) {
|
|
2349
|
+
throw new Error(`No matching asset was found for ${variants.map((v) => `"${v}"`).join(", ")}`);
|
|
2350
|
+
}
|
|
2351
|
+
return "";
|
|
2352
|
+
});
|
|
2353
|
+
return {
|
|
2354
|
+
get source() {
|
|
2355
|
+
return getSource();
|
|
2356
|
+
},
|
|
2357
|
+
get type() {
|
|
2358
|
+
return type;
|
|
2359
|
+
}
|
|
2360
|
+
};
|
|
2361
|
+
},
|
|
2362
|
+
{
|
|
2363
|
+
getCacheKey: (variants) => variants.join("~")
|
|
2364
|
+
}
|
|
2365
|
+
);
|
|
2366
|
+
var asset = (...variants) => {
|
|
2367
|
+
return assetPrivate(variants);
|
|
2286
2368
|
};
|
|
2287
2369
|
export {
|
|
2288
2370
|
EN,
|