@novely/core 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ // src/constants.ts
2
+ var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
3
+ var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
4
+ var BLOCK_STATEMENTS = /* @__PURE__ */ new Set(["choice", "condition", "block"]);
5
+ var EMPTY_SET = /* @__PURE__ */ new Set();
6
+ var DEFAULT_TYPEWRITER_SPEED = "Medium";
7
+
1
8
  // src/utils.ts
2
9
  var matchAction = (values) => {
3
10
  return (action, props) => {
@@ -70,8 +77,8 @@ var vibrate = (pattern) => {
70
77
  }
71
78
  };
72
79
  var findLastIndex = (array, fn) => {
73
- for (let i = array.length - 1; i > 0; i--) {
74
- if (fn(array[i])) {
80
+ for (let i = array.length - 1; i >= 0; i--) {
81
+ if (fn(array[i], array[i + 1])) {
75
82
  return i;
76
83
  }
77
84
  }
@@ -99,6 +106,24 @@ var createDeferredPromise = () => {
99
106
  });
100
107
  return { resolve, reject, promise };
101
108
  };
109
+ var findLastPathItemBeforeItemOfType = (path, name) => {
110
+ const index = findLastIndex(path, ([_name, _value], next) => {
111
+ return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
112
+ });
113
+ return path[index];
114
+ };
115
+ var isBlockStatement = (statement) => {
116
+ return BLOCK_STATEMENTS.has(statement);
117
+ };
118
+ var isBlockExitStatement = (statement) => {
119
+ return BLOCK_EXIT_STATEMENTS.has(statement);
120
+ };
121
+ var isSkippedDurigRestore = (item) => {
122
+ return SKIPPED_DURING_RESTORE.has(item);
123
+ };
124
+ var isAction = (element) => {
125
+ return Array.isArray(element) && isString(element[0]);
126
+ };
102
127
 
103
128
  // src/global.ts
104
129
  var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
@@ -127,13 +152,6 @@ var store = (current, subscribers = /* @__PURE__ */ new Set()) => {
127
152
  // src/novely.ts
128
153
  import { all as deepmerge } from "deepmerge";
129
154
  import { klona } from "klona/json";
130
-
131
- // src/constants.ts
132
- var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
133
- var EMPTY_SET = /* @__PURE__ */ new Set();
134
- var DEFAULT_TYPEWRITER_SPEED = "Medium";
135
-
136
- // src/novely.ts
137
155
  import { replace as replaceT9N } from "@novely/t9n";
138
156
  var novely = ({
139
157
  characters,
@@ -339,31 +357,46 @@ var novely = ({
339
357
  latest = klona(initial);
340
358
  }
341
359
  restoring = true, stack.value = latest;
360
+ const path = stack.value[0];
342
361
  let current = story;
362
+ let precurrent;
363
+ let ignoreNested = false;
343
364
  let index = 0;
344
365
  const max = stack.value[0].reduce((acc, [type, val]) => {
345
- if (isNull(type) && isNumber(val))
366
+ if (isNull(type) && isNumber(val)) {
346
367
  return acc + 1;
368
+ }
347
369
  return acc;
348
370
  }, 0);
349
371
  const queue = [];
350
372
  const keep = /* @__PURE__ */ new Set();
351
373
  const characters2 = /* @__PURE__ */ new Set();
352
- for (const [type, val] of stack.value[0]) {
374
+ const blocks = [];
375
+ for (const [type, val] of path) {
353
376
  if (type === null) {
354
- if (isString(val)) {
355
- current = current[val];
356
- } else if (isNumber(val)) {
377
+ precurrent = current;
378
+ if (isNumber(val)) {
357
379
  index++;
358
- for (let i = 0; i <= val; i++) {
359
- const [action2, ...meta] = current[i];
380
+ let startIndex = 0;
381
+ if (ignoreNested) {
382
+ const prev = findLastPathItemBeforeItemOfType(path.slice(0, index), "block");
383
+ if (prev) {
384
+ startIndex = prev[1];
385
+ ignoreNested = false;
386
+ }
387
+ }
388
+ for (let i = startIndex; i <= val; i++) {
389
+ const item = current[i];
390
+ if (!isAction(item))
391
+ continue;
392
+ const [action2, ...meta] = item;
360
393
  const push2 = () => {
361
394
  keep.add(action2);
362
395
  queue.push([action2, meta]);
363
396
  };
364
397
  if (action2 === "showCharacter")
365
398
  characters2.add(meta[0]);
366
- if (SKIPPED_DURING_RESTORE.has(action2) || isUserRequiredAction(action2, meta)) {
399
+ if (isSkippedDurigRestore(action2) || isUserRequiredAction(action2, meta)) {
367
400
  if (index === max && i === val) {
368
401
  push2();
369
402
  } else {
@@ -372,12 +405,20 @@ var novely = ({
372
405
  }
373
406
  push2();
374
407
  }
375
- current = current[val];
376
408
  }
409
+ current = current[val];
377
410
  } else if (type === "choice") {
411
+ blocks.push(precurrent = current);
378
412
  current = current[val + 1][1];
379
413
  } else if (type === "condition") {
414
+ blocks.push(precurrent = current);
380
415
  current = current[2][val];
416
+ } else if (type === "block") {
417
+ blocks.push(precurrent);
418
+ current = story[val];
419
+ } else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
420
+ current = blocks.pop();
421
+ ignoreNested = true;
381
422
  }
382
423
  }
383
424
  renderer.ui.showScreen("game");
@@ -392,7 +433,8 @@ var novely = ({
392
433
  const c0 = _meta[0];
393
434
  const c1 = meta[0];
394
435
  const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
395
- return isIdenticalID || str(c0) === str(c1);
436
+ const isIdenticalByReference = c0 === c1;
437
+ return isIdenticalID || isIdenticalByReference || str(c0) === str(c1);
396
438
  });
397
439
  if (notLatest)
398
440
  continue;
@@ -423,15 +465,25 @@ var novely = ({
423
465
  }
424
466
  restoring = goingBack = false, render();
425
467
  };
426
- const refer = () => {
468
+ const refer = (path = stack.value[0]) => {
427
469
  let current = story;
428
- for (const [type, val] of stack.value[0]) {
470
+ let precurrent = story;
471
+ const blocks = [];
472
+ for (const [type, val] of path) {
429
473
  if (type === null) {
474
+ precurrent = current;
430
475
  current = current[val];
431
476
  } else if (type === "choice") {
477
+ blocks.push(precurrent = current);
432
478
  current = current[val + 1][1];
433
479
  } else if (type === "condition") {
480
+ blocks.push(precurrent = current);
434
481
  current = current[2][val];
482
+ } else if (type === "block") {
483
+ blocks.push(precurrent);
484
+ current = story[val];
485
+ } else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
486
+ current = blocks.pop();
435
487
  }
436
488
  }
437
489
  return current;
@@ -554,9 +606,13 @@ var novely = ({
554
606
  renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
555
607
  },
556
608
  condition([condition]) {
557
- const value = condition();
558
- if (!restoring)
559
- stack.value[0].push(["condition", String(value)], [null, 0]), render();
609
+ if (!restoring) {
610
+ stack.value[0].push(
611
+ ["condition", String(condition())],
612
+ [null, 0]
613
+ );
614
+ render();
615
+ }
560
616
  },
561
617
  end() {
562
618
  match("clear", []);
@@ -608,24 +664,55 @@ var novely = ({
608
664
  renderer.text(text.map((content) => unwrap(content)).join(" "), forward, goingBack);
609
665
  },
610
666
  exit() {
667
+ if (restoring)
668
+ return;
611
669
  const path = stack.value[0];
612
- let exited = false;
670
+ const last = path.at(-1);
671
+ const ignore = [];
672
+ if (!isAction(refer(path))) {
673
+ if (last && isNull(last[0]) && isNumber(last[1])) {
674
+ last[1]--;
675
+ } else {
676
+ path.pop();
677
+ }
678
+ }
613
679
  for (let i = path.length - 1; i > 0; i--) {
614
- if (path[i][0] !== "choice" && path[i][0] !== "condition")
680
+ const [name] = path[i];
681
+ if (isBlockExitStatement(name)) {
682
+ ignore.push(name);
683
+ }
684
+ if (!isBlockStatement(name))
685
+ continue;
686
+ if (ignore.at(-1)?.startsWith(name)) {
687
+ ignore.pop();
615
688
  continue;
616
- exited = true;
617
- stack.value[0] = path.slice(0, i);
618
- next();
689
+ }
690
+ path.push([`${name}:exit`]);
691
+ const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
692
+ if (prev)
693
+ path.push([null, prev[1] + 1]);
694
+ if (!isAction(refer(path))) {
695
+ path.pop();
696
+ continue;
697
+ }
619
698
  break;
620
699
  }
621
- if (exited)
622
- render();
700
+ render();
623
701
  },
624
702
  preload([source]) {
625
703
  if (!PRELOADED_ASSETS.has(source) && !goingBack && !restoring) {
626
704
  PRELOADED_ASSETS.add(document.createElement("img").src = source);
627
705
  }
628
706
  push();
707
+ },
708
+ block([scene]) {
709
+ if (!restoring) {
710
+ stack.value[0].push(
711
+ ["block", scene],
712
+ [null, 0]
713
+ );
714
+ render();
715
+ }
629
716
  }
630
717
  });
631
718
  const enmemory = () => {
@@ -639,13 +726,11 @@ var novely = ({
639
726
  const next = () => {
640
727
  const path = stack.value[0];
641
728
  const last = path.at(-1);
642
- if (!last)
643
- return;
644
- if (isNull(last[0]) && isNumber(last[1])) {
645
- last[1] = last[1] + 1;
646
- return;
729
+ if (last && isNull(last[0]) && isNumber(last[1])) {
730
+ last[1]++;
731
+ } else {
732
+ path.push([null, 0]);
647
733
  }
648
- path.push([null, 0]);
649
734
  };
650
735
  const render = () => {
651
736
  const referred = refer();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/global.ts","../src/store.ts","../src/novely.ts","../src/constants.ts","../src/storage.ts"],"sourcesContent":["import type { ActionProxyProvider, CustomHandler } from './action';\nimport type { Character } from './character';\nimport type { Thenable } from './types';\n\ntype MatchActionMap = {\n\t[Key in keyof ActionProxyProvider<Record<string, Character>>]: (\n\t\tdata: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>,\n\t) => void;\n};\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n\tcustom: (value: [handler: CustomHandler]) => Thenable<void>;\n};\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n\treturn (action: keyof MatchActionMap, props: any) => {\n\t\treturn values[action](props);\n\t};\n};\n\nconst isNumber = (val: unknown): val is number => {\n\treturn typeof val === 'number';\n};\n\nconst isNull = (val: unknown): val is null => {\n\treturn val === null;\n};\n\nconst isString = (val: unknown): val is string => {\n\treturn typeof val === 'string';\n};\n\nconst isFunction = (val: unknown): val is (...parameters: any[]) => any => {\n\treturn typeof val === 'function';\n};\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n\treturn Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then);\n};\n\nconst isEmpty = (val: unknown): val is Record<PropertyKey, never> => {\n\treturn typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n};\n\nconst isCSSImage = (str: string) => {\n\tconst startsWith = String.prototype.startsWith.bind(str);\n\n\treturn startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n};\n\nconst str = String;\n\nconst isUserRequiredAction = (\n\taction: keyof MatchActionMapComplete,\n\tmeta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>,\n) => {\n\treturn action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n};\n\nconst getLanguage = (languages: string[]) => {\n\tlet { language } = navigator;\n\n\tif (languages.includes(language)) {\n\t\treturn language;\n\t} else if (languages.includes((language = language.slice(0, 2)))) {\n\t\treturn language;\n\t} else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n\t\treturn language;\n\t}\n\n\t/**\n\t * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n\t */\n\treturn languages[0];\n};\n\n/**\n * @copyright Techlead LLC\n * @see https://learn.javascript.ru/task/throttle\n */\nconst throttle = <Fn extends (...args: any[]) => any>(fn: Fn, ms: number) => {\n\tlet throttled = false,\n\t\tsavedArgs: any,\n\t\tsavedThis: any;\n\n\tfunction wrapper(this: any, ...args: any[]) {\n\t\tif (throttled) {\n\t\t\tsavedArgs = args;\n\t\t\t/* eslint-disable unicorn/no-this-assignment, @typescript-eslint/no-this-alias */\n\t\t\tsavedThis = this;\n\t\t\treturn;\n\t\t}\n\n\t\tfn.apply(this, args as unknown as any[]);\n\n\t\tthrottled = true;\n\n\t\tsetTimeout(function () {\n\t\t\tthrottled = false;\n\n\t\t\tif (savedArgs) {\n\t\t\t\twrapper.apply(savedThis, savedArgs);\n\t\t\t\tsavedArgs = savedThis = null;\n\t\t\t}\n\t\t}, ms);\n\t}\n\n\treturn wrapper as unknown as (...args: Parameters<Fn>) => void;\n};\n\nconst vibrate = (pattern: VibratePattern) => {\n\ttry {\n\t\tif ('vibrate' in navigator) {\n\t\t\tnavigator.vibrate(pattern);\n\t\t}\n\t} catch {}\n};\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n\tfor (let i = array.length - 1; i > 0; i--) {\n\t\tif (fn(array[i])) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n};\n\nconst preloadImagesBlocking = (images: Set<string>) => {\n\treturn Promise.allSettled([...images].map(src => {\n\t\tconst img = document.createElement('img');\n\n\t\timg.src = src;\n\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\t/**\n\t\t\t * Image is already loaded\n\t\t\t */\n\t\t\tif (img.complete && img.naturalHeight !== 0) {\n\t\t\t\tresolve(void 0);\n\t\t\t}\n\n\t\t\timg.addEventListener('load', resolve);\n\t\t\timg.addEventListener('abort', reject);\n\t\t\timg.addEventListener('error', reject);\n\t\t});\n\t}));\n}\n\nconst createDeferredPromise = <T = void>() => {\n\tlet resolve!: (value: T | PromiseLike<T>) => void, reject!: (reason?: any) => void;\n\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res; reject = rej;\n\t});\n\n\treturn { resolve, reject, promise }\n}\n\nexport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n\tpreloadImagesBlocking,\n\tcreateDeferredPromise\n};\n","const PRELOADED_ASSETS = new Set<string>();\n\nexport { PRELOADED_ASSETS }\n","type Stored<T> = {\n\tsubscribe: (cb: (value: T) => void) => () => void;\n\tupdate: (fn: (prev: T) => T) => void;\n\tget: () => T;\n};\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n\tconst subscribe = (cb: (value: T) => void) => {\n\t\tsubscribers.add(cb), cb(current);\n\n\t\treturn () => {\n\t\t\tsubscribers.delete(cb);\n\t\t};\n\t};\n\n\tconst push = (value: T) => {\n\t\tfor (const cb of subscribers) cb(value);\n\t};\n\n\tconst update = (fn: (prev: T) => T) => {\n\t\tpush((current = fn(current)));\n\t};\n\n\tconst get = () => {\n\t\treturn current;\n\t};\n\n\treturn { subscribe, update, get } as const;\n};\n\nexport { store };\nexport type { Stored };\n","import type { Character } from './character';\nimport type {\n\tActionProxyProvider,\n\tGetActionParameters,\n\tStory,\n\tValidAction,\n\tUnwrappable,\n\tCustomHandler,\n} from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration, ActionFN } from './types';\nimport type { Renderer, RendererInit } from './renderer';\nimport type { SetupT9N } from '@novely/t9n';\nimport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetLanguage as defaultGetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n\tpreloadImagesBlocking,\n\tcreateDeferredPromise\n} from './utils';\nimport { PRELOADED_ASSETS } from './global';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge';\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET, DEFAULT_TYPEWRITER_SPEED } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n> {\n\t/**\n\t * An array of languages supported by the game.\n\t */\n\tlanguages: Languages[];\n\t/**\n\t * An object containing the characters in the game.\n\t */\n\tcharacters: Characters;\n\t/**\n\t * An object that provides access to the game's storage system.\n\t */\n\tstorage: Storage;\n\t/**\n\t * Delay loading data until Promise is resolved\n\t */\n\tstorageDelay?: Promise<void>;\n\t/**\n\t * A function that returns a Renderer object used to display the game's content\n\t */\n\trenderer: (characters: RendererInit) => Renderer;\n\t/**\n\t * An optional property that specifies the initial screen to display when the game starts\n\t */\n\tinitialScreen?: NovelyScreen;\n\t/**\n\t * An object containing the translation functions used in the game\n\t */\n\tt9n: Inter;\n\t/**\n\t * Initial state value\n\t */\n\tstate?: StateScheme;\n\t/**\n\t * Initial data value\n\t */\n\tdata?: DataScheme;\n\t/**\n\t * Enable autosaves or disable\n\t * @default true\n\t */\n\tautosaves?: boolean;\n\t/**\n\t * Migration from old saves to newer\n\t */\n\tmigrations?: Migration[];\n\t/**\n\t * For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage\n\t * @default 799\n\t */\n\tthrottleTimeout?: number;\n\t/**\n\t * Custom language detector\n\t * @param languages Supported languages aka `languages: []` in the config\n\t * @example ```ts\n\t * novely({\n\t * \t\tgetLanguage(languages, original) {\n\t * \t\t\t\tif (!sdk) return original(languages);\n\t * \t\t\t\treturn sdk.environment.i18n.lang // i.e. custom language from some sdk\n\t * \t\t}\n\t * })\n\t * ```\n\t */\n\tgetLanguage?: (languages: string[], original: typeof defaultGetLanguage) => string;\n\t/**\n\t * Ignores saved language, and uses `getLanguage` to get it on every engine start\n\t * @default false\n\t */\n\toverrideLanguage?: boolean;\n\t/**\n\t * Show a prompt before exiting a game\n\t * @default true\n\t */\n\taskBeforeExit?: boolean;\n\t/**\n\t * @default \"lazy\"\n\t */\n\tpreloadAssets?: \"lazy\" | \"blocking\"\n}\n\nconst novely = <\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n>({\n\tcharacters,\n\tstorage,\n\tstorageDelay = Promise.resolve(),\n\trenderer: createRenderer,\n\tinitialScreen = 'mainmenu',\n\tt9n,\n\tlanguages,\n\tstate: defaultState,\n\tdata: defaultData,\n\tautosaves = true,\n\tmigrations = [],\n\tthrottleTimeout = 799,\n\tgetLanguage = defaultGetLanguage,\n\toverrideLanguage = false,\n\taskBeforeExit = true,\n\tpreloadAssets = \"lazy\"\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n\tlet story: Story;\n\n\tconst times = new Set<number>();\n\n\tconst ASSETS_TO_PRELOAD = new Set<string>();\n\tconst assetsLoaded = createDeferredPromise();\n\n\t/**\n\t * Prevent `undefined`\n\t */\n\tdefaultData ||= {} as DataScheme;\n\tdefaultState ||= {} as StateScheme;\n\n\t/**\n\t * Saves timestamps created in this session\n\t */\n\tconst intime = (value: number) => {\n\t\treturn times.add(value), value;\n\t};\n\n\tconst withStory = async (s: Story) => {\n\t\t/**\n\t\t * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n\t\t */\n\t\tstory = Object.fromEntries(\n\t\t\tObject.entries(s).map(([name, items]) => {\n\t\t\t\tconst flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n\t\t\t\t\treturn item.flatMap((data) => {\n\t\t\t\t\t\tconst type = data[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * This is not just an action like `['name', ...arguments]`, but an array of actions\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (Array.isArray(type)) return flat(data as ValidAction[]);\n\n\t\t\t\t\t\treturn [data as ValidAction];\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\treturn [name, flat(items)];\n\t\t\t}),\n\t\t);\n\n\t\tif (preloadAssets === 'blocking' && ASSETS_TO_PRELOAD.size > 0) {\n\t\t\trenderer.ui.showScreen('loading');\n\n\t\t\tawait preloadImagesBlocking(ASSETS_TO_PRELOAD);\n\t\t}\n\n\t\tASSETS_TO_PRELOAD.clear();\n\t\tassetsLoaded.resolve();\n\n\t\t/**\n\t\t * When `initialScreen` is not a game, we can safely show it\n\t\t */\n\t\tif (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n\t};\n\n\tconst action = new Proxy({} as ActionProxyProvider<Characters>, {\n\t\tget(_, prop) {\n\t\t\treturn (...props: Parameters<ActionFN>) => {\n\t\t\t\tif (preloadAssets === 'blocking') {\n\t\t\t\t\t/**\n\t\t\t\t\t * Load backgrounds\n\t\t\t\t\t */\n\t\t\t\t\tif (prop === 'showBackground' && typeof props[0] === 'string' && isCSSImage(props[0])) {\n\t\t\t\t\t\tASSETS_TO_PRELOAD.add(props[0]);\n\t\t\t\t\t}\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Load characters\n\t\t\t\t\t */\n\t\t\t\t\tif (prop === 'showCharacter' && typeof props[0] === 'string' && typeof props[1] === 'string') {\n\t\t\t\t\t\tconst images = characters[props[0]].emotions[props[1]];\n\n\t\t\t\t\t\tif (typeof images === 'string') {\n\t\t\t\t\t\t\tASSETS_TO_PRELOAD.add(images);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (const asset of [images.head, images.body.left, images.body.right]) {\n\t\t\t\t\t\t\t\tASSETS_TO_PRELOAD.add(asset);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [prop, ...props];\n\t\t\t};\n\t\t},\n\t});\n\n\tfunction state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n\tfunction state(): StateScheme;\n\tfunction state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n\t\tif (!value) return stack.value[1] as StateScheme | void;\n\n\t\tconst prev = stack.value[1];\n\t\tconst val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n\t\tstack.value[1] = val as StateScheme;\n\t}\n\n\tconst getDefaultSave = (state = {}) => {\n\t\treturn [\n\t\t\t[\n\t\t\t\t[null, 'start'],\n\t\t\t\t[null, 0],\n\t\t\t],\n\t\t\tstate,\n\t\t\t[intime(Date.now()), 'auto'],\n\t\t] as Save;\n\t};\n\n\tconst createStack = (current: Save, stack = [current]) => {\n\t\treturn {\n\t\t\tget value() {\n\t\t\t\treturn stack.at(-1)!;\n\t\t\t},\n\t\t\tset value(value: Save) {\n\t\t\t\tstack[stack.length - 1] = value;\n\t\t\t},\n\t\t\tback() {\n\t\t\t\tif (stack.length > 1) stack.pop(), (goingBack = true);\n\t\t\t},\n\t\t\tpush(value: Save) {\n\t\t\t\tstack.push(value);\n\t\t\t},\n\t\t\tclear() {\n\t\t\t\tstack = [getDefaultSave(klona(defaultState))];\n\t\t\t},\n\t\t};\n\t};\n\n\tconst getLanguageWithoutParameters = () => {\n\t\treturn getLanguage(languages, defaultGetLanguage);\n\t}\n\n\t/**\n\t * 1) Novely rendered using the `initialData`, but you can't start new game or `load` an empty one - this is scary, imagine losing your progress\n\t * 2) Actual stored data is loaded, language and etc is changed\n\t */\n\tconst initialData: StorageData = {\n\t\tsaves: [],\n\t\tdata: klona(defaultData) as Data,\n\t\tmeta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED],\n\t};\n\n\tconst $ = store(initialData);\n\n\tlet initialDataLoaded = false;\n\n\tconst onStorageDataChange = (value: StorageData) => {\n\t\tif (initialDataLoaded) storage.set(value);\n\t};\n\n\tconst throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);\n\n\t$.subscribe(throttledOnStorageDataChange);\n\n\tconst getStoredData = () => {\n\t\tstorage.get().then((stored) => {\n\t\t\t/**\n\t\t\t * Migration is done only once (when game loads it's data), and then it saves the updated format\n\t\t\t */\n\t\t\tfor (const migration of migrations) {\n\t\t\t\t// @ts-expect-error Types does not match between versions\n\t\t\t\tstored = migration(stored);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Default `localStorageStorage` returns empty array and engine set this up itself\n\t\t\t */\n\t\t\tstored.meta[1] ||= DEFAULT_TYPEWRITER_SPEED;\n\n\t\t\t/**\n\t\t\t * When we need to override it we do that, when not – only when language was not defined already\n\t\t\t */\n\t\t\tif (overrideLanguage) {\n\t\t\t\tstored.meta[0] = getLanguageWithoutParameters();\n\t\t\t} else {\n\t\t\t\tstored.meta[0] ||= getLanguageWithoutParameters();\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * When data is empty replace it with `defaultData`\n\t\t\t * It also might be empty (default to empty)\n\t\t\t */\n\t\t\tif (isEmpty(stored.data)) {\n\t\t\t\tstored.data = defaultData as Data;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Now the next store updates will entail saving via storage.set\n\t\t\t */\n\t\t\tinitialDataLoaded = true;\n\n\t\t\t$.update(() => stored);\n\n\t\t\t/**\n\t\t\t * When initialScreen is game, then we will load it, but after the data is loaded and when assets are loaded if that is needed\n\t\t\t */\n\t\t\tif (initialScreen === 'game') assetsLoaded.promise.then(() => {\n\t\t\t\trestore();\n\t\t\t});\n\t\t});\n\t};\n\n\t/**\n\t * By default this is resolved immediately, but also can be delayed.\n\t * I.e. storage has not loaded yet\n\t */\n\tstorageDelay.then(getStoredData);\n\n\tconst initial = getDefaultSave(klona(defaultState));\n\tconst stack = createStack(initial);\n\n\tconst save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n\t\tif (!initialDataLoaded) return;\n\n\t\t/**\n\t\t * When autosaves diabled just return\n\t\t */\n\t\tif (!autosaves && type === 'auto') return;\n\n\t\tconst current = klona(stack.value);\n\n\t\t$.update((prev) => {\n\t\t\t/**\n\t\t\t * Find latest save that were created in current session, and check if it is latest in an array\n\t\t\t *\n\t\t\t * We check if save was created in current session and it is latest in array\n\t\t\t * When it is not then replacing it will break logical chain\n\t\t\t *\n\t\t\t * [auto save 1]\n\t\t\t * [manual save 1]\n\t\t\t * [auto save 2] <- should not replace first auto save\n\t\t\t */\n\t\t\tconst isLatest = findLastIndex(prev.saves, (value) => times.has(value[2][0])) === prev.saves.length - 1;\n\n\t\t\t/**\n\t\t\t * Update type and time information\n\t\t\t */\n\t\t\tcurrent[2][0] = intime(Date.now());\n\t\t\tcurrent[2][1] = type;\n\n\t\t\tif (!override || !isLatest) {\n\t\t\t\tprev.saves.push(current);\n\n\t\t\t\treturn prev;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Get latest\n\t\t\t */\n\t\t\tconst latest = prev.saves.at(-1);\n\n\t\t\t/**\n\t\t\t * When that save is the same type, replace it\n\t\t\t */\n\t\t\tif (latest && latest[2][1] === type) {\n\t\t\t\tprev.saves[prev.saves.length - 1] = current;\n\t\t\t} else {\n\t\t\t\tprev.saves.push(current);\n\t\t\t}\n\n\t\t\treturn prev;\n\t\t});\n\t};\n\n\tconst newGame = () => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tconst save = getDefaultSave(klona(defaultState));\n\n\t\t/**\n\t\t * Initial save is automatic, and should be ignored when autosaves is turned off\n\t\t */\n\t\tif (autosaves) {\n\t\t\t$.update((prev) => {\n\t\t\t\treturn prev.saves.push(save), prev;\n\t\t\t});\n\t\t}\n\n\t\trestore(save);\n\t};\n\n\t/**\n\t * Set's the save\n\t */\n\tconst set = (save: Save) => {\n\t\tstack.value = save;\n\n\t\treturn restore(save);\n\t};\n\n\tlet restoring = false;\n\tlet goingBack = false;\n\tlet interacted = 0;\n\n\t/**\n\t * Restore\n\t */\n\tconst restore = async (save?: Save) => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tlet latest = save || $.get().saves.at(-1);\n\n\t\t/**\n\t\t * When there is no game, then make a new game\n\t\t */\n\t\tif (!latest) {\n\t\t\t$.update(() => ({\n\t\t\t\tsaves: [initial],\n\t\t\t\tdata: klona(defaultData) as Data,\n\t\t\t\tmeta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED],\n\t\t\t}));\n\n\t\t\tlatest = klona(initial);\n\t\t}\n\n\t\t(restoring = true), (stack.value = latest);\n\n\t\t/**\n\t\t * Текущий элемент в истории\n\t\t */\n\t\tlet current: any = story;\n\t\t/**\n\t\t * Текущий элемент `[null, int]`\n\t\t */\n\t\tlet index = 0;\n\n\t\t/**\n\t\t * Число элементов `[null, int]`\n\t\t */\n\t\tconst max = stack.value[0].reduce((acc, [type, val]) => {\n\t\t\tif (isNull(type) && isNumber(val)) return acc + 1;\n\n\t\t\treturn acc;\n\t\t}, 0);\n\n\t\tconst queue = [] as [any, any][];\n\t\tconst keep = new Set();\n\t\tconst characters = new Set();\n\n\t\tfor (const [type, val] of stack.value[0]) {\n\t\t\tif (type === null) {\n\t\t\t\tif (isString(val)) {\n\t\t\t\t\tcurrent = current[val];\n\t\t\t\t} else if (isNumber(val)) {\n\t\t\t\t\tindex++;\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n\t\t\t\t\t * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n\t\t\t\t\t */\n\t\t\t\t\tfor (let i = 0; i <= val; i++) {\n\t\t\t\t\t\tconst [action, ...meta] = current[i];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Add item to queue and action to keep\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst push = () => {\n\t\t\t\t\t\t\tkeep.add(action);\n\t\t\t\t\t\t\tqueue.push([action, meta]);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Do not remove characters that will be here anyways\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (action === 'showCharacter') characters.add(meta[0]);\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n\t\t\t\t\t\t * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n\t\t\t\t\t\t\tif (index === max && i === val) {\n\t\t\t\t\t\t\t\tpush();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpush();\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrent = current[val];\n\t\t\t\t}\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tcurrent = current[(val as number) + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tcurrent = current[2][val];\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Run these exactly before the main loop.\n\t\t */\n\t\trenderer.ui.showScreen('game');\n\t\t/**\n\t\t * Provide the `keep` in there\n\t\t */\n\t\tmatch('clear', [keep, characters]);\n\n\t\t/**\n\t\t * Get the next actions array.\n\t\t */\n\t\tconst next = (i: number) => queue.slice(i + 1);\n\n\t\tfor await (const [i, [action, meta]] of queue.entries()) {\n\t\t\tif (action === 'function' || action === 'custom') {\n\t\t\t\t/**\n\t\t\t\t * When `callOnlyLatest` is `true`\n\t\t\t\t */\n\t\t\t\tif (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n\t\t\t\t\t/**\n\t\t\t\t\t * We'll calculate it is `latest` or not\n\t\t\t\t\t */\n\t\t\t\t\tconst notLatest = next(i).some(([, _meta]) => {\n\t\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\t\tconst c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\t\t\t\t\t\tconst c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Also check for `undefined`\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Equal by id or equal by `toString()`\n\t\t\t\t\t\t */\n\t\t\t\t\t\treturn isIdenticalID || str(c0) === str(c1);\n\t\t\t\t\t});\n\n\t\t\t\t\tif (notLatest) continue;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Action can return Promise.\n\t\t\t\t */\n\t\t\t\tconst result = match(action, meta);\n\n\t\t\t\t/**\n\t\t\t\t * Should wait until it resolved\n\t\t\t\t */\n\t\t\t\tif (isPromise(result)) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Await it!\n\t\t\t\t\t */\n\t\t\t\t\tawait result;\n\t\t\t\t}\n\t\t\t} else if (action === 'showCharacter') {\n\t\t\t\tconst skip = next(i).some(([_action, _meta]) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Проверка на возможный `undefined`\n\t\t\t\t\t */\n\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Будет ли персонаж скрыт в будущем\n\t\t\t\t\t * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n\t\t\t\t\t */\n\t\t\t\t\tconst hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n\t\t\t\t\t/**\n\t\t\t\t\t * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n\t\t\t\t\t * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n\t\t\t\t\t */\n\t\t\t\t\tconst notLatest = _action === action && _meta[0] === meta[0];\n\n\t\t\t\t\treturn hidden || notLatest;\n\t\t\t\t});\n\n\t\t\t\tif (skip) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else if (action === 'showBackground' || action === 'animateCharacter') {\n\t\t\t\t/**\n\t\t\t\t * Такая же оптимизация применяется к фонам и анимированию персонажей.\n\t\t\t\t * Если фон изменится, то нет смысла устанавливать текущий\n\t\t\t\t */\n\t\t\t\tconst notLatest = next(i).some(([_action]) => action === _action);\n\n\t\t\t\tif (notLatest) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else {\n\t\t\t\tmatch(action, meta);\n\t\t\t}\n\t\t}\n\n\t\t(restoring = goingBack = false), render();\n\t};\n\n\tconst refer = () => {\n\t\tlet current: any = story;\n\n\t\tfor (const [type, val] of stack.value[0]) {\n\t\t\tif (type === null) {\n\t\t\t\tcurrent = current[val];\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tcurrent = current[(val as number) + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tcurrent = current[2][val];\n\t\t\t}\n\t\t}\n\n\t\treturn current;\n\t};\n\n\t/**\n\t * @param force Force exit\n\t */\n\tconst exit = (force = false) => {\n\t\tif (interacted > 1 && !force && askBeforeExit) {\n\t\t\trenderer.ui.showExitPrompt();\n\t\t\treturn;\n\t\t}\n\n\t\tconst current = stack.value;\n\n\t\tstack.clear();\n\t\trenderer.ui.showScreen('mainmenu');\n\n\t\t/**\n\t\t * First two save elements and it's type\n\t\t */\n\t\tconst [time, type] = current[2];\n\n\t\t/**\n\t\t * This is auto save and belongs to the current session\n\t\t * Player did not interacted or did it once, so this is probably not-needed save\n\t\t */\n\t\tif (type === 'auto' && interacted <= 1 && times.has(time)) {\n\t\t\t$.update((prev) => {\n\t\t\t\tprev.saves = prev.saves.filter((save) => save !== current);\n\n\t\t\t\treturn prev;\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Reset interactive value\n\t\t */\n\t\tinteractivity(false);\n\t\t/**\n\t\t * Reset session times\n\t\t */\n\t\ttimes.clear();\n\t};\n\n\tconst back = () => {\n\t\treturn stack.back(), restore(stack.value);\n\t};\n\n\tconst renderer = createRenderer({\n\t\tcharacters,\n\t\tset,\n\t\trestore,\n\t\tsave,\n\t\tnewGame,\n\t\texit,\n\t\tback,\n\t\tstack,\n\t\tlanguages,\n\t\tt: t9n.i,\n\t\t$,\n\t});\n\n\tconst match = matchAction({\n\t\twait([time]) {\n\t\t\tif (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n\t\t},\n\t\tshowBackground([background]) {\n\t\t\trenderer.background(background);\n\t\t\tpush();\n\t\t},\n\t\tplayMusic([source]) {\n\t\t\trenderer.music(source, 'music').play();\n\t\t\tpush();\n\t\t},\n\t\tstopMusic([source]) {\n\t\t\trenderer.music(source, 'music').stop();\n\t\t\tpush();\n\t\t},\n\t\tshowCharacter([character, emotion, className, style]) {\n\t\t\tconst handle = renderer.character(character);\n\n\t\t\thandle.append(className, style, restoring);\n\t\t\thandle.withEmotion(emotion)();\n\n\t\t\tpush();\n\t\t},\n\t\thideCharacter([character, className, style, duration]) {\n\t\t\trenderer.character(character).remove(className, style, duration)(push, restoring);\n\t\t},\n\t\tdialog([character, content, emotion]) {\n\t\t\t/**\n\t\t\t * Person name\n\t\t\t */\n\t\t\tconst name = (() => {\n\t\t\t\tconst c = character;\n\t\t\t\tconst cs = characters;\n\t\t\t\tconst lang = $.get().meta[0];\n\n\t\t\t\tif (c && c in cs) {\n\t\t\t\t\tconst block = cs[c].name;\n\n\t\t\t\t\tif (typeof block === 'string') {\n\t\t\t\t\t\treturn block;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (lang in block) {\n\t\t\t\t\t\treturn block[lang as Languages]\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn c || '';\n\t\t\t})();\n\n\t\t\tconst run = renderer.dialog(unwrap(content), unwrap(name), character, emotion);\n\n\t\t\trun(forward, goingBack);\n\t\t},\n\t\tfunction([fn]) {\n\t\t\tconst result = fn(restoring, goingBack);\n\n\t\t\tif (!restoring) result ? result.then(push) : push();\n\n\t\t\treturn result;\n\t\t},\n\t\tchoice([question, ...choices]) {\n\t\t\tconst isWithoutQuestion = Array.isArray(question);\n\n\t\t\tif (isWithoutQuestion) {\n\t\t\t\t/**\n\t\t\t\t * Первый элемент может быть как строкой, так и элементов выбора\n\t\t\t\t */\n\t\t\t\tchoices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n\t\t\t\t/**\n\t\t\t\t * Значит, текст не требуется\n\t\t\t\t */\n\t\t\t\tquestion = '';\n\t\t\t}\n\n\t\t\tconst unwrapped = choices.map(([content, action, visible]) => {\n\t\t\t\treturn [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n\t\t\t});\n\n\t\t\tconst run = renderer.choices(\n\t\t\t\tunwrap(question),\n\t\t\t\tunwrapped,\n\t\t\t);\n\n\t\t\trun((selected) => {\n\t\t\t\tenmemory();\n\n\t\t\t\t/**\n\t\t\t\t * If there is a question, then `index` should be shifted by `1`\n\t\t\t\t */\n\t\t\t\tconst offset = isWithoutQuestion ? 0 : 1;\n\n\t\t\t\tstack.value[0].push(['choice', selected + offset], [null, 0]);\n\t\t\t\trender();\n\t\t\t\tinteractivity(true);\n\t\t\t});\n\t\t},\n\t\tjump([scene]) {\n\t\t\t/**\n\t\t\t * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n\t\t\t */\n\t\t\tstack.value[0] = [\n\t\t\t\t[null, scene],\n\t\t\t\t[null, -1],\n\t\t\t];\n\n\t\t\tmatch('clear', []);\n\t\t},\n\t\tclear([keep, characters]) {\n\t\t\t/**\n\t\t\t * Remove vibration\n\t\t\t */\n\t\t\tvibrate(0);\n\t\t\t/**\n\t\t\t * Call the actual `clear`\n\t\t\t */\n\t\t\trenderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n\t\t},\n\t\tcondition([condition]) {\n\t\t\tconst value = condition();\n\n\t\t\tif (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n\t\t},\n\t\tend() {\n\t\t\t/**\n\t\t\t * Clear the Scene\n\t\t\t */\n\t\t\tmatch('clear', []);\n\t\t\t/**\n\t\t\t * Go to the main menu\n\t\t\t */\n\t\t\trenderer.ui.showScreen('mainmenu');\n\t\t\t/**\n\t\t\t * Reset interactive value\n\t\t\t */\n\t\t\tinteractivity(false);\n\t\t\t/**\n\t\t\t * Reset session times\n\t\t\t */\n\t\t\ttimes.clear();\n\t\t},\n\t\tinput([question, onInput, setup]) {\n\t\t\trenderer.input(unwrap(question), onInput, setup)(forward);\n\t\t},\n\t\tcustom([handler]) {\n\t\t\tconst result = renderer.custom(handler, goingBack, () => {\n\t\t\t\tif (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n\t\t\t\tif (!restoring) push();\n\t\t\t});\n\n\t\t\treturn result;\n\t\t},\n\t\tvibrate(pattern) {\n\t\t\tvibrate(pattern);\n\t\t\tpush();\n\t\t},\n\t\tnext() {\n\t\t\tpush();\n\t\t},\n\t\tanimateCharacter([character, timeout, ...classes]) {\n\t\t\tconst handler: CustomHandler = (get) => {\n\t\t\t\tconst { clear } = get('@@internal-animate-character', false);\n\t\t\t\tconst char = renderer.store.characters[character];\n\n\t\t\t\t/**\n\t\t\t\t * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n\t\t\t\t */\n\t\t\t\tif (!char) return;\n\n\t\t\t\tconst target = char.canvas;\n\n\t\t\t\t/**\n\t\t\t\t * Character is not found\n\t\t\t\t */\n\t\t\t\tif (!target) return;\n\n\t\t\t\tconst classNames = classes.filter((className) => !target.classList.contains(className));\n\n\t\t\t\ttarget.classList.add(...classNames);\n\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\t\t\t\t}, timeout);\n\n\t\t\t\tclear(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Clear timeout, because when you will game re-runs some callback might remove classes from character\n\t\t\t\t\t */\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n\t\t\t */\n\t\t\tmatch('custom', [handler]);\n\t\t},\n\t\ttext(text) {\n\t\t\trenderer.text(text.map((content) => unwrap(content)).join(' '), forward, goingBack);\n\t\t},\n\t\texit() {\n\t\t\tconst path = stack.value[0];\n\n\t\t\tlet exited = false;\n\n\t\t\tfor (let i = path.length - 1; i > 0; i--) {\n\t\t\t\tif (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n\t\t\t\texited = true;\n\t\t\t\tstack.value[0] = path.slice(0, i);\n\t\t\t\tnext();\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Run render only when exit was performed. This prevents infinite loop of `render` -> `undefined` -> `exit` -> `render`.\n\t\t\t */\n\t\t\tif (exited) render();\n\t\t},\n\t\tpreload([source]) {\n\t\t\tif (!PRELOADED_ASSETS.has(source) && !goingBack && !restoring) {\n\t\t\t\t/**\n\t\t\t\t * Make image load\n\t\t\t\t */\n\t\t\t\tPRELOADED_ASSETS.add(document.createElement('img').src = source);\n\t\t\t}\n\n\t\t\tpush();\n\t\t}\n\t});\n\n\tconst enmemory = () => {\n\t\tif (restoring) return;\n\n\t\tconst current = klona(stack.value);\n\n\t\tcurrent[2][1] = 'auto';\n\n\t\tstack.push(current);\n\n\t\tsave(true, 'auto');\n\t};\n\n\tconst next = () => {\n\t\tconst path = stack.value[0];\n\n\t\t/**\n\t\t * Last path element\n\t\t */\n\t\tconst last = path.at(-1);\n\n\t\t/**\n\t\t * Almost impossible case\n\t\t */\n\t\tif (!last) return;\n\n\t\t/**\n\t\t * When matches `[null, int]` - increase `int`\n\t\t */\n\t\tif (isNull(last[0]) && isNumber(last[1])) {\n\t\t\tlast[1] = last[1] + 1;\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t * Else add new `[null, int]`\n\t\t */\n\t\tpath.push([null, 0]);\n\t};\n\n\tconst render = () => {\n\t\tconst referred = refer();\n\n\t\tif (Array.isArray(referred)) {\n\t\t\tconst [action, ...props] = referred;\n\n\t\t\tmatch(action, props);\n\t\t} else {\n\t\t\tmatch('exit', []);\n\t\t}\n\t};\n\n\tconst push = () => {\n\t\tif (!restoring) next(), render();\n\t};\n\n\tconst forward = () => {\n\t\tenmemory();\n\t\tpush();\n\t\tinteractivity(true);\n\t};\n\n\tconst interactivity = (value = false) => {\n\t\tinteracted = value ? (interacted + 1) : 0;\n\t};\n\n\t/**\n\t * Unwraps translatable content to string\n\t *\n\t * @example ```\n\t * unwrap(t('Hello'));\n\t * unwrap({ en: 'Hello', ru: 'Привет' });\n\t * unwrap({ en: () => data().ad_viewed ? 'Diamond Hat' : 'Diamond Hat (Watch Adv)' })\n\t * unwrap('Hello, {{name}}');\n\t * ```\n\t */\n\tconst unwrap = (content: Unwrappable, global = false) => {\n\t\tconst {\n\t\t\tdata,\n\t\t\tmeta: [lang],\n\t\t} = $.get();\n\n\t\tconst obj = global ? data : state();\n\t\tconst cnt = isFunction(content) ? content(lang, obj) : typeof content === 'string' ? content : content[lang];\n\n\t\tconst str = isFunction(cnt) ? cnt() : cnt;\n\n\t\treturn replaceT9N(str, obj);\n\t};\n\n\tfunction data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n\tfunction data(): DataScheme;\n\tfunction data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n\t\tif (!value) return $.get().data as DataScheme | void;\n\n\t\tconst prev = $.get().data;\n\t\tconst val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n\t\t$.update((prev) => {\n\t\t\tprev.data = val;\n\n\t\t\treturn prev;\n\t\t});\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Function to set story\n\t\t */\n\t\twithStory,\n\t\t/**\n\t\t * Function to get actions\n\t\t */\n\t\taction,\n\t\t/**\n\t\t * State that belongs to games\n\t\t */\n\t\tstate,\n\t\t/**\n\t\t * Unlike `state`, stored at global scope instead and shared between games\n\t\t */\n\t\tdata,\n\t\t/**\n\t\t * Unwraps translatable content to a string value\n\t\t */\n\t\tunwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n\t\t\treturn unwrap(content, true);\n\t\t},\n\t\t/**\n\t\t * Function that is used for translation\n\t\t */\n\t\tt: t9n.t as Inter['t'],\n\t};\n};\n\nexport { novely };\n","import type { TypewriterSpeed } from './types';\n\nconst SKIPPED_DURING_RESTORE = new Set(['dialog', 'choice', 'input', 'vibrate', 'text'] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nconst DEFAULT_TYPEWRITER_SPEED: TypewriterSpeed = 'Medium';\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET, DEFAULT_TYPEWRITER_SPEED };\n","import type { StorageData } from './types';\n\ninterface LocalStorageStorageSettings {\n\tkey: string;\n}\n\ninterface Storage {\n\tget: () => Promise<StorageData>;\n\tset: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n\treturn {\n\t\tasync get() {\n\t\t\tconst value = localStorage.getItem(options.key);\n\n\t\t\treturn value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n\t\t},\n\t\tasync set(data) {\n\t\t\tlocalStorage.setItem(options.key, JSON.stringify(data));\n\t\t},\n\t};\n};\n\nexport type { Storage };\nexport { localStorageStorage };\n"],"mappings":"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","names":["str","getLanguage","data","state","stack","save","characters","action","push","next","str","prev"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/utils.ts","../src/global.ts","../src/store.ts","../src/novely.ts","../src/storage.ts"],"sourcesContent":["import type { TypewriterSpeed } from './types';\n\nconst SKIPPED_DURING_RESTORE = new Set(['dialog', 'choice', 'input', 'vibrate', 'text'] as const);\n\nconst BLOCK_EXIT_STATEMENTS = new Set([\"choice:exit\", \"condition:exit\", \"block:exit\"]);\n\nconst BLOCK_STATEMENTS = new Set(['choice', 'condition', 'block']);\n\nconst EMPTY_SET = new Set<any>();\n\nconst DEFAULT_TYPEWRITER_SPEED: TypewriterSpeed = 'Medium';\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET, DEFAULT_TYPEWRITER_SPEED, BLOCK_EXIT_STATEMENTS, BLOCK_STATEMENTS };\n","import type { ActionProxyProvider, CustomHandler, ValidAction } from './action';\nimport type { Character } from './character';\nimport type { Thenable, Path, PathItem } from './types';\nimport { BLOCK_STATEMENTS, BLOCK_EXIT_STATEMENTS, SKIPPED_DURING_RESTORE } from './constants';\n\ntype MatchActionMap = {\n\t[Key in keyof ActionProxyProvider<Record<string, Character>>]: (\n\t\tdata: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>,\n\t) => void;\n};\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n\tcustom: (value: [handler: CustomHandler]) => Thenable<void>;\n};\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n\treturn (action: keyof MatchActionMap, props: any) => {\n\t\treturn values[action](props);\n\t};\n};\n\nconst isNumber = (val: unknown): val is number => {\n\treturn typeof val === 'number';\n};\n\nconst isNull = (val: unknown): val is null => {\n\treturn val === null;\n};\n\nconst isString = (val: unknown): val is string => {\n\treturn typeof val === 'string';\n};\n\nconst isFunction = (val: unknown): val is (...parameters: any[]) => any => {\n\treturn typeof val === 'function';\n};\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n\treturn Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then);\n};\n\nconst isEmpty = (val: unknown): val is Record<PropertyKey, never> => {\n\treturn typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n};\n\nconst isCSSImage = (str: string) => {\n\tconst startsWith = String.prototype.startsWith.bind(str);\n\n\treturn startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n};\n\nconst str = String;\n\nconst isUserRequiredAction = (\n\taction: keyof MatchActionMapComplete,\n\tmeta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>,\n) => {\n\treturn action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n};\n\nconst getLanguage = (languages: string[]) => {\n\tlet { language } = navigator;\n\n\tif (languages.includes(language)) {\n\t\treturn language;\n\t} else if (languages.includes((language = language.slice(0, 2)))) {\n\t\treturn language;\n\t} else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n\t\treturn language;\n\t}\n\n\t/**\n\t * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n\t */\n\treturn languages[0];\n};\n\n/**\n * @copyright Techlead LLC\n * @see https://learn.javascript.ru/task/throttle\n */\nconst throttle = <Fn extends (...args: any[]) => any>(fn: Fn, ms: number) => {\n\tlet throttled = false,\n\t\tsavedArgs: any,\n\t\tsavedThis: any;\n\n\tfunction wrapper(this: any, ...args: any[]) {\n\t\tif (throttled) {\n\t\t\tsavedArgs = args;\n\t\t\t/* eslint-disable @typescript-eslint/no-this-alias */\n\t\t\tsavedThis = this;\n\t\t\treturn;\n\t\t}\n\n\t\tfn.apply(this, args as unknown as any[]);\n\n\t\tthrottled = true;\n\n\t\tsetTimeout(function () {\n\t\t\tthrottled = false;\n\n\t\t\tif (savedArgs) {\n\t\t\t\twrapper.apply(savedThis, savedArgs);\n\t\t\t\tsavedArgs = savedThis = null;\n\t\t\t}\n\t\t}, ms);\n\t}\n\n\treturn wrapper as unknown as (...args: Parameters<Fn>) => void;\n};\n\nconst vibrate = (pattern: VibratePattern) => {\n\ttry {\n\t\tif ('vibrate' in navigator) {\n\t\t\tnavigator.vibrate(pattern);\n\t\t}\n\t} catch {}\n};\n\nconst findLastIndex = <T>(array: T[], fn: (item: T, next?: T) => boolean) => {\n\tfor (let i = array.length - 1; i >= 0; i--) {\n\t\tif (fn(array[i], array[i + 1])) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n};\n\nconst preloadImagesBlocking = (images: Set<string>) => {\n\treturn Promise.allSettled([...images].map(src => {\n\t\tconst img = document.createElement('img');\n\n\t\timg.src = src;\n\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\t/**\n\t\t\t * Image is already loaded\n\t\t\t */\n\t\t\tif (img.complete && img.naturalHeight !== 0) {\n\t\t\t\tresolve(void 0);\n\t\t\t}\n\n\t\t\timg.addEventListener('load', resolve);\n\t\t\timg.addEventListener('abort', reject);\n\t\t\timg.addEventListener('error', reject);\n\t\t});\n\t}));\n}\n\nconst createDeferredPromise = <T = void>() => {\n\tlet resolve!: (value: T | PromiseLike<T>) => void, reject!: (reason?: any) => void;\n\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res; reject = rej;\n\t});\n\n\treturn { resolve, reject, promise }\n}\n\nconst findLastPathItemBeforeItemOfType = (path: Path, name: PathItem[0]) => {\n\tconst index = findLastIndex(path, ([_name, _value], next) => {\n\t\treturn isNull(_name) && isNumber(_value) && next != null && next[0] === name;\n\t});\n\n\treturn path[index] as undefined | [\n\t\tnull,\n\t\tnumber\n\t];\n}\n\nconst isBlockStatement = (statement: unknown): statement is 'choice' | 'condition' | 'block' => {\n\treturn BLOCK_STATEMENTS.has(statement as any);\n}\n\nconst isBlockExitStatement = (statement: unknown): statement is \"choice:exit\" | \"condition:exit\" | \"block:exit\" => {\n\treturn BLOCK_EXIT_STATEMENTS.has(statement as any);\n}\n\nconst isSkippedDurigRestore = (item: unknown): item is \"vibrate\" | \"dialog\" | \"input\" | \"choice\" | \"text\" => {\n\treturn SKIPPED_DURING_RESTORE.has(item as any);\n}\n\nconst noop = () => {}\n\nconst isAction = (element: unknown): element is [keyof MatchActionMapComplete, ...Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>] => {\n\treturn Array.isArray(element) && isString(element[0]);\n}\n\nexport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n\tpreloadImagesBlocking,\n\tcreateDeferredPromise,\n\tfindLastPathItemBeforeItemOfType,\n\tisBlockStatement,\n\tisBlockExitStatement,\n\tisSkippedDurigRestore,\n\tnoop,\n\tisAction\n};\n","const PRELOADED_ASSETS = new Set<string>();\n\nexport { PRELOADED_ASSETS }\n","type Stored<T> = {\n\tsubscribe: (cb: (value: T) => void) => () => void;\n\tupdate: (fn: (prev: T) => T) => void;\n\tget: () => T;\n};\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n\tconst subscribe = (cb: (value: T) => void) => {\n\t\tsubscribers.add(cb), cb(current);\n\n\t\treturn () => {\n\t\t\tsubscribers.delete(cb);\n\t\t};\n\t};\n\n\tconst push = (value: T) => {\n\t\tfor (const cb of subscribers) cb(value);\n\t};\n\n\tconst update = (fn: (prev: T) => T) => {\n\t\tpush((current = fn(current)));\n\t};\n\n\tconst get = () => {\n\t\treturn current;\n\t};\n\n\treturn { subscribe, update, get } as const;\n};\n\nexport { store };\nexport type { Stored };\n","import type { Character } from './character';\nimport type {\n\tActionProxyProvider,\n\tGetActionParameters,\n\tStory,\n\tValidAction,\n\tUnwrappable,\n\tCustomHandler,\n} from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration, ActionFN } from './types';\nimport type { Renderer, RendererInit } from './renderer';\nimport type { SetupT9N } from '@novely/t9n';\nimport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetLanguage as defaultGetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n\tpreloadImagesBlocking,\n\tcreateDeferredPromise,\n\tfindLastPathItemBeforeItemOfType,\n\tisBlockStatement,\n\tisBlockExitStatement,\n\tisSkippedDurigRestore,\n\tisAction\n} from './utils';\nimport { PRELOADED_ASSETS } from './global';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge';\nimport { klona } from 'klona/json';\nimport { EMPTY_SET, DEFAULT_TYPEWRITER_SPEED } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n> {\n\t/**\n\t * An array of languages supported by the game.\n\t */\n\tlanguages: Languages[];\n\t/**\n\t * An object containing the characters in the game.\n\t */\n\tcharacters: Characters;\n\t/**\n\t * An object that provides access to the game's storage system.\n\t */\n\tstorage: Storage;\n\t/**\n\t * Delay loading data until Promise is resolved\n\t */\n\tstorageDelay?: Promise<void>;\n\t/**\n\t * A function that returns a Renderer object used to display the game's content\n\t */\n\trenderer: (characters: RendererInit) => Renderer;\n\t/**\n\t * An optional property that specifies the initial screen to display when the game starts\n\t */\n\tinitialScreen?: NovelyScreen;\n\t/**\n\t * An object containing the translation functions used in the game\n\t */\n\tt9n: Inter;\n\t/**\n\t * Initial state value\n\t */\n\tstate?: StateScheme;\n\t/**\n\t * Initial data value\n\t */\n\tdata?: DataScheme;\n\t/**\n\t * Enable autosaves or disable\n\t * @default true\n\t */\n\tautosaves?: boolean;\n\t/**\n\t * Migration from old saves to newer\n\t */\n\tmigrations?: Migration[];\n\t/**\n\t * For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage\n\t * @default 799\n\t */\n\tthrottleTimeout?: number;\n\t/**\n\t * Custom language detector\n\t * @param languages Supported languages aka `languages: []` in the config\n\t * @example ```ts\n\t * novely({\n\t * \t\tgetLanguage(languages, original) {\n\t * \t\t\t\tif (!sdk) return original(languages);\n\t * \t\t\t\treturn sdk.environment.i18n.lang // i.e. custom language from some sdk\n\t * \t\t}\n\t * })\n\t * ```\n\t */\n\tgetLanguage?: (languages: string[], original: typeof defaultGetLanguage) => string;\n\t/**\n\t * Ignores saved language, and uses `getLanguage` to get it on every engine start\n\t * @default false\n\t */\n\toverrideLanguage?: boolean;\n\t/**\n\t * Show a prompt before exiting a game\n\t * @default true\n\t */\n\taskBeforeExit?: boolean;\n\t/**\n\t * @default \"lazy\"\n\t */\n\tpreloadAssets?: \"lazy\" | \"blocking\"\n}\n\nconst novely = <\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n>({\n\tcharacters,\n\tstorage,\n\tstorageDelay = Promise.resolve(),\n\trenderer: createRenderer,\n\tinitialScreen = 'mainmenu',\n\tt9n,\n\tlanguages,\n\tstate: defaultState,\n\tdata: defaultData,\n\tautosaves = true,\n\tmigrations = [],\n\tthrottleTimeout = 799,\n\tgetLanguage = defaultGetLanguage,\n\toverrideLanguage = false,\n\taskBeforeExit = true,\n\tpreloadAssets = \"lazy\"\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n\tlet story: Story;\n\n\tconst times = new Set<number>();\n\n\tconst ASSETS_TO_PRELOAD = new Set<string>();\n\tconst assetsLoaded = createDeferredPromise();\n\n\t/**\n\t * Prevent `undefined`\n\t */\n\tdefaultData ||= {} as DataScheme;\n\tdefaultState ||= {} as StateScheme;\n\n\t/**\n\t * Saves timestamps created in this session\n\t */\n\tconst intime = (value: number) => {\n\t\treturn times.add(value), value;\n\t};\n\n\tconst withStory = async (s: Story) => {\n\t\t/**\n\t\t * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n\t\t */\n\t\tstory = Object.fromEntries(\n\t\t\tObject.entries(s).map(([name, items]) => {\n\t\t\t\tconst flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n\t\t\t\t\treturn item.flatMap((data) => {\n\t\t\t\t\t\tconst type = data[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * This is not just an action like `['name', ...arguments]`, but an array of actions\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (Array.isArray(type)) return flat(data as ValidAction[]);\n\n\t\t\t\t\t\treturn [data as ValidAction];\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\treturn [name, flat(items)];\n\t\t\t}),\n\t\t);\n\n\t\tif (preloadAssets === 'blocking' && ASSETS_TO_PRELOAD.size > 0) {\n\t\t\trenderer.ui.showScreen('loading');\n\n\t\t\tawait preloadImagesBlocking(ASSETS_TO_PRELOAD);\n\t\t}\n\n\t\tASSETS_TO_PRELOAD.clear();\n\t\tassetsLoaded.resolve();\n\n\t\t/**\n\t\t * When `initialScreen` is not a game, we can safely show it\n\t\t */\n\t\tif (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n\t};\n\n\tconst action = new Proxy({} as ActionProxyProvider<Characters>, {\n\t\tget(_, prop) {\n\t\t\treturn (...props: Parameters<ActionFN>) => {\n\t\t\t\tif (preloadAssets === 'blocking') {\n\t\t\t\t\t/**\n\t\t\t\t\t * Load backgrounds\n\t\t\t\t\t */\n\t\t\t\t\tif (prop === 'showBackground' && typeof props[0] === 'string' && isCSSImage(props[0])) {\n\t\t\t\t\t\tASSETS_TO_PRELOAD.add(props[0]);\n\t\t\t\t\t}\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Load characters\n\t\t\t\t\t */\n\t\t\t\t\tif (prop === 'showCharacter' && typeof props[0] === 'string' && typeof props[1] === 'string') {\n\t\t\t\t\t\tconst images = characters[props[0]].emotions[props[1]];\n\n\t\t\t\t\t\tif (typeof images === 'string') {\n\t\t\t\t\t\t\tASSETS_TO_PRELOAD.add(images);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (const asset of [images.head, images.body.left, images.body.right]) {\n\t\t\t\t\t\t\t\tASSETS_TO_PRELOAD.add(asset);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [prop, ...props];\n\t\t\t};\n\t\t},\n\t});\n\n\tfunction state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n\tfunction state(): StateScheme;\n\tfunction state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n\t\tif (!value) return stack.value[1] as StateScheme | void;\n\n\t\tconst prev = stack.value[1];\n\t\tconst val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n\t\tstack.value[1] = val as StateScheme;\n\t}\n\n\tconst getDefaultSave = (state = {}) => {\n\t\treturn [\n\t\t\t[\n\t\t\t\t[null, 'start'],\n\t\t\t\t[null, 0],\n\t\t\t],\n\t\t\tstate,\n\t\t\t[intime(Date.now()), 'auto'],\n\t\t] as Save;\n\t};\n\n\tconst createStack = (current: Save, stack = [current]) => {\n\t\treturn {\n\t\t\tget value() {\n\t\t\t\treturn stack.at(-1)!;\n\t\t\t},\n\t\t\tset value(value: Save) {\n\t\t\t\tstack[stack.length - 1] = value;\n\t\t\t},\n\t\t\tback() {\n\t\t\t\tif (stack.length > 1) stack.pop(), (goingBack = true);\n\t\t\t},\n\t\t\tpush(value: Save) {\n\t\t\t\tstack.push(value);\n\t\t\t},\n\t\t\tclear() {\n\t\t\t\tstack = [getDefaultSave(klona(defaultState))];\n\t\t\t},\n\t\t};\n\t};\n\n\tconst getLanguageWithoutParameters = () => {\n\t\treturn getLanguage(languages, defaultGetLanguage);\n\t}\n\n\t/**\n\t * 1) Novely rendered using the `initialData`, but you can't start new game or `load` an empty one - this is scary, imagine losing your progress\n\t * 2) Actual stored data is loaded, language and etc is changed\n\t */\n\tconst initialData: StorageData = {\n\t\tsaves: [],\n\t\tdata: klona(defaultData) as Data,\n\t\tmeta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED],\n\t};\n\n\tconst $ = store(initialData);\n\n\tlet initialDataLoaded = false;\n\n\tconst onStorageDataChange = (value: StorageData) => {\n\t\tif (initialDataLoaded) storage.set(value);\n\t};\n\n\tconst throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);\n\n\t$.subscribe(throttledOnStorageDataChange);\n\n\tconst getStoredData = () => {\n\t\tstorage.get().then((stored) => {\n\t\t\t/**\n\t\t\t * Migration is done only once (when game loads it's data), and then it saves the updated format\n\t\t\t */\n\t\t\tfor (const migration of migrations) {\n\t\t\t\t// @ts-expect-error Types does not match between versions\n\t\t\t\tstored = migration(stored);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Default `localStorageStorage` returns empty array and engine set this up itself\n\t\t\t */\n\t\t\tstored.meta[1] ||= DEFAULT_TYPEWRITER_SPEED;\n\n\t\t\t/**\n\t\t\t * When we need to override it we do that, when not – only when language was not defined already\n\t\t\t */\n\t\t\tif (overrideLanguage) {\n\t\t\t\tstored.meta[0] = getLanguageWithoutParameters();\n\t\t\t} else {\n\t\t\t\tstored.meta[0] ||= getLanguageWithoutParameters();\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * When data is empty replace it with `defaultData`\n\t\t\t * It also might be empty (default to empty)\n\t\t\t */\n\t\t\tif (isEmpty(stored.data)) {\n\t\t\t\tstored.data = defaultData as Data;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Now the next store updates will entail saving via storage.set\n\t\t\t */\n\t\t\tinitialDataLoaded = true;\n\n\t\t\t$.update(() => stored);\n\n\t\t\t/**\n\t\t\t * When initialScreen is game, then we will load it, but after the data is loaded and when assets are loaded if that is needed\n\t\t\t */\n\t\t\tif (initialScreen === 'game') assetsLoaded.promise.then(() => {\n\t\t\t\trestore();\n\t\t\t});\n\t\t});\n\t};\n\n\t/**\n\t * By default this is resolved immediately, but also can be delayed.\n\t * I.e. storage has not loaded yet\n\t */\n\tstorageDelay.then(getStoredData);\n\n\tconst initial = getDefaultSave(klona(defaultState));\n\tconst stack = createStack(initial);\n\n\tconst save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n\t\tif (!initialDataLoaded) return;\n\n\t\t/**\n\t\t * When autosaves diabled just return\n\t\t */\n\t\tif (!autosaves && type === 'auto') return;\n\n\t\tconst current = klona(stack.value);\n\n\t\t$.update((prev) => {\n\t\t\t/**\n\t\t\t * Find latest save that were created in current session, and check if it is latest in an array\n\t\t\t *\n\t\t\t * We check if save was created in current session and it is latest in array\n\t\t\t * When it is not then replacing it will break logical chain\n\t\t\t *\n\t\t\t * [auto save 1]\n\t\t\t * [manual save 1]\n\t\t\t * [auto save 2] <- should not replace first auto save\n\t\t\t */\n\t\t\tconst isLatest = findLastIndex(prev.saves, (value) => times.has(value[2][0])) === prev.saves.length - 1;\n\n\t\t\t/**\n\t\t\t * Update type and time information\n\t\t\t */\n\t\t\tcurrent[2][0] = intime(Date.now());\n\t\t\tcurrent[2][1] = type;\n\n\t\t\tif (!override || !isLatest) {\n\t\t\t\tprev.saves.push(current);\n\n\t\t\t\treturn prev;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Get latest\n\t\t\t */\n\t\t\tconst latest = prev.saves.at(-1);\n\n\t\t\t/**\n\t\t\t * When that save is the same type, replace it\n\t\t\t */\n\t\t\tif (latest && latest[2][1] === type) {\n\t\t\t\tprev.saves[prev.saves.length - 1] = current;\n\t\t\t} else {\n\t\t\t\tprev.saves.push(current);\n\t\t\t}\n\n\t\t\treturn prev;\n\t\t});\n\t};\n\n\tconst newGame = () => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tconst save = getDefaultSave(klona(defaultState));\n\n\t\t/**\n\t\t * Initial save is automatic, and should be ignored when autosaves is turned off\n\t\t */\n\t\tif (autosaves) {\n\t\t\t$.update((prev) => {\n\t\t\t\treturn prev.saves.push(save), prev;\n\t\t\t});\n\t\t}\n\n\t\trestore(save);\n\t};\n\n\t/**\n\t * Set's the save\n\t */\n\tconst set = (save: Save) => {\n\t\tstack.value = save;\n\n\t\treturn restore(save);\n\t};\n\n\tlet restoring = false;\n\tlet goingBack = false;\n\tlet interacted = 0;\n\n\t/**\n\t * Restore\n\t */\n\tconst restore = async (save?: Save) => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tlet latest = save || $.get().saves.at(-1);\n\n\t\t/**\n\t\t * When there is no game, then make a new game\n\t\t */\n\t\tif (!latest) {\n\t\t\t$.update(() => ({\n\t\t\t\tsaves: [initial],\n\t\t\t\tdata: klona(defaultData) as Data,\n\t\t\t\tmeta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED],\n\t\t\t}));\n\n\t\t\tlatest = klona(initial);\n\t\t}\n\n\t\t(restoring = true), (stack.value = latest);\n\n\t\tconst path = stack.value[0];\n\n\t\t/**\n\t\t * Current item in the story\n\t\t */\n\t\tlet current: any = story;\n\t\t/**\n\t\t * Previous `current` value\n\t\t */\n\t\tlet precurrent: any;\n\t\t/**\n\t\t * Should we ignore some actions\n\t\t */\n\t\tlet ignoreNested = false;\n\n\t\t/**\n\t\t * Current item of type `[null, int]`\n\t\t */\n\t\tlet index = 0;\n\n\t\t/**\n\t\t * Cound of items of type `[null, int]`\n\t\t */\n\t\tconst max = stack.value[0].reduce((acc, [type, val]) => {\n\t\t\tif (isNull(type) && isNumber(val)) {\n\t\t\t\treturn acc + 1;\n\t\t\t}\n\n\t\t\treturn acc;\n\t\t}, 0);\n\n\t\tconst queue = [] as [any, any][];\n\t\tconst keep = new Set();\n\t\tconst characters = new Set();\n\t\tconst blocks = [];\n\n\t\tfor (const [type, val] of path) {\n\t\t\tif (type === null) {\n\t\t\t\tprecurrent = current;\n\n\t\t\t\tif (isNumber(val)) {\n\t\t\t\t\tindex++;\n\n\t\t\t\t\tlet startIndex = 0;\n\n\t\t\t\t\tif (ignoreNested) {\n\t\t\t\t\t\tconst prev = findLastPathItemBeforeItemOfType(path.slice(0, index), 'block');\n\n\t\t\t\t\t\tif (prev) {\n\t\t\t\t\t\t\tstartIndex = prev[1];\n\t\t\t\t\t\t\tignoreNested = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n\t\t\t\t\t * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n\t\t\t\t\t */\n\t\t\t\t\tfor (let i = startIndex; i <= val; i++) {\n\t\t\t\t\t\tconst item = current[i];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * In case of broken save at least not throw\n\t\t\t\t\t\t * But is should not happen\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (!isAction(item)) continue;\n\n\t\t\t\t\t\tconst [action, ...meta] = item;\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Add item to queue and action to keep\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst push = () => {\n\t\t\t\t\t\t\tkeep.add(action);\n\t\t\t\t\t\t\tqueue.push([action, meta]);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Do not remove characters that will be here anyways\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (action === 'showCharacter') characters.add(meta[0]);\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n\t\t\t\t\t\t * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (isSkippedDurigRestore(action) || isUserRequiredAction(action, meta)) {\n\t\t\t\t\t\t\tif (index === max && i === val) {\n\t\t\t\t\t\t\t\tpush();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpush();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcurrent = current[val];\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tblocks.push(precurrent = current);\n\t\t\t\tcurrent = current[val + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tblocks.push(precurrent = current);\n\t\t\t\tcurrent = current[2][val];\n\t\t\t} else if (type === 'block') {\n\t\t\t\tblocks.push(precurrent);\n\t\t\t\tcurrent = story[val]\n\t\t\t} else if (type === 'block:exit' || type === 'choice:exit' || type === 'condition:exit') {\n\t\t\t\tcurrent = blocks.pop();\n\t\t\t\tignoreNested = true;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Run these exactly before the main loop.\n\t\t */\n\t\trenderer.ui.showScreen('game');\n\t\t/**\n\t\t * Provide the `keep` in there\n\t\t */\n\t\tmatch('clear', [keep, characters]);\n\n\t\t/**\n\t\t * Get the next actions array.\n\t\t */\n\t\tconst next = (i: number) => queue.slice(i + 1);\n\n\t\tfor await (const [i, [action, meta]] of queue.entries()) {\n\t\t\tif (action === 'function' || action === 'custom') {\n\t\t\t\t/**\n\t\t\t\t * When `callOnlyLatest` is `true`\n\t\t\t\t */\n\t\t\t\tif (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n\t\t\t\t\t/**\n\t\t\t\t\t * We'll calculate it is `latest` or not\n\t\t\t\t\t */\n\t\t\t\t\tconst notLatest = next(i).some(([, _meta]) => {\n\t\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\t\tconst c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\t\t\t\t\t\tconst c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Also check for `undefined`\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n\t\t\t\t\t\tconst isIdenticalByReference = c0 === c1;\n\n\t\t\t\t\t\treturn isIdenticalID || isIdenticalByReference || (str(c0) === str(c1));\n\t\t\t\t\t});\n\n\t\t\t\t\tif (notLatest) continue;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Action can return Promise.\n\t\t\t\t */\n\t\t\t\tconst result = match(action, meta);\n\n\t\t\t\t/**\n\t\t\t\t * Should wait until it resolved\n\t\t\t\t */\n\t\t\t\tif (isPromise(result)) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Await it!\n\t\t\t\t\t */\n\t\t\t\t\tawait result;\n\t\t\t\t}\n\t\t\t} else if (action === 'showCharacter') {\n\t\t\t\tconst skip = next(i).some(([_action, _meta]) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Проверка на возможный `undefined`\n\t\t\t\t\t */\n\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Будет ли персонаж скрыт в будущем\n\t\t\t\t\t * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n\t\t\t\t\t */\n\t\t\t\t\tconst hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n\t\t\t\t\t/**\n\t\t\t\t\t * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n\t\t\t\t\t * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n\t\t\t\t\t */\n\t\t\t\t\tconst notLatest = _action === action && _meta[0] === meta[0];\n\n\t\t\t\t\treturn hidden || notLatest;\n\t\t\t\t});\n\n\t\t\t\tif (skip) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else if (action === 'showBackground' || action === 'animateCharacter') {\n\t\t\t\t/**\n\t\t\t\t * @todo: Также сравнивать персонажей в animateCharacter. Чтобы не просто последний запускался, а последний для персонажа.\n\t\t\t\t */\n\n\t\t\t\t/**\n\t\t\t\t * Такая же оптимизация применяется к фонам и анимированию персонажей.\n\t\t\t\t * Если фон изменится, то нет смысла устанавливать текущий\n\t\t\t\t */\n\t\t\t\tconst notLatest = next(i).some(([_action]) => action === _action);\n\n\t\t\t\tif (notLatest) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else {\n\t\t\t\tmatch(action, meta);\n\t\t\t}\n\t\t}\n\n\t\t(restoring = goingBack = false), render();\n\t};\n\n\tconst refer = (path = stack.value[0]) => {\n\t\tlet current: any = story;\n\t\tlet precurrent: any = story;\n\n\t\tconst blocks: any[] = [];\n\n\t\tfor (const [type, val] of path) {\n\t\t\tif (type === null) {\n\t\t\t\tprecurrent = current;\n\t\t\t\tcurrent = current[val];\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tblocks.push(precurrent = current);\n\t\t\t\tcurrent = current[val as number + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tblocks.push(precurrent = current);\n\t\t\t\tcurrent = current[2][val];\n\t\t\t} else if (type === 'block') {\n\t\t\t\tblocks.push(precurrent);\n\t\t\t\tcurrent = story[val];\n\t\t\t} else if (type === 'block:exit' || type === 'choice:exit' || type === 'condition:exit') {\n\t\t\t\tcurrent = blocks.pop()\n\t\t\t}\n\t\t}\n\n\t\treturn current;\n\t};\n\n\t/**\n\t * @param force Force exit\n\t */\n\tconst exit = (force = false) => {\n\t\tif (interacted > 1 && !force && askBeforeExit) {\n\t\t\trenderer.ui.showExitPrompt();\n\t\t\treturn;\n\t\t}\n\n\t\tconst current = stack.value;\n\n\t\tstack.clear();\n\t\trenderer.ui.showScreen('mainmenu');\n\n\t\t/**\n\t\t * First two save elements and it's type\n\t\t */\n\t\tconst [time, type] = current[2];\n\n\t\t/**\n\t\t * This is auto save and belongs to the current session\n\t\t * Player did not interacted or did it once, so this is probably not-needed save\n\t\t */\n\t\tif (type === 'auto' && interacted <= 1 && times.has(time)) {\n\t\t\t$.update((prev) => {\n\t\t\t\tprev.saves = prev.saves.filter((save) => save !== current);\n\n\t\t\t\treturn prev;\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Reset interactive value\n\t\t */\n\t\tinteractivity(false);\n\t\t/**\n\t\t * Reset session times\n\t\t */\n\t\ttimes.clear();\n\t};\n\n\tconst back = () => {\n\t\treturn stack.back(), restore(stack.value);\n\t};\n\n\tconst renderer = createRenderer({\n\t\tcharacters,\n\t\tset,\n\t\trestore,\n\t\tsave,\n\t\tnewGame,\n\t\texit,\n\t\tback,\n\t\tstack,\n\t\tlanguages,\n\t\tt: t9n.i,\n\t\t$,\n\t});\n\n\tconst match = matchAction({\n\t\twait([time]) {\n\t\t\tif (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n\t\t},\n\t\tshowBackground([background]) {\n\t\t\trenderer.background(background);\n\t\t\tpush();\n\t\t},\n\t\tplayMusic([source]) {\n\t\t\trenderer.music(source, 'music').play();\n\t\t\tpush();\n\t\t},\n\t\tstopMusic([source]) {\n\t\t\trenderer.music(source, 'music').stop();\n\t\t\tpush();\n\t\t},\n\t\tshowCharacter([character, emotion, className, style]) {\n\t\t\tconst handle = renderer.character(character);\n\n\t\t\thandle.append(className, style, restoring);\n\t\t\thandle.withEmotion(emotion)();\n\n\t\t\tpush();\n\t\t},\n\t\thideCharacter([character, className, style, duration]) {\n\t\t\trenderer.character(character).remove(className, style, duration)(push, restoring);\n\t\t},\n\t\tdialog([character, content, emotion]) {\n\t\t\t/**\n\t\t\t * Person name\n\t\t\t */\n\t\t\tconst name = (() => {\n\t\t\t\tconst c = character;\n\t\t\t\tconst cs = characters;\n\t\t\t\tconst lang = $.get().meta[0];\n\n\t\t\t\tif (c && c in cs) {\n\t\t\t\t\tconst block = cs[c].name;\n\n\t\t\t\t\tif (typeof block === 'string') {\n\t\t\t\t\t\treturn block;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (lang in block) {\n\t\t\t\t\t\treturn block[lang as Languages]\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn c || '';\n\t\t\t})();\n\n\t\t\tconst run = renderer.dialog(unwrap(content), unwrap(name), character, emotion);\n\n\t\t\trun(forward, goingBack);\n\t\t},\n\t\tfunction([fn]) {\n\t\t\tconst result = fn(restoring, goingBack);\n\n\t\t\tif (!restoring) result ? result.then(push) : push();\n\n\t\t\treturn result;\n\t\t},\n\t\tchoice([question, ...choices]) {\n\t\t\tconst isWithoutQuestion = Array.isArray(question);\n\n\t\t\tif (isWithoutQuestion) {\n\t\t\t\t/**\n\t\t\t\t * Первый элемент может быть как строкой, так и элементов выбора\n\t\t\t\t */\n\t\t\t\tchoices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n\t\t\t\t/**\n\t\t\t\t * Значит, текст не требуется\n\t\t\t\t */\n\t\t\t\tquestion = '';\n\t\t\t}\n\n\t\t\tconst unwrapped = choices.map(([content, action, visible]) => {\n\t\t\t\treturn [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n\t\t\t});\n\n\t\t\tconst run = renderer.choices(\n\t\t\t\tunwrap(question),\n\t\t\t\tunwrapped,\n\t\t\t);\n\n\t\t\trun((selected) => {\n\t\t\t\tenmemory();\n\n\t\t\t\t/**\n\t\t\t\t * If there is a question, then `index` should be shifted by `1`\n\t\t\t\t */\n\t\t\t\tconst offset = isWithoutQuestion ? 0 : 1;\n\n\t\t\t\tstack.value[0].push(['choice', selected + offset], [null, 0]);\n\t\t\t\trender();\n\t\t\t\tinteractivity(true);\n\t\t\t});\n\t\t},\n\t\tjump([scene]) {\n\t\t\t/**\n\t\t\t * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n\t\t\t */\n\t\t\tstack.value[0] = [\n\t\t\t\t[null, scene],\n\t\t\t\t[null, -1],\n\t\t\t];\n\n\t\t\tmatch('clear', []);\n\t\t},\n\t\tclear([keep, characters]) {\n\t\t\t/**\n\t\t\t * Remove vibration\n\t\t\t */\n\t\t\tvibrate(0);\n\t\t\t/**\n\t\t\t * Call the actual `clear`\n\t\t\t */\n\t\t\trenderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n\t\t},\n\t\tcondition([condition]) {\n\t\t\tif (!restoring) {\n\t\t\t\tstack.value[0].push(\n\t\t\t\t\t['condition', String(condition())],\n\t\t\t\t\t[null, 0]\n\t\t\t\t);\n\n\t\t\t\trender();\n\t\t\t}\n\t\t},\n\t\tend() {\n\t\t\t/**\n\t\t\t * Clear the Scene\n\t\t\t */\n\t\t\tmatch('clear', []);\n\t\t\t/**\n\t\t\t * Go to the main menu\n\t\t\t */\n\t\t\trenderer.ui.showScreen('mainmenu');\n\t\t\t/**\n\t\t\t * Reset interactive value\n\t\t\t */\n\t\t\tinteractivity(false);\n\t\t\t/**\n\t\t\t * Reset session times\n\t\t\t */\n\t\t\ttimes.clear();\n\t\t},\n\t\tinput([question, onInput, setup]) {\n\t\t\trenderer.input(unwrap(question), onInput, setup)(forward);\n\t\t},\n\t\tcustom([handler]) {\n\t\t\tconst result = renderer.custom(handler, goingBack, () => {\n\t\t\t\tif (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n\t\t\t\tif (!restoring) push();\n\t\t\t});\n\n\t\t\treturn result;\n\t\t},\n\t\tvibrate(pattern) {\n\t\t\tvibrate(pattern);\n\t\t\tpush();\n\t\t},\n\t\tnext() {\n\t\t\tpush();\n\t\t},\n\t\tanimateCharacter([character, timeout, ...classes]) {\n\t\t\tconst handler: CustomHandler = (get) => {\n\t\t\t\tconst { clear } = get('@@internal-animate-character', false);\n\t\t\t\tconst char = renderer.store.characters[character];\n\n\t\t\t\t/**\n\t\t\t\t * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n\t\t\t\t */\n\t\t\t\tif (!char) return;\n\n\t\t\t\tconst target = char.canvas;\n\n\t\t\t\t/**\n\t\t\t\t * Character is not found\n\t\t\t\t */\n\t\t\t\tif (!target) return;\n\n\t\t\t\tconst classNames = classes.filter((className) => !target.classList.contains(className));\n\n\t\t\t\ttarget.classList.add(...classNames);\n\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\t\t\t\t}, timeout);\n\n\t\t\t\tclear(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Clear timeout, because when you will game re-runs some callback might remove classes from character\n\t\t\t\t\t */\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n\t\t\t */\n\t\t\tmatch('custom', [handler]);\n\t\t},\n\t\ttext(text) {\n\t\t\trenderer.text(text.map((content) => unwrap(content)).join(' '), forward, goingBack);\n\t\t},\n\t\texit() {\n\t\t\tif (restoring) return;\n\n\t\t\tconst path = stack.value[0];\n\t\t\tconst last = path.at(-1);\n\t\t\tconst ignore: (\"choice:exit\" | \"condition:exit\" | \"block:exit\")[] = [];\n\n\t\t\t/**\n\t\t\t * - should be an array\n\t\t\t * - first element is action name\n\t\t\t */\n\t\t\tif (!isAction(refer(path))) {\n\t\t\t\tif (last && isNull(last[0]) && isNumber(last[1])) {\n\t\t\t\t\tlast[1]--;\n\t\t\t\t} else {\n\t\t\t\t\tpath.pop();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (let i = path.length - 1; i > 0; i--) {\n\t\t\t\tconst [name] = path[i];\n\n\t\t\t\t/**\n\t\t\t\t * Remember already exited paths\n\t\t\t\t */\n\t\t\t\tif (isBlockExitStatement(name)) {\n\t\t\t\t\tignore.push(name);\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Ignore everything that we do not need there\n\t\t\t\t */\n\t\t\t\tif (!isBlockStatement(name)) continue;\n\n\t\t\t\t/**\n\t\t\t\t * When we found an already exited path we remove it from the list\n\t\t\t\t */\n\t\t\t\tif (ignore.at(-1)?.startsWith(name)) {\n\t\t\t\t\tignore.pop();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Exit from the path\n\t\t\t\t */\n\t\t\t\tpath.push([`${name}:exit`]);\n\n\t\t\t\tconst prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);\n\n\t\t\t\t/**\n\t\t\t\t * When possible also go to the next action (or exit from one layer above)\n\t\t\t\t */\n\t\t\t\tif (prev) path.push([null, prev[1] + 1]);\n\n\t\t\t\t/**\n\t\t\t\t * If we added an `[null, int]` but it points not to action, then\n\t\t\t\t *\n\t\t\t\t * - remove that item\n\t\t\t\t * - close another block\n\t\t\t\t */\n\t\t\t\tif (!isAction(refer(path))) {\n\t\t\t\t\tpath.pop();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\trender();\n\t\t},\n\t\tpreload([source]) {\n\t\t\tif (!PRELOADED_ASSETS.has(source) && !goingBack && !restoring) {\n\t\t\t\t/**\n\t\t\t\t * Make image load\n\t\t\t\t */\n\t\t\t\tPRELOADED_ASSETS.add(document.createElement('img').src = source);\n\t\t\t}\n\n\t\t\tpush();\n\t\t},\n\t\tblock([scene]) {\n\t\t\tif (!restoring) {\n\t\t\t\tstack.value[0].push(\n\t\t\t\t\t['block', scene],\n\t\t\t\t\t[null, 0]\n\t\t\t\t);\n\n\t\t\t\trender();\n\t\t\t}\n\t\t},\n\t});\n\n\tconst enmemory = () => {\n\t\tif (restoring) return;\n\n\t\tconst current = klona(stack.value);\n\n\t\tcurrent[2][1] = 'auto';\n\n\t\tstack.push(current);\n\n\t\tsave(true, 'auto');\n\t};\n\n\tconst next = () => {\n\t\tconst path = stack.value[0];\n\n\t\t/**\n\t\t * Last path element\n\t\t */\n\t\tconst last = path.at(-1);\n\n\t\tif (last && isNull(last[0]) && isNumber(last[1])) {\n\t\t\tlast[1]++;\n\t\t} else {\n\t\t\tpath.push([null, 0])\n\t\t}\n\t};\n\n\tconst render = () => {\n\t\tconst referred = refer();\n\n\t\tif (Array.isArray(referred)) {\n\t\t\tconst [action, ...props] = referred;\n\n\t\t\tmatch(action, props);\n\t\t} else {\n\t\t\tmatch('exit', []);\n\t\t}\n\t};\n\n\tconst push = () => {\n\t\tif (!restoring) next(), render();\n\t};\n\n\tconst forward = () => {\n\t\tenmemory();\n\t\tpush();\n\t\tinteractivity(true);\n\t};\n\n\tconst interactivity = (value = false) => {\n\t\tinteracted = value ? (interacted + 1) : 0;\n\t};\n\n\t/**\n\t * Unwraps translatable content to string\n\t *\n\t * @example ```\n\t * unwrap(t('Hello'));\n\t * unwrap({ en: 'Hello', ru: 'Привет' });\n\t * unwrap({ en: () => data().ad_viewed ? 'Diamond Hat' : 'Diamond Hat (Watch Adv)' })\n\t * unwrap('Hello, {{name}}');\n\t * ```\n\t */\n\tconst unwrap = (content: Unwrappable, global = false) => {\n\t\tconst {\n\t\t\tdata,\n\t\t\tmeta: [lang],\n\t\t} = $.get();\n\n\t\tconst obj = global ? data : state();\n\t\tconst cnt = isFunction(content) ? content(lang, obj) : typeof content === 'string' ? content : content[lang];\n\n\t\tconst str = isFunction(cnt) ? cnt() : cnt;\n\n\t\treturn replaceT9N(str, obj);\n\t};\n\n\tfunction data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n\tfunction data(): DataScheme;\n\tfunction data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n\t\tif (!value) return $.get().data as DataScheme | void;\n\n\t\tconst prev = $.get().data;\n\t\tconst val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n\t\t$.update((prev) => {\n\t\t\tprev.data = val;\n\n\t\t\treturn prev;\n\t\t});\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Function to set story\n\t\t */\n\t\twithStory,\n\t\t/**\n\t\t * Function to get actions\n\t\t */\n\t\taction,\n\t\t/**\n\t\t * State that belongs to games\n\t\t */\n\t\tstate,\n\t\t/**\n\t\t * Unlike `state`, stored at global scope instead and shared between games\n\t\t */\n\t\tdata,\n\t\t/**\n\t\t * Unwraps translatable content to a string value\n\t\t */\n\t\tunwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n\t\t\treturn unwrap(content, true);\n\t\t},\n\t\t/**\n\t\t * Function that is used for translation\n\t\t */\n\t\tt: t9n.t as Inter['t'],\n\t};\n};\n\nexport { novely };\n","import type { StorageData } from './types';\n\ninterface LocalStorageStorageSettings {\n\tkey: string;\n}\n\ninterface Storage {\n\tget: () => Promise<StorageData>;\n\tset: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n\treturn {\n\t\tasync get() {\n\t\t\tconst value = localStorage.getItem(options.key);\n\n\t\t\treturn value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n\t\t},\n\t\tasync set(data) {\n\t\t\tlocalStorage.setItem(options.key, JSON.stringify(data));\n\t\t},\n\t};\n};\n\nexport type { Storage };\nexport { localStorageStorage };\n"],"mappings":"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","names":["str","getLanguage","data","state","stack","save","characters","action","push","next","str","prev"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novely/core",
3
3
  "description": "Novely - powerful visual novel engine for creating interactive stories and games with branching narratives and rich multimedia content.",
4
- "version": "0.10.0",
4
+ "version": "0.11.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "publishConfig": {