@novely/core 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -45,13 +45,7 @@ type DeepPartial<T> = unknown extends T ? T : T extends object ? {
45
45
  [P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
46
46
  } : T;
47
47
 
48
- type ValidAction = ['choice', [number]] | ['clear', []] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: {
49
- input: HTMLInputElement;
50
- error: (error: string) => void;
51
- event: InputEvent & {
52
- currentTarget: HTMLInputElement;
53
- };
54
- }) => void, ((input: HTMLInputElement) => void)?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit'] | ValidAction[];
48
+ type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit'] | ValidAction[];
55
49
  type Story = Record<string, ValidAction[]>;
56
50
  type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string>;
57
51
  type FunctionableValue<T> = T | (() => T);
@@ -82,6 +76,7 @@ type CustomHandler = CustomHandlerFunction & {
82
76
  callOnlyLatest?: boolean;
83
77
  requireUserAction?: boolean;
84
78
  skipClearOnGoingBack?: boolean;
79
+ id?: string | symbol;
85
80
  };
86
81
  interface ActionInputOnInputMeta {
87
82
  /**
@@ -104,12 +99,13 @@ interface ActionInputOnInputMeta {
104
99
  */
105
100
  value: string;
106
101
  }
102
+ type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
107
103
  type ActionProxyProvider<Characters extends Record<string, Character>> = {
108
104
  choice: {
109
105
  (...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
110
106
  (question: Unwrappable, ...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
111
107
  };
112
- clear: () => ValidAction;
108
+ clear: (keep?: Set<keyof DefaultActionProxyProvider>, keepCharacters?: Set<string>) => ValidAction;
113
109
  condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
114
110
  exit: () => ValidAction;
115
111
  dialog: {
@@ -133,7 +129,7 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
133
129
  };
134
130
  wait: (time: FunctionableValue<number>) => ValidAction;
135
131
  function: (fn: (restoring: boolean, goingBack: boolean) => Thenable<void>) => ValidAction;
136
- input: (question: Unwrappable, onInput: (meta: ActionInputOnInputMeta) => void, setup?: (input: HTMLInputElement) => void) => ValidAction;
132
+ input: (question: Unwrappable, onInput: (meta: ActionInputOnInputMeta) => void, setup?: ActionInputSetup) => ValidAction;
137
133
  custom: (handler: CustomHandler) => ValidAction;
138
134
  vibrate: (...pattern: number[]) => ValidAction;
139
135
  next: () => ValidAction;
@@ -173,7 +169,7 @@ type Renderer = {
173
169
  choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[]) => (resolve: (selected: number) => void) => void;
174
170
  input: (question: string, onInput: Parameters<DefaultActionProxyProvider['input']>[1], setup?: Parameters<DefaultActionProxyProvider['input']>[2]) => (resolve: () => void) => void;
175
171
  music: (source: string, method: keyof RendererStore['audio']) => AudioHandle;
176
- clear: (goingBack: boolean) => (resolve: () => void) => void;
172
+ clear: (goingBack: boolean, keep: Set<keyof DefaultActionProxyProvider>, keepCharacters: Set<string>) => (resolve: () => void) => void;
177
173
  custom: (fn: Parameters<DefaultActionProxyProvider['custom']>[0], goingBack: boolean, push: () => void) => Thenable<void>;
178
174
  text: (str: string, resolve: () => void) => void;
179
175
  store: RendererStore;
@@ -261,16 +257,35 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
261
257
  migrations?: Migration[];
262
258
  }
263
259
  declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends _novely_t9n.T9N<Languages, string>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, t9n, languages, state: defaultState, data: defaultData, autosaves, migrations }: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {
260
+ /**
261
+ * Function to set story
262
+ */
264
263
  withStory: (s: Story) => void;
264
+ /**
265
+ * Function to get actions
266
+ */
265
267
  action: ActionProxyProvider<Characters>;
268
+ /**
269
+ * State that belongs to games
270
+ */
266
271
  state: {
267
272
  (value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;
268
273
  (): StateScheme;
269
274
  };
275
+ /**
276
+ * Unlike `state`, stored at global scope instead and shared between games
277
+ */
278
+ data: {
279
+ (value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;
280
+ (): DataScheme;
281
+ };
270
282
  /**
271
283
  * Unwraps translatable content to a string value
272
284
  */
273
285
  unwrap(content: string | ((lang: string, obj: Record<string, unknown>) => string) | Record<Languages, string>): string;
286
+ /**
287
+ * Function that is used for translation
288
+ */
274
289
  t: Inter["t"];
275
290
  };
276
291
 
@@ -159,6 +159,12 @@ var Novely = (() => {
159
159
  var isFunction = (val) => {
160
160
  return typeof val === "function";
161
161
  };
162
+ var isPromise = (val) => {
163
+ return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
164
+ };
165
+ var isEmpty = (val) => {
166
+ return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
167
+ };
162
168
  var str = (value) => {
163
169
  return String(value);
164
170
  };
@@ -274,28 +280,29 @@ var Novely = (() => {
274
280
  "vibrate",
275
281
  "text"
276
282
  ]);
283
+ var EMPTY_SET = /* @__PURE__ */ new Set();
277
284
 
278
285
  // ../t9n/dist/index.js
279
- var p = (t, i) => {
286
+ var p = (e, i) => {
280
287
  let r = [];
281
288
  for (let a of i) {
282
- if (!t)
289
+ if (!e)
283
290
  break;
284
- let [e, s] = t.split(a, 2);
285
- r.push(e), t = s;
291
+ let [t, s] = e.split(a, 2);
292
+ r.push(t), e = s;
286
293
  }
287
- return r.push(t), r;
294
+ return r.push(e), r;
288
295
  };
289
296
  var T = /{{(.*?)}}/g;
290
- var c = (t, i, r, a, e) => t.replace(T, (s, o, n) => {
297
+ var c = (e, i, r, a, t) => (Array.isArray(e) && (e = e.join("")), e.replace(T, (s, o, n) => {
291
298
  s = 0, n = i;
292
299
  let [d, g, l] = p(o.trim(), ["@", "%"]), u = d.split(".");
293
300
  for (; n && s < u.length; )
294
301
  n = n[u[s++]];
295
- g && r && n && e && (n = r[g][e.select(n)]);
302
+ g && r && n && t && (n = r[g][t.select(n)]);
296
303
  let S = a && l && a[l];
297
304
  return S && (n = S(n)), n ?? "";
298
- });
305
+ }));
299
306
 
300
307
  // src/novely.ts
301
308
  var novely = ({
@@ -313,17 +320,19 @@ var Novely = (() => {
313
320
  }) => {
314
321
  let story;
315
322
  let times = /* @__PURE__ */ new Set();
323
+ defaultData ||= {};
324
+ defaultState ||= {};
316
325
  const intime = (value) => {
317
326
  return times.add(value), value;
318
327
  };
319
328
  const withStory = (s) => {
320
329
  story = Object.fromEntries(Object.entries(s).map(([name, items]) => {
321
330
  const flat = (item) => {
322
- return item.flatMap((data) => {
323
- const type = data[0];
331
+ return item.flatMap((data2) => {
332
+ const type = data2[0];
324
333
  if (Array.isArray(type))
325
- return flat(data);
326
- return [data];
334
+ return flat(data2);
335
+ return [data2];
327
336
  });
328
337
  };
329
338
  return [name, flat(items)];
@@ -370,7 +379,7 @@ var Novely = (() => {
370
379
  };
371
380
  const initialData = {
372
381
  saves: [],
373
- data: {},
382
+ data: klona(defaultData),
374
383
  meta: [getLanguage(languages), getTypewriterSpeed()]
375
384
  };
376
385
  const $ = store(initialData);
@@ -388,6 +397,9 @@ var Novely = (() => {
388
397
  }
389
398
  stored.meta[0] ||= getLanguage(languages);
390
399
  stored.meta[1] ||= getTypewriterSpeed();
400
+ if (isEmpty(stored.data)) {
401
+ stored.data = defaultData;
402
+ }
391
403
  initialDataLoaded = true;
392
404
  $.update(() => stored);
393
405
  if (initialScreen === "game")
@@ -443,12 +455,10 @@ var Novely = (() => {
443
455
  return;
444
456
  let latest = save2 ? save2 : $.get().saves.at(-1);
445
457
  if (!latest) {
446
- $.update(() => ({ saves: [initial], data: {}, meta: [getLanguage(languages), getTypewriterSpeed()] }));
458
+ $.update(() => ({ saves: [initial], data: klona(defaultData), meta: [getLanguage(languages), getTypewriterSpeed()] }));
447
459
  latest = klona(initial);
448
460
  }
449
461
  restoring = true, stack.value = latest;
450
- renderer.ui.showScreen("game");
451
- match("clear", [goingBack]);
452
462
  let current = story;
453
463
  let index = 0;
454
464
  const max = stack.value[0].reduce((acc, [type, val]) => {
@@ -457,22 +467,30 @@ var Novely = (() => {
457
467
  return acc;
458
468
  }, 0);
459
469
  const queue = [];
470
+ const keep = /* @__PURE__ */ new Set();
471
+ const characters2 = /* @__PURE__ */ new Set();
460
472
  for (const [type, val] of stack.value[0]) {
461
473
  if (type === null) {
462
474
  if (isString(val)) {
463
475
  current = current[val];
464
476
  } else if (isNumber(val)) {
465
477
  index++;
466
- for (let i = 0; i < val; i++) {
478
+ for (let i = 0; i <= val; i++) {
467
479
  const [action2, ...meta] = current[i];
480
+ const push2 = () => {
481
+ keep.add(action2);
482
+ queue.push([action2, meta]);
483
+ };
484
+ if (action2 === "showCharacter")
485
+ characters2.add(meta[0]);
468
486
  if (SKIPPED_DURING_RESTORE.has(action2) || isUserRequiredAction(action2, meta)) {
469
487
  if (index === max && i === val) {
470
- queue.push([action2, meta]);
488
+ push2();
471
489
  } else {
472
490
  continue;
473
491
  }
474
492
  }
475
- queue.push([action2, meta]);
493
+ push2();
476
494
  }
477
495
  current = current[val];
478
496
  }
@@ -482,21 +500,33 @@ var Novely = (() => {
482
500
  current = current[2][val];
483
501
  }
484
502
  }
485
- const indexedQueue = queue.map((value, index2) => value.concat(index2));
503
+ queue.forEach((value, index2) => {
504
+ value.push(index2);
505
+ });
506
+ const indexedQueue = queue;
507
+ renderer.ui.showScreen("game");
508
+ match("clear", [keep, characters2]);
509
+ const next2 = (i) => indexedQueue.slice(i + 1);
486
510
  for await (const [action2, meta, i] of indexedQueue) {
487
511
  if (action2 === "function" || action2 === "custom") {
488
512
  if (action2 === "custom" && meta[0].callOnlyLatest) {
489
- const next2 = indexedQueue.slice(i + 1);
490
- const notLatest = next2.some(([_action, _meta]) => _meta && meta && str(_meta[0]) === str(meta[0]));
513
+ const notLatest = next2(i).some(([_action, _meta]) => {
514
+ if (!_meta || !meta)
515
+ return false;
516
+ const c0 = _meta[0];
517
+ const c1 = meta[0];
518
+ const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
519
+ return isIdenticalID || str(c0) === str(c1);
520
+ });
491
521
  if (notLatest)
492
522
  continue;
493
523
  }
494
524
  const result = match(action2, meta);
495
- if (result && "then" in result)
525
+ if (isPromise(result)) {
496
526
  await result;
527
+ }
497
528
  } else if (action2 === "showCharacter") {
498
- const next2 = indexedQueue.slice(i + 1);
499
- const skip = next2.some(([_action, _meta]) => {
529
+ const skip = next2(i).some(([_action, _meta]) => {
500
530
  if (!_meta || !meta)
501
531
  return false;
502
532
  const hidden = _action === "hideCharacter" && _meta[0] === meta[0];
@@ -506,9 +536,8 @@ var Novely = (() => {
506
536
  if (skip)
507
537
  continue;
508
538
  match(action2, meta);
509
- } else if (action2 === "showBackground") {
510
- const next2 = indexedQueue.slice(i + 1);
511
- const notLatest = next2.some(([_action]) => action2 === _action);
539
+ } else if (action2 === "showBackground" || action2 === "animateCharacter") {
540
+ const notLatest = next2(i).some(([_action]) => action2 === _action);
512
541
  if (notLatest)
513
542
  continue;
514
543
  match(action2, meta);
@@ -614,16 +643,19 @@ var Novely = (() => {
614
643
  });
615
644
  renderer.choices(unwrap(question), unwrapped)((selected) => {
616
645
  enmemory();
617
- stack.value[0].push(["choice", isWithoutQuestion ? selected : selected + 1], [null, 0]), render(), interactivity(true);
646
+ const offset = isWithoutQuestion ? 0 : 1;
647
+ stack.value[0].push(["choice", selected + offset], [null, 0]);
648
+ render();
649
+ interactivity(true);
618
650
  });
619
651
  },
620
652
  jump([scene]) {
621
653
  stack.value[0] = [[null, scene], [null, -1]];
622
654
  match("clear", []);
623
655
  },
624
- clear() {
656
+ clear([keep, characters2]) {
625
657
  vibrate(0);
626
- renderer.clear(goingBack)(push);
658
+ renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
627
659
  },
628
660
  condition([condition]) {
629
661
  const value = condition();
@@ -670,12 +702,11 @@ var Novely = (() => {
670
702
  target.classList.remove(...classNames);
671
703
  }, timeout);
672
704
  clear(() => {
705
+ target.classList.remove(...classNames);
673
706
  clearTimeout(timeoutId);
674
707
  });
675
708
  };
676
- handler.callOnlyLatest = true;
677
- return renderer.custom(handler, goingBack, () => {
678
- }), push();
709
+ match("custom", [handler]);
679
710
  },
680
711
  text(text) {
681
712
  renderer.text(text.map((content) => unwrap(content)).join(" "), forward);
@@ -729,21 +760,47 @@ var Novely = (() => {
729
760
  interacted = value;
730
761
  };
731
762
  const unwrap = (content, global = false) => {
732
- const { data, meta: [lang] } = $.get();
733
- const obj = global ? data : state();
763
+ const { data: data2, meta: [lang] } = $.get();
764
+ const obj = global ? data2 : state();
734
765
  const str2 = isFunction(content) ? content(lang, obj) : typeof content === "object" ? content[lang] : content;
735
766
  return c(str2, obj);
736
767
  };
768
+ function data(value) {
769
+ if (!value)
770
+ return $.get().data;
771
+ const prev = $.get().data;
772
+ const val = isFunction(value) ? value(prev) : (0, import_deepmerge.all)([prev, value]);
773
+ $.update((prev2) => {
774
+ prev2.data = val;
775
+ return prev2;
776
+ });
777
+ }
737
778
  return {
779
+ /**
780
+ * Function to set story
781
+ */
738
782
  withStory,
783
+ /**
784
+ * Function to get actions
785
+ */
739
786
  action,
787
+ /**
788
+ * State that belongs to games
789
+ */
740
790
  state,
791
+ /**
792
+ * Unlike `state`, stored at global scope instead and shared between games
793
+ */
794
+ data,
741
795
  /**
742
796
  * Unwraps translatable content to a string value
743
797
  */
744
798
  unwrap(content) {
745
799
  return unwrap(content, true);
746
800
  },
801
+ /**
802
+ * Function that is used for translation
803
+ */
747
804
  t: t9n.t
748
805
  };
749
806
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js","../src/index.ts","../src/utils.ts","../src/store.ts","../src/novely.ts","../../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/json/index.mjs","../src/constants.ts","../../t9n/src/lib.ts","../../t9n/src/translation.ts","../../t9n/src/translations.ts","../src/storage.ts"],"sourcesContent":["'use strict';\n\nvar isMergeableObject = function isMergeableObject(value) {\n\treturn isNonNullObject(value)\n\t\t&& !isSpecial(value)\n};\n\nfunction isNonNullObject(value) {\n\treturn !!value && typeof value === 'object'\n}\n\nfunction isSpecial(value) {\n\tvar stringValue = Object.prototype.toString.call(value);\n\n\treturn stringValue === '[object RegExp]'\n\t\t|| stringValue === '[object Date]'\n\t\t|| isReactElement(value)\n}\n\n// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25\nvar canUseSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;\n\nfunction isReactElement(value) {\n\treturn value.$$typeof === REACT_ELEMENT_TYPE\n}\n\nfunction emptyTarget(val) {\n\treturn Array.isArray(val) ? [] : {}\n}\n\nfunction cloneUnlessOtherwiseSpecified(value, options) {\n\treturn (options.clone !== false && options.isMergeableObject(value))\n\t\t? deepmerge(emptyTarget(value), value, options)\n\t\t: value\n}\n\nfunction defaultArrayMerge(target, source, options) {\n\treturn target.concat(source).map(function(element) {\n\t\treturn cloneUnlessOtherwiseSpecified(element, options)\n\t})\n}\n\nfunction getMergeFunction(key, options) {\n\tif (!options.customMerge) {\n\t\treturn deepmerge\n\t}\n\tvar customMerge = options.customMerge(key);\n\treturn typeof customMerge === 'function' ? customMerge : deepmerge\n}\n\nfunction getEnumerableOwnPropertySymbols(target) {\n\treturn Object.getOwnPropertySymbols\n\t\t? Object.getOwnPropertySymbols(target).filter(function(symbol) {\n\t\t\treturn Object.propertyIsEnumerable.call(target, symbol)\n\t\t})\n\t\t: []\n}\n\nfunction getKeys(target) {\n\treturn Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))\n}\n\nfunction propertyIsOnObject(object, property) {\n\ttry {\n\t\treturn property in object\n\t} catch(_) {\n\t\treturn false\n\t}\n}\n\n// Protects from prototype poisoning and unexpected merging up the prototype chain.\nfunction propertyIsUnsafe(target, key) {\n\treturn propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,\n\t\t&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,\n\t\t\t&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.\n}\n\nfunction mergeObject(target, source, options) {\n\tvar destination = {};\n\tif (options.isMergeableObject(target)) {\n\t\tgetKeys(target).forEach(function(key) {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(target[key], options);\n\t\t});\n\t}\n\tgetKeys(source).forEach(function(key) {\n\t\tif (propertyIsUnsafe(target, key)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {\n\t\t\tdestination[key] = getMergeFunction(key, options)(target[key], source[key], options);\n\t\t} else {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(source[key], options);\n\t\t}\n\t});\n\treturn destination\n}\n\nfunction deepmerge(target, source, options) {\n\toptions = options || {};\n\toptions.arrayMerge = options.arrayMerge || defaultArrayMerge;\n\toptions.isMergeableObject = options.isMergeableObject || isMergeableObject;\n\t// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()\n\t// implementations can use it. The caller may not replace it.\n\toptions.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;\n\n\tvar sourceIsArray = Array.isArray(source);\n\tvar targetIsArray = Array.isArray(target);\n\tvar sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;\n\n\tif (!sourceAndTargetTypesMatch) {\n\t\treturn cloneUnlessOtherwiseSpecified(source, options)\n\t} else if (sourceIsArray) {\n\t\treturn options.arrayMerge(target, source, options)\n\t} else {\n\t\treturn mergeObject(target, source, options)\n\t}\n}\n\ndeepmerge.all = function deepmergeAll(array, options) {\n\tif (!Array.isArray(array)) {\n\t\tthrow new Error('first argument should be an array')\n\t}\n\n\treturn array.reduce(function(prev, next) {\n\t\treturn deepmerge(prev, next, options)\n\t}, {})\n};\n\nvar deepmerge_1 = deepmerge;\n\nmodule.exports = deepmerge_1;\n","export type { ValidAction, Story, ActionProxyProvider, DefaultActionProxyProvider, GetActionParameters, Unwrappable, CustomHandler, CustomHandlerGetResult, CustomHandlerGetResultDataFunction, FunctionableValue } from './action'\nexport type { Emotions, Character } from './character'\nexport type { CharacterHandle, AudioHandle, RendererStore, Renderer, RendererInit } from './renderer'\nexport type { Storage } from './storage'\nexport type { Thenable, Path, StorageData, StorageMeta, TypewriterSpeed, Lang, NovelyScreen } from './types'\nexport type { Stored } from './store'\nexport type { BaseTranslationStrings } from '@novely/t9n';\n\nexport { novely } from './novely'\nexport { localStorageStorage } from './storage'","import type { ActionProxyProvider, CustomHandler } from './action'\nimport type { Character } from './character'\nimport type { TypewriterSpeed, Thenable } from './types'\n\ntype MatchActionMap = {\n [Key in keyof ActionProxyProvider<Record<string, Character>>]: (data: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>) => void;\n}\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n custom: (value: [handler: CustomHandler]) => Thenable<void>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n return (action: keyof MatchActionMap, props: any) => {\n return values[action](props);\n }\n}\n\nconst isNumber = (val: unknown): val is number => {\n return typeof val === 'number';\n}\n\nconst isNull = (val: unknown): val is null => {\n return val === null;\n}\n\nconst isString = (val: unknown): val is string => {\n return typeof val === 'string';\n}\n\nconst isFunction = (val: unknown): val is ((...parameters: any[]) => any) => {\n return typeof val === 'function';\n}\n\nconst isCSSImage = (str: string) => {\n const startsWith = String.prototype.startsWith.bind(str);\n\n return startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n}\n\nconst str = (value: unknown) => {\n return String(value);\n}\n\nconst isUserRequiredAction = (action: keyof MatchActionMapComplete, meta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>) => {\n return action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n}\n\nconst getTypewriterSpeed = (): TypewriterSpeed => {\n return 'Medium'\n}\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n if (languages.includes(language)) {\n return language;\n } else if (languages.includes((language = language.substring(0, 2)))) {\n return language;\n } else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n return language\n }\n\n /**\n * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n */\n return 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 let throttled = false, savedArgs: any, savedThis: any;\n\n function wrapper(this: any) {\n if (throttled) {\n savedArgs = arguments;\n savedThis = this;\n return;\n }\n\n fn.apply(this, arguments as unknown as any[]);\n\n throttled = true;\n\n setTimeout(function () {\n throttled = false;\n\n if (savedArgs) {\n wrapper.apply(savedThis, savedArgs);\n savedArgs = savedThis = null;\n }\n }, ms);\n }\n\n return wrapper as unknown as (...args: Parameters<Fn>) => void;\n}\n\nconst vibrate = (pattern: VibratePattern) => {\n try {\n if ('vibrate' in navigator) {\n navigator.vibrate(pattern);\n }\n } catch { }\n}\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n for (let i = array.length - 1; i > 0; i--) {\n if (fn(array[i])) {\n return i;\n }\n }\n\n return -1;\n}\n\nexport { matchAction, isNumber, isNull, isString, isCSSImage, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex }","type Stored<T> = {\n subscribe: (cb: (value: T) => void) => () => void;\n update: (fn: (prev: T) => T) => void;\n get: () => T;\n}\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n const subscribe = (cb: (value: T) => void) => {\n subscribers.add(cb), cb(current);\n\n return () => {\n subscribers.delete(cb);\n }\n };\n\n const push = (value: T) => {\n subscribers.forEach((cb) => cb(value))\n };\n\n const update = (fn: (prev: T) => T) => {\n push((current = fn(current)));\n };\n\n const get = () => {\n return current;\n };\n\n return { subscribe, update, get } as const;\n};\n\nexport { store }\nexport type { Stored }","import type { Character } from './character';\nimport type { ActionProxyProvider, GetActionParameters, Story, ValidAction, Unwrappable, CustomHandler } from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types'\nimport type { Renderer, RendererInit } from './renderer'\nimport type { SetupT9N } from '@novely/t9n'\nimport { matchAction, isNumber, isNull, isString, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex } from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge'\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends ReturnType<SetupT9N<Languages>>, StateScheme extends State, DataScheme extends Data> {\n /**\n * An array of languages supported by the game.\n */\n languages: Languages[];\n /**\n * An object containing the characters in the game.\n */\n characters: Characters;\n /**\n * An object that provides access to the game's storage system.\n */\n storage: Storage;\n /**\n * Delay loading data until Promise is resolved\n */\n storageDelay?: Promise<void>;\n /**\n * A function that returns a Renderer object used to display the game's content\n */\n renderer: (characters: RendererInit) => Renderer;\n /**\n * An optional property that specifies the initial screen to display when the game starts\n */\n initialScreen?: NovelyScreen;\n /**\n * An object containing the translation functions used in the game\n */\n t9n: Inter;\n /**\n * Initial state value\n */\n state?: StateScheme;\n /**\n * Initial data value\n */\n data?: DataScheme;\n /**\n * Enable autosaves or disable\n * @default true\n */\n autosaves?: boolean;\n /**\n * Migration from old saves to newer\n */\n migrations?: Migration[]\n}\n\nconst novely = <\n Languages extends string,\n Characters extends Record<string, Character<Languages>>,\n Inter extends ReturnType<SetupT9N<Languages>>,\n StateScheme extends State,\n DataScheme extends Data\n>({\n characters,\n storage,\n storageDelay = Promise.resolve(),\n renderer: createRenderer,\n initialScreen = \"mainmenu\",\n t9n,\n languages,\n state: defaultState,\n data: defaultData,\n autosaves = true,\n migrations = []\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n let story: Story;\n let times = new Set<number>();\n\n /**\n * Saves timestamps created in this session\n */\n const intime = (value: number) => {\n return times.add(value), value;\n }\n\n // @todo: find bug here\n const withStory = (s: Story) => {\n /**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\n story = Object.fromEntries(Object.entries(s).map(([name, items]) => {\n const flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n return item.flatMap((data) => {\n const type = data[0];\n\n /**\n * This is not just an action like `['name', ...arguments]`, but an array of actions\n */\n if (Array.isArray(type)) return flat(data as ValidAction[]);\n\n return [data as ValidAction];\n });\n };\n\n return [name, flat(items)];\n }));\n\n /**\n * When `initialScreen` is not a game, we can safely show it\n */\n if (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n }\n\n const action = new Proxy({} as ActionProxyProvider<Characters>, {\n get(_, prop) {\n return (...props: Parameters<ActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]>) => {\n return [prop, ...props];\n }\n }\n });\n\n function state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n function state(): StateScheme;\n function state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n if (!value) return stack.value[1] as StateScheme | void;\n\n const prev = stack.value[1];\n const val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n stack.value[1] = val as StateScheme;\n }\n\n const getDefaultSave = (state = {}) => {\n return [[[null, 'start'], [null, 0]], state, [intime(Date.now()), 'auto']] as Save;\n }\n\n const createStack = (current: Save, stack = [current]) => {\n return {\n get value() {\n return stack.at(-1)!;\n },\n set value(value: Save) {\n stack[stack.length - 1] = value;\n },\n back() {\n if (stack.length > 1) stack.pop(), goingBack = true;\n },\n push(value: Save) {\n stack.push(value);\n },\n clear() {\n stack = [getDefaultSave(klona(defaultState))];\n }\n }\n }\n\n /**\n * 1) Novely rendered using the `initialData`, you can still start new game or `load` an empty one - this is scary, imagine losing your progress\n * 2) Actual stored data is loaded, language and etc is changed \n */\n const initialData: StorageData = {\n saves: [],\n data: {},\n meta: [getLanguage(languages), getTypewriterSpeed()],\n };\n\n const $ = store(initialData);\n\n let initialDataLoaded = false;\n\n const onStorageDataChange = (value: StorageData) => {\n if (initialDataLoaded) storage.set(value);\n };\n\n const throttledOnStorageDataChange = throttle(onStorageDataChange, 120);\n\n $.subscribe(throttledOnStorageDataChange);\n\n const getStoredData = () => {\n storage.get().then(stored => {\n /**\n * Migration is done only once (when game loads it's data), and then it saves the updated format\n */\n for (const migration of migrations) {\n // @ts-expect-error Types does not match between versions\n stored = migration(stored);\n }\n\n /**\n * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n */\n stored.meta[0] ||= getLanguage(languages);\n stored.meta[1] ||= getTypewriterSpeed();\n\n /**\n * Now the next store updates will entail saving via storage.set\n */\n initialDataLoaded = true;\n\n $.update(() => stored);\n\n /**\n * When initialScreen is game, then we will load it, but after the data is loaded\n */\n if (initialScreen === 'game') restore();\n });\n }\n\n /**\n * By default this is resolved immediately, but also can be delayed.\n * I.e. storage has not loaded yet\n */\n storageDelay.then(getStoredData)\n\n const initial = getDefaultSave(klona(defaultState));\n const stack = createStack(initial);\n\n const save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n if (!initialDataLoaded) return;\n\n /**\n * When autosaves diabled just return\n */\n if (!autosaves && type === 'auto') return;\n\n const current = klona(stack.value);\n\n $.update(prev => {\n /**\n * Find latest save that were created in current session, and check if it is latest in an array\n * \n * We check if save was created in current session and it is latest in array\n * When it is not then replacing it will break logical chain\n * \n * [auto save 1]\n * [manual save 1]\n * [auto save 2] <- should not replace first auto save \n */\n const isLatest = findLastIndex(prev.saves, value => times.has(value[2][0])) === prev.saves.length - 1;\n\n /**\n * Update type and time information\n */\n current[2][0] = intime(Date.now());\n current[2][1] = type;\n\n if (!override || !isLatest) {\n prev.saves.push(current);\n\n return prev;\n }\n\n /**\n * Get latest\n */\n const latest = prev.saves.at(-1);\n\n /**\n * When that save is the same type, replace it\n */\n if (latest && latest[2][1] === type) {\n prev.saves[prev.saves.length - 1] = current;\n } else {\n prev.saves.push(current);\n }\n\n return prev;\n });\n }\n\n const newGame = () => {\n if (!initialDataLoaded) return;\n\n const save = getDefaultSave(klona(defaultState));\n\n /**\n * Initial save is automatic, and should be ignored when autosaves is turned off\n */\n if (autosaves) {\n $.update(prev => {\n return prev.saves.push(save), prev;\n });\n }\n\n restore(save);\n }\n\n /**\n * Set's the save\n */\n const set = (save: Save) => {\n stack.value = save;\n\n return restore(save);\n }\n\n let restoring = false;\n let goingBack = false;\n let interacted = false;\n\n /**\n * Restore\n */\n const restore = async (save?: Save) => {\n if (!initialDataLoaded) return;\n\n let latest = save ? save : $.get().saves.at(-1);\n\n /**\n * When there is no game, then make a new game\n */\n if (!latest) {\n $.update(() => ({ saves: [initial], data: {}, meta: [getLanguage(languages), getTypewriterSpeed()] }));\n\n latest = klona(initial);\n }\n\n restoring = true, stack.value = latest;\n\n renderer.ui.showScreen('game');\n match('clear', [goingBack]);\n\n /**\n * Текущий элемент в истории\n */\n let current: any = story;\n /**\n * Текущий элемент `[null, int]`\n */\n let index = 0;\n\n /**\n * Число элементов `[null, int]`\n */\n const max = stack.value[0].reduce((acc, [type, val]) => {\n if (isNull(type) && isNumber(val)) return acc + 1;\n\n return acc;\n }, 0);\n\n const queue = [] as [any, any][];\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n if (isString(val)) {\n current = current[val];\n } else if (isNumber(val)) {\n index++;\n\n /**\n * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n */\n for (let i = 0; i < val; i++) {\n const [action, ...meta] = current[i];\n\n /**\n * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n */\n if (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n if (index === max && i === val) {\n queue.push([action, meta]);\n } else {\n continue;\n }\n }\n\n queue.push([action, meta]);\n }\n\n current = current[val];\n }\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n const indexedQueue = queue.map((value, index) => value.concat(index) as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number]);\n\n for await (const [action, meta, i] of indexedQueue) {\n if (action === 'function' || action === 'custom') {\n /**\n * Если `callOnlyLatest` - `true`\n */\n if (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n /**\n * Вычислим `latest` или нет\n */\n const next = indexedQueue.slice(i + 1);\n const notLatest = next.some(([_action, _meta]) => _meta && meta && str(_meta[0]) === str(meta[0]));\n\n if (notLatest) continue;\n }\n\n /**\n * Action может возвращать Promise. Нужно подожать его `resolve`\n */\n const result = match(action, meta);\n\n /**\n * Дождёмся окончания\n */\n if (result && 'then' in result) await result;\n } else if (action === 'showCharacter') {\n const next = indexedQueue.slice(i + 1);\n const skip = next.some(([_action, _meta]) => {\n /**\n * Проверка на возможный `undefined`\n */\n if (!_meta || !meta) return false;\n\n /**\n * Будет ли персонаж скрыт в будущем\n * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n */\n const hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n /**\n * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n */\n const notLatest = _action === action && _meta[0] === meta[0];\n\n return hidden || notLatest;\n })\n\n if (skip) continue;\n\n match(action, meta);\n } else if (action === 'showBackground') {\n const next = indexedQueue.slice(i + 1);\n /**\n * Такая же оптимизация применяется к фонам.\n * Если фон изменится, то нет смысла устанавливать текущий\n */\n const notLatest = next.some(([_action]) => action === _action);\n\n if (notLatest) continue;\n\n match(action, meta);\n } else {\n match(action, meta);\n }\n }\n\n restoring = goingBack = false, render();\n }\n\n const refer = () => {\n let current: any = story;\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n current = current[val];\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n return current;\n }\n\n const exit = () => {\n const current = stack.value;\n\n stack.clear();\n renderer.ui.showScreen('mainmenu');\n\n /**\n * First two save elements and it's type\n */\n const [[first, second], , [time, type]] = current;\n\n if (type === 'auto' && first && second) {\n /**\n * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n */\n if (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n $.update((prev) => {\n prev.saves = prev.saves.filter(save => save !== current);\n\n return prev;\n })\n }\n }\n\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n }\n\n const back = () => {\n return stack.back(), restore(stack.value);\n }\n\n const renderer = createRenderer({\n characters,\n set,\n restore,\n save,\n newGame,\n exit,\n back,\n stack,\n languages,\n t: t9n.i,\n $\n });\n\n const match = matchAction({\n wait([time]) {\n /**\n * `restoring` может поменяться на `true` перед тем как запуститься `push` из `setTimeout`\n */\n if (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n },\n showBackground([background]) {\n renderer.background(background);\n push()\n },\n playMusic([source]) {\n renderer.music(source, 'music').play();\n push()\n },\n stopMusic([source]) {\n renderer.music(source, 'music').stop();\n push()\n },\n showCharacter([character, emotion, className, style]) {\n const handle = renderer.character(character);\n\n handle.append(className, style, restoring);\n handle.withEmotion(emotion)();\n\n push()\n },\n hideCharacter([character, className, style, duration]) {\n renderer.character(character).remove(className, style, duration)(push, restoring);\n },\n dialog([character, content, emotion]) {\n /**\n * Имя персонажа, с учетом выбранного языка\n */\n const name = (() => {\n const c = character, cs = characters;\n const lang = $.get().meta[0];\n\n return c ? c in cs ? typeof cs[c].name === 'string' ? cs[c].name as string : (cs[c].name as Record<string, string>)[lang] : c : '';\n })();\n\n renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n },\n function([fn]) {\n const result = fn(restoring, goingBack);\n\n if (!restoring) result ? result.then(push) : push();\n\n return result;\n },\n choice([question, ...choices]) {\n const isWithoutQuestion = Array.isArray(question);\n\n if (isWithoutQuestion) {\n /**\n * Первый элемент может быть как строкой, так и элементов выбора\n */\n choices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n /**\n * Значит, текст не требуется\n */\n question = '';\n }\n\n const unwrapped = choices.map(([content, action, visible]) => {\n return [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n });\n\n renderer.choices(unwrap(question), unwrapped)((selected) => {\n enmemory();\n\n /**\n * Если был вопрос, то `index` смещается на единицу назад, поэтому нужно добавить единицу\n */\n stack.value[0].push(['choice', isWithoutQuestion ? selected : selected + 1], [null, 0]), render(), interactivity(true);\n });\n },\n jump([scene]) {\n /**\n * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n */\n stack.value[0] = [[null, scene], [null, -1]];\n\n match('clear', []);\n },\n clear() {\n vibrate(0);\n renderer.clear(goingBack)(push);\n },\n condition([condition]) {\n const value = condition();\n\n if (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n },\n end() {\n /**\n * Clear the Scene\n */\n match('clear', []);\n /**\n * Go to the main menu\n */\n renderer.ui.showScreen('mainmenu');\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n },\n input([question, onInput, setup]) {\n renderer.input(unwrap(question), onInput, setup)(forward);\n },\n custom([handler]) {\n const result = renderer.custom(handler, goingBack, () => {\n if (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n if (!restoring) push();\n });\n\n return result;\n },\n vibrate(pattern) {\n vibrate(pattern);\n push()\n },\n next() {\n push();\n },\n animateCharacter([character, timeout, ...classes]) {\n const handler: CustomHandler = (get) => {\n const { clear } = get('@@internal-animate-character', false);\n const char = renderer.store.characters[character];\n\n /**\n * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n */\n if (!char) return;\n\n const target = char.canvas;\n\n /**\n * Character is not found\n */\n if (!target) return;\n\n const classNames = classes.filter(className => !target.classList.contains(className));\n\n target.classList.add(...classNames);\n\n const timeoutId = setTimeout(() => {\n target.classList.remove(...classNames);\n }, timeout);\n\n clear(() => {\n /**\n * Clear timeout, because when you will game re-runs some callback might remove classes from character\n */\n clearTimeout(timeoutId);\n });\n }\n\n handler.callOnlyLatest = true;\n\n return renderer.custom(handler, goingBack, () => { }), push();\n },\n text(text) {\n renderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n },\n exit() {\n const path = stack.value[0];\n\n for (let i = path.length - 1; i > 0; i--) {\n if (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n stack.value[0] = path.slice(0, i);\n next();\n\n break;\n }\n\n render();\n }\n });\n\n const enmemory = () => {\n if (restoring) return;\n\n const current = klona(stack.value);\n\n current[2][1] = 'auto';\n\n stack.push(current);\n\n save(true, 'auto');\n }\n\n const next = () => {\n const path = stack.value[0];\n /**\n * Последний элемент пути\n */\n const last = path[path.length - 1]!;\n\n /**\n * Если он вида `[null, int]` - увеличивает `int`\n */\n if (isNull(last[0]) && isNumber(last[1])) {\n last[1] = last[1] + 1;\n return;\n }\n\n /**\n * Иначе добавляет новое `[null int]`\n */\n path.push([null, 0]);\n }\n\n const render = () => {\n const referred = refer();\n\n if (!Array.isArray(referred)) return;\n\n const [action, ...props] = referred;\n\n match(action, props);\n }\n\n const push = () => {\n if (!restoring) next(), render();\n }\n\n const forward = () => {\n enmemory();\n push();\n interactivity(true)\n }\n\n const interactivity = (value = false) => {\n interacted = value;\n }\n\n /**\n * Unwraps translatable content to string\n * \n * @example ```\n * unwrap(t('Hello'));\n * unwrap({ en: 'Hello', ru: 'Привет' });\n * unwrap('Hello, {{name}}');\n * ```\n */\n const unwrap = (content: Unwrappable, global = false) => {\n const { data, meta: [lang] } = $.get();\n\n const obj = global ? data : state();\n const str = isFunction(content)\n ? content(lang, obj)\n : typeof content === 'object'\n ? content[lang]\n : content;\n \n return replaceT9N(str, obj);\n }\n\n return {\n withStory,\n action,\n state,\n /**\n * Unwraps translatable content to a string value\n */\n unwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n return unwrap(content, true);\n },\n t: t9n.t as Inter['t'],\n }\n}\n\nexport { novely }\n","export function klona(val) {\n\tvar k, out, tmp;\n\n\tif (Array.isArray(val)) {\n\t\tout = Array(k=val.length);\n\t\twhile (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\treturn out;\n\t}\n\n\tif (Object.prototype.toString.call(val) === '[object Object]') {\n\t\tout = {}; // null\n\t\tfor (k in val) {\n\t\t\tif (k === '__proto__') {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tvalue: klona(val[k]),\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tout[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\n\treturn val;\n}\n","const SKIPPED_DURING_RESTORE = new Set([\n 'dialog',\n 'choice',\n 'input',\n 'vibrate',\n 'text'\n] as const);\n\nexport { SKIPPED_DURING_RESTORE }","const split = (input: string, delimeters: string[]) => {\n const output: (string | undefined)[] = [];\n\n for (const delimeter of delimeters) {\n if (!input) break;\n\n const [start, end] = input.split(delimeter, 2);\n\n output.push(start); input = end;\n }\n\n output.push(input);\n\n return output;\n}\n\nexport { split }","import type { BaseTranslationStrings } from './translations';\nimport { split } from './lib';\n\ntype PluralType = Intl.LDMLPluralRule;\ntype FunctionalSetupT9N = <LanguageKey extends string, PluralKey extends string, StringKey extends string, Actions extends string>(parameters: { [Lang in LanguageKey]: { pluralization: { [Plural in PluralKey]: Partial<Record<PluralType, string>> }; internal: { [Key in BaseTranslationStrings]: string }; strings: { [Str in StringKey]: string }; actions?: { [Action in Actions]?: (value: string) => string; } } }) => T9N<LanguageKey, StringKey>\ntype SetupT9N<LanguageKey extends string> = <PluralKey extends string, StringKey extends string, Actions extends string>(parameters: { [Lang in LanguageKey]: { pluralization: { [Plural in PluralKey]: Partial<Record<PluralType, string>> }; internal: { [Key in BaseTranslationStrings]: string }; strings: { [Str in StringKey]: string }; actions?: { [Action in Actions]?: (value: string) => string; } } }) => T9N<LanguageKey, StringKey>\n\ntype T9N<LanguageKey extends string, StringKey extends string> = {\n t(key: StringKey | Record<LanguageKey, string>): (lang: LanguageKey | (string & {}), obj: Record<string, unknown>) => string;\n i(key: StringKey, lang: LanguageKey | (string & {})): string;\n}\n\nconst RGX = /{{(.*?)}}/g;\n\nconst replace = (str: string, obj: Record<string, unknown>, pluralization?: Record<string, Record<string, PluralType>>, actions?: Partial<Record<string, (str: string) => string>>, pr?: Intl.PluralRules) => {\n return str.replace(RGX, (x: any, key: string, y: any) => {\n x = 0;\n y = obj;\n\n const [pathstr, plural, action] = split(key.trim(), ['@', '%']);\n\n let path = pathstr!.split('.');\n\n while (y && x < path.length) y = y[path[x++]];\n\n if (plural && pluralization && y && pr) {\n y = pluralization[plural][pr.select(y)];\n }\n\n const actionHandler = actions && action && actions[action];\n\n if (actionHandler) y = actionHandler(y);\n\n return y != null ? y : '';\n });\n}\n\nconst createT9N: FunctionalSetupT9N = (parameters) => {\n let locale: string | undefined;\n let pr: Intl.PluralRules | undefined;\n\n return {\n t(key) {\n return (lang, obj) => {\n /**\n * At first run `locale` and `pr` are not defined.\n * When `locale` changes, `pr` should be updated`\n */\n if (!locale || !pr || lang != locale) {\n pr = new Intl.PluralRules(locale = lang);\n }\n\n // @ts-ignore\n const str: string = typeof key === 'object' ? key[lang] : parameters[lang]['strings'][key];\n\n if (!str) return '';\n\n // @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n return replace(str, obj, parameters[lang]['pluralization'], parameters[lang]['actions'], pr);\n }\n },\n i(key, lang) {\n // @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n return parameters[lang]['internal'][key] as string;\n }\n }\n}\n\nexport { createT9N, replace }\nexport type { SetupT9N, T9N, FunctionalSetupT9N } ","const RU = {\n 'NewGame': 'Новая игра',\n 'HomeScreen': 'Главный экран',\n 'ToTheGame': 'К игре',\n 'Language': 'Язык',\n 'NoSaves': 'Сохранений нет',\n 'LoadSave': 'Загрузить',\n 'Saves': 'Сохранения',\n 'Settings': 'Настройки',\n 'Sumbit': 'Подтвердить',\n 'GoBack': 'Назад',\n 'DoSave': 'Сохранение',\n 'Auto': 'Авто',\n 'Stop': 'Стоп',\n 'Exit': 'Выход',\n 'Automatic': 'Автоматическое',\n 'Manual': 'Ручное',\n 'Remove': 'Удалить',\n 'LoadASaveFrom': 'Загрузить сохранение от',\n 'DeleteASaveFrom': 'Удалить сохранение от',\n 'TextSpeed': 'Скорость Текста',\n 'TextSpeedSlow': 'Медленная',\n 'TextSpeedMedium': 'Средняя',\n 'TextSpeedFast': 'Быстрая',\n 'TextSpeedAuto': 'Автоматическая'\n};\n\ntype BaseTranslationStrings = keyof typeof RU;\n\nconst EN: Record<BaseTranslationStrings, string> = {\n 'NewGame': 'New Game',\n 'HomeScreen': 'Home Screen',\n 'ToTheGame': 'To the Game',\n 'Language': 'Language',\n 'NoSaves': 'No saves',\n 'LoadSave': 'Load',\n 'Saves': 'Saves',\n 'Settings': 'Settings',\n 'Sumbit': 'Submit',\n 'GoBack': 'Go back',\n 'DoSave': 'Save',\n 'Auto': 'Auto',\n 'Stop': 'Stop',\n 'Exit': 'Exit',\n 'Automatic': 'Automatic',\n 'Manual': 'Manual',\n 'Remove': 'Remove',\n 'LoadASaveFrom': 'Load a save from',\n 'DeleteASaveFrom': 'Delete a save from',\n 'TextSpeed': 'Text Speed',\n 'TextSpeedSlow': 'Slow',\n 'TextSpeedMedium': 'Medium',\n 'TextSpeedFast': 'Fast',\n 'TextSpeedAuto': 'Auto'\n};\n\nexport { RU, EN }\nexport type { BaseTranslationStrings }","import type { StorageData } from './types'\n\ninterface LocalStorageStorageSettings {\n key: string\n}\n\ninterface Storage {\n get: () => Promise<StorageData>;\n set: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n return {\n async get() {\n const value = localStorage.getItem(options.key);\n\n return value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n },\n async set(data) {\n localStorage.setItem(options.key, JSON.stringify(data));\n }\n }\n}\n\nexport type { Storage }\nexport { localStorageStorage }"],"mappings":"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","names":["isMergeableObject","deepmerge","split","input","delimeters","output","delimeter","start","end","RGX","replace","str","obj","pluralization","actions","pr","x","key","y","pathstr","plural","action","path","actionHandler","deepmerge","state","stack","save","action","index","next","c","str"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js","../src/index.ts","../src/utils.ts","../src/store.ts","../src/novely.ts","../../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/json/index.mjs","../src/constants.ts","../../t9n/src/lib.ts","../../t9n/src/translation.ts","../../t9n/src/translations.ts","../src/storage.ts"],"sourcesContent":["'use strict';\n\nvar isMergeableObject = function isMergeableObject(value) {\n\treturn isNonNullObject(value)\n\t\t&& !isSpecial(value)\n};\n\nfunction isNonNullObject(value) {\n\treturn !!value && typeof value === 'object'\n}\n\nfunction isSpecial(value) {\n\tvar stringValue = Object.prototype.toString.call(value);\n\n\treturn stringValue === '[object RegExp]'\n\t\t|| stringValue === '[object Date]'\n\t\t|| isReactElement(value)\n}\n\n// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25\nvar canUseSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;\n\nfunction isReactElement(value) {\n\treturn value.$$typeof === REACT_ELEMENT_TYPE\n}\n\nfunction emptyTarget(val) {\n\treturn Array.isArray(val) ? [] : {}\n}\n\nfunction cloneUnlessOtherwiseSpecified(value, options) {\n\treturn (options.clone !== false && options.isMergeableObject(value))\n\t\t? deepmerge(emptyTarget(value), value, options)\n\t\t: value\n}\n\nfunction defaultArrayMerge(target, source, options) {\n\treturn target.concat(source).map(function(element) {\n\t\treturn cloneUnlessOtherwiseSpecified(element, options)\n\t})\n}\n\nfunction getMergeFunction(key, options) {\n\tif (!options.customMerge) {\n\t\treturn deepmerge\n\t}\n\tvar customMerge = options.customMerge(key);\n\treturn typeof customMerge === 'function' ? customMerge : deepmerge\n}\n\nfunction getEnumerableOwnPropertySymbols(target) {\n\treturn Object.getOwnPropertySymbols\n\t\t? Object.getOwnPropertySymbols(target).filter(function(symbol) {\n\t\t\treturn Object.propertyIsEnumerable.call(target, symbol)\n\t\t})\n\t\t: []\n}\n\nfunction getKeys(target) {\n\treturn Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))\n}\n\nfunction propertyIsOnObject(object, property) {\n\ttry {\n\t\treturn property in object\n\t} catch(_) {\n\t\treturn false\n\t}\n}\n\n// Protects from prototype poisoning and unexpected merging up the prototype chain.\nfunction propertyIsUnsafe(target, key) {\n\treturn propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,\n\t\t&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,\n\t\t\t&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.\n}\n\nfunction mergeObject(target, source, options) {\n\tvar destination = {};\n\tif (options.isMergeableObject(target)) {\n\t\tgetKeys(target).forEach(function(key) {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(target[key], options);\n\t\t});\n\t}\n\tgetKeys(source).forEach(function(key) {\n\t\tif (propertyIsUnsafe(target, key)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {\n\t\t\tdestination[key] = getMergeFunction(key, options)(target[key], source[key], options);\n\t\t} else {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(source[key], options);\n\t\t}\n\t});\n\treturn destination\n}\n\nfunction deepmerge(target, source, options) {\n\toptions = options || {};\n\toptions.arrayMerge = options.arrayMerge || defaultArrayMerge;\n\toptions.isMergeableObject = options.isMergeableObject || isMergeableObject;\n\t// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()\n\t// implementations can use it. The caller may not replace it.\n\toptions.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;\n\n\tvar sourceIsArray = Array.isArray(source);\n\tvar targetIsArray = Array.isArray(target);\n\tvar sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;\n\n\tif (!sourceAndTargetTypesMatch) {\n\t\treturn cloneUnlessOtherwiseSpecified(source, options)\n\t} else if (sourceIsArray) {\n\t\treturn options.arrayMerge(target, source, options)\n\t} else {\n\t\treturn mergeObject(target, source, options)\n\t}\n}\n\ndeepmerge.all = function deepmergeAll(array, options) {\n\tif (!Array.isArray(array)) {\n\t\tthrow new Error('first argument should be an array')\n\t}\n\n\treturn array.reduce(function(prev, next) {\n\t\treturn deepmerge(prev, next, options)\n\t}, {})\n};\n\nvar deepmerge_1 = deepmerge;\n\nmodule.exports = deepmerge_1;\n","export type { ValidAction, Story, ActionProxyProvider, DefaultActionProxyProvider, GetActionParameters, Unwrappable, CustomHandler, CustomHandlerGetResult, CustomHandlerGetResultDataFunction, FunctionableValue } from './action'\nexport type { Emotions, Character } from './character'\nexport type { CharacterHandle, AudioHandle, RendererStore, Renderer, RendererInit } from './renderer'\nexport type { Storage } from './storage'\nexport type { Thenable, Path, StorageData, StorageMeta, TypewriterSpeed, Lang, NovelyScreen } from './types'\nexport type { Stored } from './store'\nexport type { BaseTranslationStrings } from '@novely/t9n';\n\nexport { novely } from './novely'\nexport { localStorageStorage } from './storage'","import type { ActionProxyProvider, CustomHandler } from './action'\nimport type { Character } from './character'\nimport type { TypewriterSpeed, Thenable } from './types'\n\ntype MatchActionMap = {\n [Key in keyof ActionProxyProvider<Record<string, Character>>]: (data: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>) => void;\n}\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n custom: (value: [handler: CustomHandler]) => Thenable<void>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n return (action: keyof MatchActionMap, props: any) => {\n return values[action](props);\n }\n}\n\nconst isNumber = (val: unknown): val is number => {\n return typeof val === 'number';\n}\n\nconst isNull = (val: unknown): val is null => {\n return val === null;\n}\n\nconst isString = (val: unknown): val is string => {\n return typeof val === 'string';\n}\n\nconst isFunction = (val: unknown): val is ((...parameters: any[]) => any) => {\n return typeof val === 'function';\n}\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n return Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then)\n}\n\nconst isEmpty = (val: unknown): val is {} => {\n return typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n}\n\nconst isCSSImage = (str: string) => {\n const startsWith = String.prototype.startsWith.bind(str);\n\n return startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n}\n\nconst str = (value: unknown) => {\n return String(value);\n}\n\nconst isUserRequiredAction = (action: keyof MatchActionMapComplete, meta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>) => {\n return action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n}\n\nconst getTypewriterSpeed = (): TypewriterSpeed => {\n return 'Medium'\n}\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n if (languages.includes(language)) {\n return language;\n } else if (languages.includes((language = language.substring(0, 2)))) {\n return language;\n } else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n return language\n }\n\n /**\n * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n */\n return 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 let throttled = false, savedArgs: any, savedThis: any;\n\n function wrapper(this: any) {\n if (throttled) {\n savedArgs = arguments;\n savedThis = this;\n return;\n }\n\n fn.apply(this, arguments as unknown as any[]);\n\n throttled = true;\n\n setTimeout(function () {\n throttled = false;\n\n if (savedArgs) {\n wrapper.apply(savedThis, savedArgs);\n savedArgs = savedThis = null;\n }\n }, ms);\n }\n\n return wrapper as unknown as (...args: Parameters<Fn>) => void;\n}\n\nconst vibrate = (pattern: VibratePattern) => {\n try {\n if ('vibrate' in navigator) {\n navigator.vibrate(pattern);\n }\n } catch { }\n}\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n for (let i = array.length - 1; i > 0; i--) {\n if (fn(array[i])) {\n return i;\n }\n }\n\n return -1;\n}\n\nexport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, isCSSImage, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex }","type Stored<T> = {\n subscribe: (cb: (value: T) => void) => () => void;\n update: (fn: (prev: T) => T) => void;\n get: () => T;\n}\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n const subscribe = (cb: (value: T) => void) => {\n subscribers.add(cb), cb(current);\n\n return () => {\n subscribers.delete(cb);\n }\n };\n\n const push = (value: T) => {\n subscribers.forEach((cb) => cb(value))\n };\n\n const update = (fn: (prev: T) => T) => {\n push((current = fn(current)));\n };\n\n const get = () => {\n return current;\n };\n\n return { subscribe, update, get } as const;\n};\n\nexport { store }\nexport type { Stored }","import type { Character } from './character';\nimport type { ActionProxyProvider, GetActionParameters, Story, ValidAction, Unwrappable, CustomHandler } from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types'\nimport type { Renderer, RendererInit } from './renderer'\nimport type { SetupT9N } from '@novely/t9n'\nimport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex } from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge'\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends ReturnType<SetupT9N<Languages>>, StateScheme extends State, DataScheme extends Data> {\n /**\n * An array of languages supported by the game.\n */\n languages: Languages[];\n /**\n * An object containing the characters in the game.\n */\n characters: Characters;\n /**\n * An object that provides access to the game's storage system.\n */\n storage: Storage;\n /**\n * Delay loading data until Promise is resolved\n */\n storageDelay?: Promise<void>;\n /**\n * A function that returns a Renderer object used to display the game's content\n */\n renderer: (characters: RendererInit) => Renderer;\n /**\n * An optional property that specifies the initial screen to display when the game starts\n */\n initialScreen?: NovelyScreen;\n /**\n * An object containing the translation functions used in the game\n */\n t9n: Inter;\n /**\n * Initial state value\n */\n state?: StateScheme;\n /**\n * Initial data value\n */\n data?: DataScheme;\n /**\n * Enable autosaves or disable\n * @default true\n */\n autosaves?: boolean;\n /**\n * Migration from old saves to newer\n */\n migrations?: Migration[]\n}\n\nconst novely = <\n Languages extends string,\n Characters extends Record<string, Character<Languages>>,\n Inter extends ReturnType<SetupT9N<Languages>>,\n StateScheme extends State,\n DataScheme extends Data\n>({\n characters,\n storage,\n storageDelay = Promise.resolve(),\n renderer: createRenderer,\n initialScreen = \"mainmenu\",\n t9n,\n languages,\n state: defaultState,\n data: defaultData,\n autosaves = true,\n migrations = []\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n let story: Story;\n let times = new Set<number>();\n\n /**\n * Prevent `undefined`\n */\n defaultData ||= {} as DataScheme;\n defaultState ||= {} as StateScheme;\n\n /**\n * Saves timestamps created in this session\n */\n const intime = (value: number) => {\n return times.add(value), value;\n }\n\n const withStory = (s: Story) => {\n /**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\n story = Object.fromEntries(Object.entries(s).map(([name, items]) => {\n const flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n return item.flatMap((data) => {\n const type = data[0];\n\n /**\n * This is not just an action like `['name', ...arguments]`, but an array of actions\n */\n if (Array.isArray(type)) return flat(data as ValidAction[]);\n\n return [data as ValidAction];\n });\n };\n\n return [name, flat(items)];\n }));\n\n /**\n * When `initialScreen` is not a game, we can safely show it\n */\n if (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n }\n\n const action = new Proxy({} as ActionProxyProvider<Characters>, {\n get(_, prop) {\n return (...props: Parameters<ActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]>) => {\n return [prop, ...props];\n }\n }\n });\n\n function state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n function state(): StateScheme;\n function state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n if (!value) return stack.value[1] as StateScheme | void;\n\n const prev = stack.value[1];\n const val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n stack.value[1] = val as StateScheme;\n }\n\n const getDefaultSave = (state = {}) => {\n return [[[null, 'start'], [null, 0]], state, [intime(Date.now()), 'auto']] as Save;\n }\n\n const createStack = (current: Save, stack = [current]) => {\n return {\n get value() {\n return stack.at(-1)!;\n },\n set value(value: Save) {\n stack[stack.length - 1] = value;\n },\n back() {\n if (stack.length > 1) stack.pop(), goingBack = true;\n },\n push(value: Save) {\n stack.push(value);\n },\n clear() {\n stack = [getDefaultSave(klona(defaultState))];\n }\n }\n }\n\n /**\n * 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 * 2) Actual stored data is loaded, language and etc is changed \n */\n const initialData: StorageData = {\n saves: [],\n data: klona(defaultData) as Data,\n meta: [getLanguage(languages), getTypewriterSpeed()],\n };\n\n const $ = store(initialData);\n\n let initialDataLoaded = false;\n\n const onStorageDataChange = (value: StorageData) => {\n if (initialDataLoaded) storage.set(value);\n };\n\n const throttledOnStorageDataChange = throttle(onStorageDataChange, 120);\n\n $.subscribe(throttledOnStorageDataChange);\n\n const getStoredData = () => {\n storage.get().then(stored => {\n /**\n * Migration is done only once (when game loads it's data), and then it saves the updated format\n */\n for (const migration of migrations) {\n // @ts-expect-error Types does not match between versions\n stored = migration(stored);\n }\n\n /**\n * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n */\n stored.meta[0] ||= getLanguage(languages);\n stored.meta[1] ||= getTypewriterSpeed();\n\n /**\n * When data is empty replace it with `defaultData`\n * It also might be empty (default to empty)\n */\n if (isEmpty(stored.data)) {\n stored.data = defaultData as Data;\n }\n\n /**\n * Now the next store updates will entail saving via storage.set\n */\n initialDataLoaded = true;\n\n $.update(() => stored);\n\n /**\n * When initialScreen is game, then we will load it, but after the data is loaded\n */\n if (initialScreen === 'game') restore();\n });\n }\n\n /**\n * By default this is resolved immediately, but also can be delayed.\n * I.e. storage has not loaded yet\n */\n storageDelay.then(getStoredData)\n\n const initial = getDefaultSave(klona(defaultState));\n const stack = createStack(initial);\n\n const save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n if (!initialDataLoaded) return;\n\n /**\n * When autosaves diabled just return\n */\n if (!autosaves && type === 'auto') return;\n\n const current = klona(stack.value);\n\n $.update(prev => {\n /**\n * Find latest save that were created in current session, and check if it is latest in an array\n * \n * We check if save was created in current session and it is latest in array\n * When it is not then replacing it will break logical chain\n * \n * [auto save 1]\n * [manual save 1]\n * [auto save 2] <- should not replace first auto save \n */\n const isLatest = findLastIndex(prev.saves, value => times.has(value[2][0])) === prev.saves.length - 1;\n\n /**\n * Update type and time information\n */\n current[2][0] = intime(Date.now());\n current[2][1] = type;\n\n if (!override || !isLatest) {\n prev.saves.push(current);\n\n return prev;\n }\n\n /**\n * Get latest\n */\n const latest = prev.saves.at(-1);\n\n /**\n * When that save is the same type, replace it\n */\n if (latest && latest[2][1] === type) {\n prev.saves[prev.saves.length - 1] = current;\n } else {\n prev.saves.push(current);\n }\n\n return prev;\n });\n }\n\n const newGame = () => {\n if (!initialDataLoaded) return;\n\n const save = getDefaultSave(klona(defaultState));\n\n /**\n * Initial save is automatic, and should be ignored when autosaves is turned off\n */\n if (autosaves) {\n $.update(prev => {\n return prev.saves.push(save), prev;\n });\n }\n\n restore(save);\n }\n\n /**\n * Set's the save\n */\n const set = (save: Save) => {\n stack.value = save;\n\n return restore(save);\n }\n\n let restoring = false;\n let goingBack = false;\n let interacted = false;\n\n /**\n * Restore\n */\n const restore = async (save?: Save) => {\n if (!initialDataLoaded) return;\n\n let latest = save ? save : $.get().saves.at(-1);\n\n /**\n * When there is no game, then make a new game\n */\n if (!latest) {\n $.update(() => ({ saves: [initial], data: klona(defaultData) as Data, meta: [getLanguage(languages), getTypewriterSpeed()] }));\n\n latest = klona(initial);\n }\n\n restoring = true, stack.value = latest;\n\n /**\n * Текущий элемент в истории\n */\n let current: any = story;\n /**\n * Текущий элемент `[null, int]`\n */\n let index = 0;\n\n /**\n * Число элементов `[null, int]`\n */\n const max = stack.value[0].reduce((acc, [type, val]) => {\n if (isNull(type) && isNumber(val)) return acc + 1;\n\n return acc;\n }, 0);\n\n const queue = [] as [any, any][];\n const keep = new Set();\n const characters = new Set();\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n if (isString(val)) {\n current = current[val];\n } else if (isNumber(val)) {\n index++;\n\n /**\n * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n */\n for (let i = 0; i <= val; i++) {\n const [action, ...meta] = current[i];\n\n /**\n * Add item to queue and action to keep\n */\n const push = () => {\n keep.add(action);\n queue.push([action, meta]);\n }\n\n /**\n * Do not remove characters that will be here anyways\n */\n if (action === 'showCharacter') characters.add(meta[0]);\n\n /**\n * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n */\n if (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n if (index === max && i === val) {\n push();\n } else {\n continue;\n }\n }\n\n push();\n }\n\n current = current[val];\n }\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n queue.forEach((value, index) => {\n /**\n * Mutate the queue item\n */\n value.push(index);\n });\n\n /**\n * This is basically made for TypeScript.\n */\n const indexedQueue = queue as unknown as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number][];\n\n /**\n * Run these exactly before the main loop.\n */\n renderer.ui.showScreen('game');\n /**\n * Provide the `keep` in there\n */\n match('clear', [keep, characters]);\n\n /**\n * Get the next actions array.\n */\n const next = (i: number) => indexedQueue.slice(i + 1);\n\n for await (const [action, meta, i] of indexedQueue) {\n if (action === 'function' || action === 'custom') {\n /**\n * When `callOnlyLatest` is `true`\n */\n if (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n /**\n * We'll calculate it is `latest` or not\n */\n const notLatest = next(i).some(([_action, _meta]) => {\n if (!_meta || !meta) return false;\n\n const c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n const c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n /**\n * Also check for `undefined`\n */\n const isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n \n /**\n * Equal by id or equal by `toString()`\n */\n return isIdenticalID || (str(c0) === str(c1));\n });\n\n if (notLatest) continue;\n }\n\n /**\n * Action can return Promise. \n */\n const result = match(action, meta);\n\n /**\n * Should wait until it resolved\n */\n if (isPromise(result)) {\n /**\n * Await it!\n */\n await result;\n }\n } else if (action === 'showCharacter') {\n const skip = next(i).some(([_action, _meta]) => {\n /**\n * Проверка на возможный `undefined`\n */\n if (!_meta || !meta) return false;\n\n /**\n * Будет ли персонаж скрыт в будущем\n * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n */\n const hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n /**\n * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n */\n const notLatest = _action === action && _meta[0] === meta[0];\n\n return hidden || notLatest;\n })\n\n if (skip) continue;\n\n match(action, meta);\n } else if (action === 'showBackground' || action === 'animateCharacter') {\n /**\n * Такая же оптимизация применяется к фонам и анимированию персонажей.\n * Если фон изменится, то нет смысла устанавливать текущий\n */\n const notLatest = next(i).some(([_action]) => action === _action);\n\n if (notLatest) continue;\n\n match(action, meta);\n } else {\n match(action, meta);\n }\n }\n\n restoring = goingBack = false, render();\n }\n\n const refer = () => {\n let current: any = story;\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n current = current[val];\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n return current;\n }\n\n const exit = () => {\n const current = stack.value;\n\n stack.clear();\n renderer.ui.showScreen('mainmenu');\n\n /**\n * First two save elements and it's type\n */\n const [[first, second], , [time, type]] = current;\n\n if (type === 'auto' && first && second) {\n /**\n * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n */\n if (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n $.update((prev) => {\n prev.saves = prev.saves.filter(save => save !== current);\n\n return prev;\n })\n }\n }\n\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n }\n\n const back = () => {\n return stack.back(), restore(stack.value);\n }\n\n const renderer = createRenderer({\n characters,\n set,\n restore,\n save,\n newGame,\n exit,\n back,\n stack,\n languages,\n t: t9n.i,\n $\n });\n\n const match = matchAction({\n wait([time]) {\n if (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n },\n showBackground([background]) {\n renderer.background(background);\n push()\n },\n playMusic([source]) {\n renderer.music(source, 'music').play();\n push()\n },\n stopMusic([source]) {\n renderer.music(source, 'music').stop();\n push()\n },\n showCharacter([character, emotion, className, style]) {\n const handle = renderer.character(character);\n\n handle.append(className, style, restoring);\n handle.withEmotion(emotion)();\n\n push()\n },\n hideCharacter([character, className, style, duration]) {\n renderer.character(character).remove(className, style, duration)(push, restoring);\n },\n dialog([character, content, emotion]) {\n /**\n * Person name\n */\n const name = (() => {\n const c = character, cs = characters;\n const lang = $.get().meta[0];\n\n return c ? c in cs ? typeof cs[c].name === 'string' ? cs[c].name as string : (cs[c].name as Record<string, string>)[lang] : c : '';\n })();\n\n renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n },\n function([fn]) {\n const result = fn(restoring, goingBack);\n\n if (!restoring) result ? result.then(push) : push();\n\n return result;\n },\n choice([question, ...choices]) {\n const isWithoutQuestion = Array.isArray(question);\n\n if (isWithoutQuestion) {\n /**\n * Первый элемент может быть как строкой, так и элементов выбора\n */\n choices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n /**\n * Значит, текст не требуется\n */\n question = '';\n }\n\n const unwrapped = choices.map(([content, action, visible]) => {\n return [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n });\n\n renderer.choices(unwrap(question), unwrapped)((selected) => {\n enmemory();\n\n /**\n * If there is a question, then `index` should be shifted by `1`\n */\n const offset = isWithoutQuestion ? 0 : 1;\n\n stack.value[0].push(['choice', selected + offset], [null, 0]);\n render();\n interactivity(true);\n });\n },\n jump([scene]) {\n /**\n * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n */\n stack.value[0] = [[null, scene], [null, -1]];\n\n match('clear', []);\n },\n clear([keep, characters]) {\n /**\n * Remove vibration\n */\n vibrate(0);\n /**\n * Call the actual `clear`\n */\n renderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n },\n condition([condition]) {\n const value = condition();\n\n if (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n },\n end() {\n /**\n * Clear the Scene\n */\n match('clear', []);\n /**\n * Go to the main menu\n */\n renderer.ui.showScreen('mainmenu');\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n },\n input([question, onInput, setup]) {\n renderer.input(unwrap(question), onInput, setup)(forward);\n },\n custom([handler]) {\n const result = renderer.custom(handler, goingBack, () => {\n if (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n if (!restoring) push();\n });\n\n return result;\n },\n vibrate(pattern) {\n vibrate(pattern);\n push()\n },\n next() {\n push();\n },\n animateCharacter([character, timeout, ...classes]) {\n const handler: CustomHandler = (get) => {\n const { clear } = get('@@internal-animate-character', false);\n const char = renderer.store.characters[character];\n\n /**\n * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n */\n if (!char) return;\n\n const target = char.canvas;\n\n /**\n * Character is not found\n */\n if (!target) return;\n\n const classNames = classes.filter(className => !target.classList.contains(className));\n\n target.classList.add(...classNames);\n\n const timeoutId = setTimeout(() => {\n target.classList.remove(...classNames);\n }, timeout);\n\n clear(() => {\n target.classList.remove(...classNames);\n \n /**\n * Clear timeout, because when you will game re-runs some callback might remove classes from character\n */\n clearTimeout(timeoutId);\n });\n }\n\n /**\n * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n */\n match('custom', [handler]);\n },\n text(text) {\n renderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n },\n exit() {\n const path = stack.value[0];\n\n for (let i = path.length - 1; i > 0; i--) {\n if (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n stack.value[0] = path.slice(0, i);\n next();\n\n break;\n }\n\n render();\n }\n });\n\n const enmemory = () => {\n if (restoring) return;\n\n const current = klona(stack.value);\n\n current[2][1] = 'auto';\n\n stack.push(current);\n\n save(true, 'auto');\n }\n\n const next = () => {\n const path = stack.value[0];\n /**\n * Последний элемент пути\n */\n const last = path[path.length - 1]!;\n\n /**\n * Если он вида `[null, int]` - увеличивает `int`\n */\n if (isNull(last[0]) && isNumber(last[1])) {\n last[1] = last[1] + 1;\n return;\n }\n\n /**\n * Иначе добавляет новое `[null int]`\n */\n path.push([null, 0]);\n }\n\n const render = () => {\n const referred = refer();\n\n if (!Array.isArray(referred)) return;\n\n const [action, ...props] = referred;\n\n match(action, props);\n }\n\n const push = () => {\n if (!restoring) next(), render();\n }\n\n const forward = () => {\n enmemory();\n push();\n interactivity(true)\n }\n\n const interactivity = (value = false) => {\n interacted = value;\n }\n\n /**\n * Unwraps translatable content to string\n * \n * @example ```\n * unwrap(t('Hello'));\n * unwrap({ en: 'Hello', ru: 'Привет' });\n * unwrap('Hello, {{name}}');\n * ```\n */\n const unwrap = (content: Unwrappable, global = false) => {\n const { data, meta: [lang] } = $.get();\n\n const obj = global ? data : state();\n const str = isFunction(content)\n ? content(lang, obj)\n : typeof content === 'object'\n ? content[lang]\n : content;\n \n return replaceT9N(str, obj);\n }\n\n function data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n function data(): DataScheme;\n function data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n if (!value) return $.get().data as DataScheme | void;\n\n const prev = $.get().data;\n const val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n $.update((prev) => {\n prev.data = val;\n\n return prev;\n });\n }\n\n return {\n /**\n * Function to set story\n */\n withStory,\n /**\n * Function to get actions\n */\n action,\n /**\n * State that belongs to games\n */\n state,\n /**\n * Unlike `state`, stored at global scope instead and shared between games\n */\n data,\n /**\n * Unwraps translatable content to a string value\n */\n unwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n return unwrap(content, true);\n },\n /**\n * Function that is used for translation\n */\n t: t9n.t as Inter['t'],\n }\n}\n\nexport { novely }\n","export function klona(val) {\n\tvar k, out, tmp;\n\n\tif (Array.isArray(val)) {\n\t\tout = Array(k=val.length);\n\t\twhile (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\treturn out;\n\t}\n\n\tif (Object.prototype.toString.call(val) === '[object Object]') {\n\t\tout = {}; // null\n\t\tfor (k in val) {\n\t\t\tif (k === '__proto__') {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tvalue: klona(val[k]),\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tout[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\n\treturn val;\n}\n","const SKIPPED_DURING_RESTORE = new Set([\n 'dialog',\n 'choice',\n 'input',\n 'vibrate',\n 'text'\n] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET }","const split = (input: string, delimeters: string[]) => {\n const output: (string | undefined)[] = [];\n\n for (const delimeter of delimeters) {\n if (!input) break;\n\n const [start, end] = input.split(delimeter, 2);\n\n output.push(start); input = end;\n }\n\n output.push(input);\n\n return output;\n}\n\nexport { split }","import type { BaseTranslationStrings } from './translations';\nimport { split } from './lib';\n\ntype PluralType = Intl.LDMLPluralRule;\ntype FunctionalSetupT9N = <LanguageKey extends string, PluralKey extends string, StringKey extends string, Actions extends string>(parameters: { [Lang in LanguageKey]: { pluralization: { [Plural in PluralKey]: Partial<Record<PluralType, string>> }; internal: { [Key in BaseTranslationStrings]: string }; strings: { [Str in StringKey]: string }; actions?: { [Action in Actions]?: (value: string) => string; } } }) => T9N<LanguageKey, StringKey>\ntype SetupT9N<LanguageKey extends string> = <PluralKey extends string, StringKey extends string, Actions extends string>(parameters: { [Lang in LanguageKey]: { pluralization: { [Plural in PluralKey]: Partial<Record<PluralType, string>> }; internal: { [Key in BaseTranslationStrings]: string }; strings: { [Str in StringKey]: string }; actions?: { [Action in Actions]?: (value: string) => string; } } }) => T9N<LanguageKey, StringKey>\n\ntype T9N<LanguageKey extends string, StringKey extends string> = {\n t(key: StringKey | Record<LanguageKey, string>): (lang: LanguageKey | (string & {}), obj: Record<string, unknown>) => string;\n i(key: StringKey, lang: LanguageKey | (string & {})): string;\n}\n\nconst RGX = /{{(.*?)}}/g;\n\nconst replace = (str: string | string[], obj: Record<string, unknown>, pluralization?: Record<string, Record<string, PluralType>>, actions?: Partial<Record<string, (str: string) => string>>, pr?: Intl.PluralRules) => {\n if (Array.isArray(str)) str = str.join('');\n\n return str.replace(RGX, (x: any, key: string, y: any) => {\n x = 0;\n y = obj;\n\n const [pathstr, plural, action] = split(key.trim(), ['@', '%']);\n\n let path = pathstr!.split('.');\n\n while (y && x < path.length) y = y[path[x++]];\n\n if (plural && pluralization && y && pr) {\n y = pluralization[plural][pr.select(y)];\n }\n\n const actionHandler = actions && action && actions[action];\n\n if (actionHandler) y = actionHandler(y);\n\n return y != null ? y : '';\n });\n}\n\nconst createT9N: FunctionalSetupT9N = (parameters) => {\n let locale: string | undefined;\n let pr: Intl.PluralRules | undefined;\n\n return {\n t(key) {\n return (lang, obj) => {\n /**\n * At first run `locale` and `pr` are not defined.\n * When `locale` changes, `pr` should be updated`\n */\n if (!locale || !pr || lang != locale) {\n pr = new Intl.PluralRules(locale = lang);\n }\n\n // @ts-ignore\n const str: string | string[] = typeof key === 'object' ? key[lang] : parameters[lang]['strings'][key];\n\n if (!str) return '';\n\n // @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n return replace(str, obj, parameters[lang]['pluralization'], parameters[lang]['actions'], pr);\n }\n },\n i(key, lang) {\n // @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n return parameters[lang]['internal'][key] as string;\n }\n }\n}\n\nexport { createT9N, replace }\nexport type { SetupT9N, T9N, FunctionalSetupT9N } ","const RU = {\n 'NewGame': 'Новая игра',\n 'HomeScreen': 'Главный экран',\n 'ToTheGame': 'К игре',\n 'Language': 'Язык',\n 'NoSaves': 'Сохранений нет',\n 'LoadSave': 'Загрузить',\n 'Saves': 'Сохранения',\n 'Settings': 'Настройки',\n 'Sumbit': 'Подтвердить',\n 'GoBack': 'Назад',\n 'DoSave': 'Сохранение',\n 'Auto': 'Авто',\n 'Stop': 'Стоп',\n 'Exit': 'Выход',\n 'Automatic': 'Автоматическое',\n 'Manual': 'Ручное',\n 'Remove': 'Удалить',\n 'LoadASaveFrom': 'Загрузить сохранение от',\n 'DeleteASaveFrom': 'Удалить сохранение от',\n 'TextSpeed': 'Скорость Текста',\n 'TextSpeedSlow': 'Медленная',\n 'TextSpeedMedium': 'Средняя',\n 'TextSpeedFast': 'Быстрая',\n 'TextSpeedAuto': 'Автоматическая'\n};\n\ntype BaseTranslationStrings = keyof typeof RU;\n\nconst EN: Record<BaseTranslationStrings, string> = {\n 'NewGame': 'New Game',\n 'HomeScreen': 'Home Screen',\n 'ToTheGame': 'To the Game',\n 'Language': 'Language',\n 'NoSaves': 'No saves',\n 'LoadSave': 'Load',\n 'Saves': 'Saves',\n 'Settings': 'Settings',\n 'Sumbit': 'Submit',\n 'GoBack': 'Go back',\n 'DoSave': 'Save',\n 'Auto': 'Auto',\n 'Stop': 'Stop',\n 'Exit': 'Exit',\n 'Automatic': 'Automatic',\n 'Manual': 'Manual',\n 'Remove': 'Remove',\n 'LoadASaveFrom': 'Load a save from',\n 'DeleteASaveFrom': 'Delete a save from',\n 'TextSpeed': 'Text Speed',\n 'TextSpeedSlow': 'Slow',\n 'TextSpeedMedium': 'Medium',\n 'TextSpeedFast': 'Fast',\n 'TextSpeedAuto': 'Auto'\n};\n\nexport { RU, EN }\nexport type { BaseTranslationStrings }","import type { StorageData } from './types'\n\ninterface LocalStorageStorageSettings {\n key: string\n}\n\ninterface Storage {\n get: () => Promise<StorageData>;\n set: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n return {\n async get() {\n const value = localStorage.getItem(options.key);\n\n return value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n },\n async set(data) {\n localStorage.setItem(options.key, JSON.stringify(data));\n }\n }\n}\n\nexport type { Storage }\nexport { localStorageStorage }"],"mappings":"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","names":["isMergeableObject","deepmerge","split","input","delimeters","output","delimeter","start","end","RGX","replace","str","obj","pluralization","actions","pr","x","key","y","pathstr","plural","action","path","actionHandler","data","deepmerge","state","stack","save","characters","action","push","index","next","c","str","prev"]}
package/dist/index.js CHANGED
@@ -16,6 +16,12 @@ var isString = (val) => {
16
16
  var isFunction = (val) => {
17
17
  return typeof val === "function";
18
18
  };
19
+ var isPromise = (val) => {
20
+ return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
21
+ };
22
+ var isEmpty = (val) => {
23
+ return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
24
+ };
19
25
  var str = (value) => {
20
26
  return String(value);
21
27
  };
@@ -104,6 +110,7 @@ var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set([
104
110
  "vibrate",
105
111
  "text"
106
112
  ]);
113
+ var EMPTY_SET = /* @__PURE__ */ new Set();
107
114
 
108
115
  // src/novely.ts
109
116
  import { replace as replaceT9N } from "@novely/t9n";
@@ -122,17 +129,19 @@ var novely = ({
122
129
  }) => {
123
130
  let story;
124
131
  let times = /* @__PURE__ */ new Set();
132
+ defaultData ||= {};
133
+ defaultState ||= {};
125
134
  const intime = (value) => {
126
135
  return times.add(value), value;
127
136
  };
128
137
  const withStory = (s) => {
129
138
  story = Object.fromEntries(Object.entries(s).map(([name, items]) => {
130
139
  const flat = (item) => {
131
- return item.flatMap((data) => {
132
- const type = data[0];
140
+ return item.flatMap((data2) => {
141
+ const type = data2[0];
133
142
  if (Array.isArray(type))
134
- return flat(data);
135
- return [data];
143
+ return flat(data2);
144
+ return [data2];
136
145
  });
137
146
  };
138
147
  return [name, flat(items)];
@@ -179,7 +188,7 @@ var novely = ({
179
188
  };
180
189
  const initialData = {
181
190
  saves: [],
182
- data: {},
191
+ data: klona(defaultData),
183
192
  meta: [getLanguage(languages), getTypewriterSpeed()]
184
193
  };
185
194
  const $ = store(initialData);
@@ -197,6 +206,9 @@ var novely = ({
197
206
  }
198
207
  stored.meta[0] ||= getLanguage(languages);
199
208
  stored.meta[1] ||= getTypewriterSpeed();
209
+ if (isEmpty(stored.data)) {
210
+ stored.data = defaultData;
211
+ }
200
212
  initialDataLoaded = true;
201
213
  $.update(() => stored);
202
214
  if (initialScreen === "game")
@@ -252,12 +264,10 @@ var novely = ({
252
264
  return;
253
265
  let latest = save2 ? save2 : $.get().saves.at(-1);
254
266
  if (!latest) {
255
- $.update(() => ({ saves: [initial], data: {}, meta: [getLanguage(languages), getTypewriterSpeed()] }));
267
+ $.update(() => ({ saves: [initial], data: klona(defaultData), meta: [getLanguage(languages), getTypewriterSpeed()] }));
256
268
  latest = klona(initial);
257
269
  }
258
270
  restoring = true, stack.value = latest;
259
- renderer.ui.showScreen("game");
260
- match("clear", [goingBack]);
261
271
  let current = story;
262
272
  let index = 0;
263
273
  const max = stack.value[0].reduce((acc, [type, val]) => {
@@ -266,22 +276,30 @@ var novely = ({
266
276
  return acc;
267
277
  }, 0);
268
278
  const queue = [];
279
+ const keep = /* @__PURE__ */ new Set();
280
+ const characters2 = /* @__PURE__ */ new Set();
269
281
  for (const [type, val] of stack.value[0]) {
270
282
  if (type === null) {
271
283
  if (isString(val)) {
272
284
  current = current[val];
273
285
  } else if (isNumber(val)) {
274
286
  index++;
275
- for (let i = 0; i < val; i++) {
287
+ for (let i = 0; i <= val; i++) {
276
288
  const [action2, ...meta] = current[i];
289
+ const push2 = () => {
290
+ keep.add(action2);
291
+ queue.push([action2, meta]);
292
+ };
293
+ if (action2 === "showCharacter")
294
+ characters2.add(meta[0]);
277
295
  if (SKIPPED_DURING_RESTORE.has(action2) || isUserRequiredAction(action2, meta)) {
278
296
  if (index === max && i === val) {
279
- queue.push([action2, meta]);
297
+ push2();
280
298
  } else {
281
299
  continue;
282
300
  }
283
301
  }
284
- queue.push([action2, meta]);
302
+ push2();
285
303
  }
286
304
  current = current[val];
287
305
  }
@@ -291,21 +309,33 @@ var novely = ({
291
309
  current = current[2][val];
292
310
  }
293
311
  }
294
- const indexedQueue = queue.map((value, index2) => value.concat(index2));
312
+ queue.forEach((value, index2) => {
313
+ value.push(index2);
314
+ });
315
+ const indexedQueue = queue;
316
+ renderer.ui.showScreen("game");
317
+ match("clear", [keep, characters2]);
318
+ const next2 = (i) => indexedQueue.slice(i + 1);
295
319
  for await (const [action2, meta, i] of indexedQueue) {
296
320
  if (action2 === "function" || action2 === "custom") {
297
321
  if (action2 === "custom" && meta[0].callOnlyLatest) {
298
- const next2 = indexedQueue.slice(i + 1);
299
- const notLatest = next2.some(([_action, _meta]) => _meta && meta && str(_meta[0]) === str(meta[0]));
322
+ const notLatest = next2(i).some(([_action, _meta]) => {
323
+ if (!_meta || !meta)
324
+ return false;
325
+ const c0 = _meta[0];
326
+ const c1 = meta[0];
327
+ const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
328
+ return isIdenticalID || str(c0) === str(c1);
329
+ });
300
330
  if (notLatest)
301
331
  continue;
302
332
  }
303
333
  const result = match(action2, meta);
304
- if (result && "then" in result)
334
+ if (isPromise(result)) {
305
335
  await result;
336
+ }
306
337
  } else if (action2 === "showCharacter") {
307
- const next2 = indexedQueue.slice(i + 1);
308
- const skip = next2.some(([_action, _meta]) => {
338
+ const skip = next2(i).some(([_action, _meta]) => {
309
339
  if (!_meta || !meta)
310
340
  return false;
311
341
  const hidden = _action === "hideCharacter" && _meta[0] === meta[0];
@@ -315,9 +345,8 @@ var novely = ({
315
345
  if (skip)
316
346
  continue;
317
347
  match(action2, meta);
318
- } else if (action2 === "showBackground") {
319
- const next2 = indexedQueue.slice(i + 1);
320
- const notLatest = next2.some(([_action]) => action2 === _action);
348
+ } else if (action2 === "showBackground" || action2 === "animateCharacter") {
349
+ const notLatest = next2(i).some(([_action]) => action2 === _action);
321
350
  if (notLatest)
322
351
  continue;
323
352
  match(action2, meta);
@@ -423,16 +452,19 @@ var novely = ({
423
452
  });
424
453
  renderer.choices(unwrap(question), unwrapped)((selected) => {
425
454
  enmemory();
426
- stack.value[0].push(["choice", isWithoutQuestion ? selected : selected + 1], [null, 0]), render(), interactivity(true);
455
+ const offset = isWithoutQuestion ? 0 : 1;
456
+ stack.value[0].push(["choice", selected + offset], [null, 0]);
457
+ render();
458
+ interactivity(true);
427
459
  });
428
460
  },
429
461
  jump([scene]) {
430
462
  stack.value[0] = [[null, scene], [null, -1]];
431
463
  match("clear", []);
432
464
  },
433
- clear() {
465
+ clear([keep, characters2]) {
434
466
  vibrate(0);
435
- renderer.clear(goingBack)(push);
467
+ renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
436
468
  },
437
469
  condition([condition]) {
438
470
  const value = condition();
@@ -479,12 +511,11 @@ var novely = ({
479
511
  target.classList.remove(...classNames);
480
512
  }, timeout);
481
513
  clear(() => {
514
+ target.classList.remove(...classNames);
482
515
  clearTimeout(timeoutId);
483
516
  });
484
517
  };
485
- handler.callOnlyLatest = true;
486
- return renderer.custom(handler, goingBack, () => {
487
- }), push();
518
+ match("custom", [handler]);
488
519
  },
489
520
  text(text) {
490
521
  renderer.text(text.map((content) => unwrap(content)).join(" "), forward);
@@ -538,21 +569,47 @@ var novely = ({
538
569
  interacted = value;
539
570
  };
540
571
  const unwrap = (content, global = false) => {
541
- const { data, meta: [lang] } = $.get();
542
- const obj = global ? data : state();
572
+ const { data: data2, meta: [lang] } = $.get();
573
+ const obj = global ? data2 : state();
543
574
  const str2 = isFunction(content) ? content(lang, obj) : typeof content === "object" ? content[lang] : content;
544
575
  return replaceT9N(str2, obj);
545
576
  };
577
+ function data(value) {
578
+ if (!value)
579
+ return $.get().data;
580
+ const prev = $.get().data;
581
+ const val = isFunction(value) ? value(prev) : deepmerge([prev, value]);
582
+ $.update((prev2) => {
583
+ prev2.data = val;
584
+ return prev2;
585
+ });
586
+ }
546
587
  return {
588
+ /**
589
+ * Function to set story
590
+ */
547
591
  withStory,
592
+ /**
593
+ * Function to get actions
594
+ */
548
595
  action,
596
+ /**
597
+ * State that belongs to games
598
+ */
549
599
  state,
600
+ /**
601
+ * Unlike `state`, stored at global scope instead and shared between games
602
+ */
603
+ data,
550
604
  /**
551
605
  * Unwraps translatable content to a string value
552
606
  */
553
607
  unwrap(content) {
554
608
  return unwrap(content, true);
555
609
  },
610
+ /**
611
+ * Function that is used for translation
612
+ */
556
613
  t: t9n.t
557
614
  };
558
615
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.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 { TypewriterSpeed, Thenable } from './types'\n\ntype MatchActionMap = {\n [Key in keyof ActionProxyProvider<Record<string, Character>>]: (data: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>) => void;\n}\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n custom: (value: [handler: CustomHandler]) => Thenable<void>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n return (action: keyof MatchActionMap, props: any) => {\n return values[action](props);\n }\n}\n\nconst isNumber = (val: unknown): val is number => {\n return typeof val === 'number';\n}\n\nconst isNull = (val: unknown): val is null => {\n return val === null;\n}\n\nconst isString = (val: unknown): val is string => {\n return typeof val === 'string';\n}\n\nconst isFunction = (val: unknown): val is ((...parameters: any[]) => any) => {\n return typeof val === 'function';\n}\n\nconst isCSSImage = (str: string) => {\n const startsWith = String.prototype.startsWith.bind(str);\n\n return startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n}\n\nconst str = (value: unknown) => {\n return String(value);\n}\n\nconst isUserRequiredAction = (action: keyof MatchActionMapComplete, meta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>) => {\n return action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n}\n\nconst getTypewriterSpeed = (): TypewriterSpeed => {\n return 'Medium'\n}\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n if (languages.includes(language)) {\n return language;\n } else if (languages.includes((language = language.substring(0, 2)))) {\n return language;\n } else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n return language\n }\n\n /**\n * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n */\n return 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 let throttled = false, savedArgs: any, savedThis: any;\n\n function wrapper(this: any) {\n if (throttled) {\n savedArgs = arguments;\n savedThis = this;\n return;\n }\n\n fn.apply(this, arguments as unknown as any[]);\n\n throttled = true;\n\n setTimeout(function () {\n throttled = false;\n\n if (savedArgs) {\n wrapper.apply(savedThis, savedArgs);\n savedArgs = savedThis = null;\n }\n }, ms);\n }\n\n return wrapper as unknown as (...args: Parameters<Fn>) => void;\n}\n\nconst vibrate = (pattern: VibratePattern) => {\n try {\n if ('vibrate' in navigator) {\n navigator.vibrate(pattern);\n }\n } catch { }\n}\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n for (let i = array.length - 1; i > 0; i--) {\n if (fn(array[i])) {\n return i;\n }\n }\n\n return -1;\n}\n\nexport { matchAction, isNumber, isNull, isString, isCSSImage, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex }","type Stored<T> = {\n subscribe: (cb: (value: T) => void) => () => void;\n update: (fn: (prev: T) => T) => void;\n get: () => T;\n}\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n const subscribe = (cb: (value: T) => void) => {\n subscribers.add(cb), cb(current);\n\n return () => {\n subscribers.delete(cb);\n }\n };\n\n const push = (value: T) => {\n subscribers.forEach((cb) => cb(value))\n };\n\n const update = (fn: (prev: T) => T) => {\n push((current = fn(current)));\n };\n\n const get = () => {\n return current;\n };\n\n return { subscribe, update, get } as const;\n};\n\nexport { store }\nexport type { Stored }","import type { Character } from './character';\nimport type { ActionProxyProvider, GetActionParameters, Story, ValidAction, Unwrappable, CustomHandler } from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types'\nimport type { Renderer, RendererInit } from './renderer'\nimport type { SetupT9N } from '@novely/t9n'\nimport { matchAction, isNumber, isNull, isString, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex } from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge'\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends ReturnType<SetupT9N<Languages>>, StateScheme extends State, DataScheme extends Data> {\n /**\n * An array of languages supported by the game.\n */\n languages: Languages[];\n /**\n * An object containing the characters in the game.\n */\n characters: Characters;\n /**\n * An object that provides access to the game's storage system.\n */\n storage: Storage;\n /**\n * Delay loading data until Promise is resolved\n */\n storageDelay?: Promise<void>;\n /**\n * A function that returns a Renderer object used to display the game's content\n */\n renderer: (characters: RendererInit) => Renderer;\n /**\n * An optional property that specifies the initial screen to display when the game starts\n */\n initialScreen?: NovelyScreen;\n /**\n * An object containing the translation functions used in the game\n */\n t9n: Inter;\n /**\n * Initial state value\n */\n state?: StateScheme;\n /**\n * Initial data value\n */\n data?: DataScheme;\n /**\n * Enable autosaves or disable\n * @default true\n */\n autosaves?: boolean;\n /**\n * Migration from old saves to newer\n */\n migrations?: Migration[]\n}\n\nconst novely = <\n Languages extends string,\n Characters extends Record<string, Character<Languages>>,\n Inter extends ReturnType<SetupT9N<Languages>>,\n StateScheme extends State,\n DataScheme extends Data\n>({\n characters,\n storage,\n storageDelay = Promise.resolve(),\n renderer: createRenderer,\n initialScreen = \"mainmenu\",\n t9n,\n languages,\n state: defaultState,\n data: defaultData,\n autosaves = true,\n migrations = []\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n let story: Story;\n let times = new Set<number>();\n\n /**\n * Saves timestamps created in this session\n */\n const intime = (value: number) => {\n return times.add(value), value;\n }\n\n // @todo: find bug here\n const withStory = (s: Story) => {\n /**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\n story = Object.fromEntries(Object.entries(s).map(([name, items]) => {\n const flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n return item.flatMap((data) => {\n const type = data[0];\n\n /**\n * This is not just an action like `['name', ...arguments]`, but an array of actions\n */\n if (Array.isArray(type)) return flat(data as ValidAction[]);\n\n return [data as ValidAction];\n });\n };\n\n return [name, flat(items)];\n }));\n\n /**\n * When `initialScreen` is not a game, we can safely show it\n */\n if (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n }\n\n const action = new Proxy({} as ActionProxyProvider<Characters>, {\n get(_, prop) {\n return (...props: Parameters<ActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]>) => {\n return [prop, ...props];\n }\n }\n });\n\n function state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n function state(): StateScheme;\n function state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n if (!value) return stack.value[1] as StateScheme | void;\n\n const prev = stack.value[1];\n const val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n stack.value[1] = val as StateScheme;\n }\n\n const getDefaultSave = (state = {}) => {\n return [[[null, 'start'], [null, 0]], state, [intime(Date.now()), 'auto']] as Save;\n }\n\n const createStack = (current: Save, stack = [current]) => {\n return {\n get value() {\n return stack.at(-1)!;\n },\n set value(value: Save) {\n stack[stack.length - 1] = value;\n },\n back() {\n if (stack.length > 1) stack.pop(), goingBack = true;\n },\n push(value: Save) {\n stack.push(value);\n },\n clear() {\n stack = [getDefaultSave(klona(defaultState))];\n }\n }\n }\n\n /**\n * 1) Novely rendered using the `initialData`, you can still start new game or `load` an empty one - this is scary, imagine losing your progress\n * 2) Actual stored data is loaded, language and etc is changed \n */\n const initialData: StorageData = {\n saves: [],\n data: {},\n meta: [getLanguage(languages), getTypewriterSpeed()],\n };\n\n const $ = store(initialData);\n\n let initialDataLoaded = false;\n\n const onStorageDataChange = (value: StorageData) => {\n if (initialDataLoaded) storage.set(value);\n };\n\n const throttledOnStorageDataChange = throttle(onStorageDataChange, 120);\n\n $.subscribe(throttledOnStorageDataChange);\n\n const getStoredData = () => {\n storage.get().then(stored => {\n /**\n * Migration is done only once (when game loads it's data), and then it saves the updated format\n */\n for (const migration of migrations) {\n // @ts-expect-error Types does not match between versions\n stored = migration(stored);\n }\n\n /**\n * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n */\n stored.meta[0] ||= getLanguage(languages);\n stored.meta[1] ||= getTypewriterSpeed();\n\n /**\n * Now the next store updates will entail saving via storage.set\n */\n initialDataLoaded = true;\n\n $.update(() => stored);\n\n /**\n * When initialScreen is game, then we will load it, but after the data is loaded\n */\n if (initialScreen === 'game') restore();\n });\n }\n\n /**\n * By default this is resolved immediately, but also can be delayed.\n * I.e. storage has not loaded yet\n */\n storageDelay.then(getStoredData)\n\n const initial = getDefaultSave(klona(defaultState));\n const stack = createStack(initial);\n\n const save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n if (!initialDataLoaded) return;\n\n /**\n * When autosaves diabled just return\n */\n if (!autosaves && type === 'auto') return;\n\n const current = klona(stack.value);\n\n $.update(prev => {\n /**\n * Find latest save that were created in current session, and check if it is latest in an array\n * \n * We check if save was created in current session and it is latest in array\n * When it is not then replacing it will break logical chain\n * \n * [auto save 1]\n * [manual save 1]\n * [auto save 2] <- should not replace first auto save \n */\n const isLatest = findLastIndex(prev.saves, value => times.has(value[2][0])) === prev.saves.length - 1;\n\n /**\n * Update type and time information\n */\n current[2][0] = intime(Date.now());\n current[2][1] = type;\n\n if (!override || !isLatest) {\n prev.saves.push(current);\n\n return prev;\n }\n\n /**\n * Get latest\n */\n const latest = prev.saves.at(-1);\n\n /**\n * When that save is the same type, replace it\n */\n if (latest && latest[2][1] === type) {\n prev.saves[prev.saves.length - 1] = current;\n } else {\n prev.saves.push(current);\n }\n\n return prev;\n });\n }\n\n const newGame = () => {\n if (!initialDataLoaded) return;\n\n const save = getDefaultSave(klona(defaultState));\n\n /**\n * Initial save is automatic, and should be ignored when autosaves is turned off\n */\n if (autosaves) {\n $.update(prev => {\n return prev.saves.push(save), prev;\n });\n }\n\n restore(save);\n }\n\n /**\n * Set's the save\n */\n const set = (save: Save) => {\n stack.value = save;\n\n return restore(save);\n }\n\n let restoring = false;\n let goingBack = false;\n let interacted = false;\n\n /**\n * Restore\n */\n const restore = async (save?: Save) => {\n if (!initialDataLoaded) return;\n\n let latest = save ? save : $.get().saves.at(-1);\n\n /**\n * When there is no game, then make a new game\n */\n if (!latest) {\n $.update(() => ({ saves: [initial], data: {}, meta: [getLanguage(languages), getTypewriterSpeed()] }));\n\n latest = klona(initial);\n }\n\n restoring = true, stack.value = latest;\n\n renderer.ui.showScreen('game');\n match('clear', [goingBack]);\n\n /**\n * Текущий элемент в истории\n */\n let current: any = story;\n /**\n * Текущий элемент `[null, int]`\n */\n let index = 0;\n\n /**\n * Число элементов `[null, int]`\n */\n const max = stack.value[0].reduce((acc, [type, val]) => {\n if (isNull(type) && isNumber(val)) return acc + 1;\n\n return acc;\n }, 0);\n\n const queue = [] as [any, any][];\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n if (isString(val)) {\n current = current[val];\n } else if (isNumber(val)) {\n index++;\n\n /**\n * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n */\n for (let i = 0; i < val; i++) {\n const [action, ...meta] = current[i];\n\n /**\n * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n */\n if (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n if (index === max && i === val) {\n queue.push([action, meta]);\n } else {\n continue;\n }\n }\n\n queue.push([action, meta]);\n }\n\n current = current[val];\n }\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n const indexedQueue = queue.map((value, index) => value.concat(index) as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number]);\n\n for await (const [action, meta, i] of indexedQueue) {\n if (action === 'function' || action === 'custom') {\n /**\n * Если `callOnlyLatest` - `true`\n */\n if (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n /**\n * Вычислим `latest` или нет\n */\n const next = indexedQueue.slice(i + 1);\n const notLatest = next.some(([_action, _meta]) => _meta && meta && str(_meta[0]) === str(meta[0]));\n\n if (notLatest) continue;\n }\n\n /**\n * Action может возвращать Promise. Нужно подожать его `resolve`\n */\n const result = match(action, meta);\n\n /**\n * Дождёмся окончания\n */\n if (result && 'then' in result) await result;\n } else if (action === 'showCharacter') {\n const next = indexedQueue.slice(i + 1);\n const skip = next.some(([_action, _meta]) => {\n /**\n * Проверка на возможный `undefined`\n */\n if (!_meta || !meta) return false;\n\n /**\n * Будет ли персонаж скрыт в будущем\n * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n */\n const hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n /**\n * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n */\n const notLatest = _action === action && _meta[0] === meta[0];\n\n return hidden || notLatest;\n })\n\n if (skip) continue;\n\n match(action, meta);\n } else if (action === 'showBackground') {\n const next = indexedQueue.slice(i + 1);\n /**\n * Такая же оптимизация применяется к фонам.\n * Если фон изменится, то нет смысла устанавливать текущий\n */\n const notLatest = next.some(([_action]) => action === _action);\n\n if (notLatest) continue;\n\n match(action, meta);\n } else {\n match(action, meta);\n }\n }\n\n restoring = goingBack = false, render();\n }\n\n const refer = () => {\n let current: any = story;\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n current = current[val];\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n return current;\n }\n\n const exit = () => {\n const current = stack.value;\n\n stack.clear();\n renderer.ui.showScreen('mainmenu');\n\n /**\n * First two save elements and it's type\n */\n const [[first, second], , [time, type]] = current;\n\n if (type === 'auto' && first && second) {\n /**\n * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n */\n if (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n $.update((prev) => {\n prev.saves = prev.saves.filter(save => save !== current);\n\n return prev;\n })\n }\n }\n\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n }\n\n const back = () => {\n return stack.back(), restore(stack.value);\n }\n\n const renderer = createRenderer({\n characters,\n set,\n restore,\n save,\n newGame,\n exit,\n back,\n stack,\n languages,\n t: t9n.i,\n $\n });\n\n const match = matchAction({\n wait([time]) {\n /**\n * `restoring` может поменяться на `true` перед тем как запуститься `push` из `setTimeout`\n */\n if (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n },\n showBackground([background]) {\n renderer.background(background);\n push()\n },\n playMusic([source]) {\n renderer.music(source, 'music').play();\n push()\n },\n stopMusic([source]) {\n renderer.music(source, 'music').stop();\n push()\n },\n showCharacter([character, emotion, className, style]) {\n const handle = renderer.character(character);\n\n handle.append(className, style, restoring);\n handle.withEmotion(emotion)();\n\n push()\n },\n hideCharacter([character, className, style, duration]) {\n renderer.character(character).remove(className, style, duration)(push, restoring);\n },\n dialog([character, content, emotion]) {\n /**\n * Имя персонажа, с учетом выбранного языка\n */\n const name = (() => {\n const c = character, cs = characters;\n const lang = $.get().meta[0];\n\n return c ? c in cs ? typeof cs[c].name === 'string' ? cs[c].name as string : (cs[c].name as Record<string, string>)[lang] : c : '';\n })();\n\n renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n },\n function([fn]) {\n const result = fn(restoring, goingBack);\n\n if (!restoring) result ? result.then(push) : push();\n\n return result;\n },\n choice([question, ...choices]) {\n const isWithoutQuestion = Array.isArray(question);\n\n if (isWithoutQuestion) {\n /**\n * Первый элемент может быть как строкой, так и элементов выбора\n */\n choices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n /**\n * Значит, текст не требуется\n */\n question = '';\n }\n\n const unwrapped = choices.map(([content, action, visible]) => {\n return [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n });\n\n renderer.choices(unwrap(question), unwrapped)((selected) => {\n enmemory();\n\n /**\n * Если был вопрос, то `index` смещается на единицу назад, поэтому нужно добавить единицу\n */\n stack.value[0].push(['choice', isWithoutQuestion ? selected : selected + 1], [null, 0]), render(), interactivity(true);\n });\n },\n jump([scene]) {\n /**\n * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n */\n stack.value[0] = [[null, scene], [null, -1]];\n\n match('clear', []);\n },\n clear() {\n vibrate(0);\n renderer.clear(goingBack)(push);\n },\n condition([condition]) {\n const value = condition();\n\n if (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n },\n end() {\n /**\n * Clear the Scene\n */\n match('clear', []);\n /**\n * Go to the main menu\n */\n renderer.ui.showScreen('mainmenu');\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n },\n input([question, onInput, setup]) {\n renderer.input(unwrap(question), onInput, setup)(forward);\n },\n custom([handler]) {\n const result = renderer.custom(handler, goingBack, () => {\n if (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n if (!restoring) push();\n });\n\n return result;\n },\n vibrate(pattern) {\n vibrate(pattern);\n push()\n },\n next() {\n push();\n },\n animateCharacter([character, timeout, ...classes]) {\n const handler: CustomHandler = (get) => {\n const { clear } = get('@@internal-animate-character', false);\n const char = renderer.store.characters[character];\n\n /**\n * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n */\n if (!char) return;\n\n const target = char.canvas;\n\n /**\n * Character is not found\n */\n if (!target) return;\n\n const classNames = classes.filter(className => !target.classList.contains(className));\n\n target.classList.add(...classNames);\n\n const timeoutId = setTimeout(() => {\n target.classList.remove(...classNames);\n }, timeout);\n\n clear(() => {\n /**\n * Clear timeout, because when you will game re-runs some callback might remove classes from character\n */\n clearTimeout(timeoutId);\n });\n }\n\n handler.callOnlyLatest = true;\n\n return renderer.custom(handler, goingBack, () => { }), push();\n },\n text(text) {\n renderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n },\n exit() {\n const path = stack.value[0];\n\n for (let i = path.length - 1; i > 0; i--) {\n if (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n stack.value[0] = path.slice(0, i);\n next();\n\n break;\n }\n\n render();\n }\n });\n\n const enmemory = () => {\n if (restoring) return;\n\n const current = klona(stack.value);\n\n current[2][1] = 'auto';\n\n stack.push(current);\n\n save(true, 'auto');\n }\n\n const next = () => {\n const path = stack.value[0];\n /**\n * Последний элемент пути\n */\n const last = path[path.length - 1]!;\n\n /**\n * Если он вида `[null, int]` - увеличивает `int`\n */\n if (isNull(last[0]) && isNumber(last[1])) {\n last[1] = last[1] + 1;\n return;\n }\n\n /**\n * Иначе добавляет новое `[null int]`\n */\n path.push([null, 0]);\n }\n\n const render = () => {\n const referred = refer();\n\n if (!Array.isArray(referred)) return;\n\n const [action, ...props] = referred;\n\n match(action, props);\n }\n\n const push = () => {\n if (!restoring) next(), render();\n }\n\n const forward = () => {\n enmemory();\n push();\n interactivity(true)\n }\n\n const interactivity = (value = false) => {\n interacted = value;\n }\n\n /**\n * Unwraps translatable content to string\n * \n * @example ```\n * unwrap(t('Hello'));\n * unwrap({ en: 'Hello', ru: 'Привет' });\n * unwrap('Hello, {{name}}');\n * ```\n */\n const unwrap = (content: Unwrappable, global = false) => {\n const { data, meta: [lang] } = $.get();\n\n const obj = global ? data : state();\n const str = isFunction(content)\n ? content(lang, obj)\n : typeof content === 'object'\n ? content[lang]\n : content;\n \n return replaceT9N(str, obj);\n }\n\n return {\n withStory,\n action,\n state,\n /**\n * Unwraps translatable content to a string value\n */\n unwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n return unwrap(content, true);\n },\n t: t9n.t as Inter['t'],\n }\n}\n\nexport { novely }\n","const SKIPPED_DURING_RESTORE = new Set([\n 'dialog',\n 'choice',\n 'input',\n 'vibrate',\n 'text'\n] as const);\n\nexport { SKIPPED_DURING_RESTORE }","import type { StorageData } from './types'\n\ninterface LocalStorageStorageSettings {\n key: string\n}\n\ninterface Storage {\n get: () => Promise<StorageData>;\n set: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n return {\n async get() {\n const value = localStorage.getItem(options.key);\n\n return value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n },\n async set(data) {\n localStorage.setItem(options.key, JSON.stringify(data));\n }\n }\n}\n\nexport type { Storage }\nexport { localStorageStorage }"],"mappings":"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","names":["state","stack","save","action","index","next","str"]}
1
+ {"version":3,"sources":["../src/utils.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 { TypewriterSpeed, Thenable } from './types'\n\ntype MatchActionMap = {\n [Key in keyof ActionProxyProvider<Record<string, Character>>]: (data: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>) => void;\n}\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n custom: (value: [handler: CustomHandler]) => Thenable<void>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n return (action: keyof MatchActionMap, props: any) => {\n return values[action](props);\n }\n}\n\nconst isNumber = (val: unknown): val is number => {\n return typeof val === 'number';\n}\n\nconst isNull = (val: unknown): val is null => {\n return val === null;\n}\n\nconst isString = (val: unknown): val is string => {\n return typeof val === 'string';\n}\n\nconst isFunction = (val: unknown): val is ((...parameters: any[]) => any) => {\n return typeof val === 'function';\n}\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n return Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then)\n}\n\nconst isEmpty = (val: unknown): val is {} => {\n return typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n}\n\nconst isCSSImage = (str: string) => {\n const startsWith = String.prototype.startsWith.bind(str);\n\n return startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n}\n\nconst str = (value: unknown) => {\n return String(value);\n}\n\nconst isUserRequiredAction = (action: keyof MatchActionMapComplete, meta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>) => {\n return action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n}\n\nconst getTypewriterSpeed = (): TypewriterSpeed => {\n return 'Medium'\n}\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n if (languages.includes(language)) {\n return language;\n } else if (languages.includes((language = language.substring(0, 2)))) {\n return language;\n } else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n return language\n }\n\n /**\n * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n */\n return 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 let throttled = false, savedArgs: any, savedThis: any;\n\n function wrapper(this: any) {\n if (throttled) {\n savedArgs = arguments;\n savedThis = this;\n return;\n }\n\n fn.apply(this, arguments as unknown as any[]);\n\n throttled = true;\n\n setTimeout(function () {\n throttled = false;\n\n if (savedArgs) {\n wrapper.apply(savedThis, savedArgs);\n savedArgs = savedThis = null;\n }\n }, ms);\n }\n\n return wrapper as unknown as (...args: Parameters<Fn>) => void;\n}\n\nconst vibrate = (pattern: VibratePattern) => {\n try {\n if ('vibrate' in navigator) {\n navigator.vibrate(pattern);\n }\n } catch { }\n}\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n for (let i = array.length - 1; i > 0; i--) {\n if (fn(array[i])) {\n return i;\n }\n }\n\n return -1;\n}\n\nexport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, isCSSImage, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex }","type Stored<T> = {\n subscribe: (cb: (value: T) => void) => () => void;\n update: (fn: (prev: T) => T) => void;\n get: () => T;\n}\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n const subscribe = (cb: (value: T) => void) => {\n subscribers.add(cb), cb(current);\n\n return () => {\n subscribers.delete(cb);\n }\n };\n\n const push = (value: T) => {\n subscribers.forEach((cb) => cb(value))\n };\n\n const update = (fn: (prev: T) => T) => {\n push((current = fn(current)));\n };\n\n const get = () => {\n return current;\n };\n\n return { subscribe, update, get } as const;\n};\n\nexport { store }\nexport type { Stored }","import type { Character } from './character';\nimport type { ActionProxyProvider, GetActionParameters, Story, ValidAction, Unwrappable, CustomHandler } from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types'\nimport type { Renderer, RendererInit } from './renderer'\nimport type { SetupT9N } from '@novely/t9n'\nimport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex } from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge'\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends ReturnType<SetupT9N<Languages>>, StateScheme extends State, DataScheme extends Data> {\n /**\n * An array of languages supported by the game.\n */\n languages: Languages[];\n /**\n * An object containing the characters in the game.\n */\n characters: Characters;\n /**\n * An object that provides access to the game's storage system.\n */\n storage: Storage;\n /**\n * Delay loading data until Promise is resolved\n */\n storageDelay?: Promise<void>;\n /**\n * A function that returns a Renderer object used to display the game's content\n */\n renderer: (characters: RendererInit) => Renderer;\n /**\n * An optional property that specifies the initial screen to display when the game starts\n */\n initialScreen?: NovelyScreen;\n /**\n * An object containing the translation functions used in the game\n */\n t9n: Inter;\n /**\n * Initial state value\n */\n state?: StateScheme;\n /**\n * Initial data value\n */\n data?: DataScheme;\n /**\n * Enable autosaves or disable\n * @default true\n */\n autosaves?: boolean;\n /**\n * Migration from old saves to newer\n */\n migrations?: Migration[]\n}\n\nconst novely = <\n Languages extends string,\n Characters extends Record<string, Character<Languages>>,\n Inter extends ReturnType<SetupT9N<Languages>>,\n StateScheme extends State,\n DataScheme extends Data\n>({\n characters,\n storage,\n storageDelay = Promise.resolve(),\n renderer: createRenderer,\n initialScreen = \"mainmenu\",\n t9n,\n languages,\n state: defaultState,\n data: defaultData,\n autosaves = true,\n migrations = []\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n let story: Story;\n let times = new Set<number>();\n\n /**\n * Prevent `undefined`\n */\n defaultData ||= {} as DataScheme;\n defaultState ||= {} as StateScheme;\n\n /**\n * Saves timestamps created in this session\n */\n const intime = (value: number) => {\n return times.add(value), value;\n }\n\n const withStory = (s: Story) => {\n /**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\n story = Object.fromEntries(Object.entries(s).map(([name, items]) => {\n const flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n return item.flatMap((data) => {\n const type = data[0];\n\n /**\n * This is not just an action like `['name', ...arguments]`, but an array of actions\n */\n if (Array.isArray(type)) return flat(data as ValidAction[]);\n\n return [data as ValidAction];\n });\n };\n\n return [name, flat(items)];\n }));\n\n /**\n * When `initialScreen` is not a game, we can safely show it\n */\n if (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n }\n\n const action = new Proxy({} as ActionProxyProvider<Characters>, {\n get(_, prop) {\n return (...props: Parameters<ActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]>) => {\n return [prop, ...props];\n }\n }\n });\n\n function state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n function state(): StateScheme;\n function state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n if (!value) return stack.value[1] as StateScheme | void;\n\n const prev = stack.value[1];\n const val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n stack.value[1] = val as StateScheme;\n }\n\n const getDefaultSave = (state = {}) => {\n return [[[null, 'start'], [null, 0]], state, [intime(Date.now()), 'auto']] as Save;\n }\n\n const createStack = (current: Save, stack = [current]) => {\n return {\n get value() {\n return stack.at(-1)!;\n },\n set value(value: Save) {\n stack[stack.length - 1] = value;\n },\n back() {\n if (stack.length > 1) stack.pop(), goingBack = true;\n },\n push(value: Save) {\n stack.push(value);\n },\n clear() {\n stack = [getDefaultSave(klona(defaultState))];\n }\n }\n }\n\n /**\n * 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 * 2) Actual stored data is loaded, language and etc is changed \n */\n const initialData: StorageData = {\n saves: [],\n data: klona(defaultData) as Data,\n meta: [getLanguage(languages), getTypewriterSpeed()],\n };\n\n const $ = store(initialData);\n\n let initialDataLoaded = false;\n\n const onStorageDataChange = (value: StorageData) => {\n if (initialDataLoaded) storage.set(value);\n };\n\n const throttledOnStorageDataChange = throttle(onStorageDataChange, 120);\n\n $.subscribe(throttledOnStorageDataChange);\n\n const getStoredData = () => {\n storage.get().then(stored => {\n /**\n * Migration is done only once (when game loads it's data), and then it saves the updated format\n */\n for (const migration of migrations) {\n // @ts-expect-error Types does not match between versions\n stored = migration(stored);\n }\n\n /**\n * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n */\n stored.meta[0] ||= getLanguage(languages);\n stored.meta[1] ||= getTypewriterSpeed();\n\n /**\n * When data is empty replace it with `defaultData`\n * It also might be empty (default to empty)\n */\n if (isEmpty(stored.data)) {\n stored.data = defaultData as Data;\n }\n\n /**\n * Now the next store updates will entail saving via storage.set\n */\n initialDataLoaded = true;\n\n $.update(() => stored);\n\n /**\n * When initialScreen is game, then we will load it, but after the data is loaded\n */\n if (initialScreen === 'game') restore();\n });\n }\n\n /**\n * By default this is resolved immediately, but also can be delayed.\n * I.e. storage has not loaded yet\n */\n storageDelay.then(getStoredData)\n\n const initial = getDefaultSave(klona(defaultState));\n const stack = createStack(initial);\n\n const save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n if (!initialDataLoaded) return;\n\n /**\n * When autosaves diabled just return\n */\n if (!autosaves && type === 'auto') return;\n\n const current = klona(stack.value);\n\n $.update(prev => {\n /**\n * Find latest save that were created in current session, and check if it is latest in an array\n * \n * We check if save was created in current session and it is latest in array\n * When it is not then replacing it will break logical chain\n * \n * [auto save 1]\n * [manual save 1]\n * [auto save 2] <- should not replace first auto save \n */\n const isLatest = findLastIndex(prev.saves, value => times.has(value[2][0])) === prev.saves.length - 1;\n\n /**\n * Update type and time information\n */\n current[2][0] = intime(Date.now());\n current[2][1] = type;\n\n if (!override || !isLatest) {\n prev.saves.push(current);\n\n return prev;\n }\n\n /**\n * Get latest\n */\n const latest = prev.saves.at(-1);\n\n /**\n * When that save is the same type, replace it\n */\n if (latest && latest[2][1] === type) {\n prev.saves[prev.saves.length - 1] = current;\n } else {\n prev.saves.push(current);\n }\n\n return prev;\n });\n }\n\n const newGame = () => {\n if (!initialDataLoaded) return;\n\n const save = getDefaultSave(klona(defaultState));\n\n /**\n * Initial save is automatic, and should be ignored when autosaves is turned off\n */\n if (autosaves) {\n $.update(prev => {\n return prev.saves.push(save), prev;\n });\n }\n\n restore(save);\n }\n\n /**\n * Set's the save\n */\n const set = (save: Save) => {\n stack.value = save;\n\n return restore(save);\n }\n\n let restoring = false;\n let goingBack = false;\n let interacted = false;\n\n /**\n * Restore\n */\n const restore = async (save?: Save) => {\n if (!initialDataLoaded) return;\n\n let latest = save ? save : $.get().saves.at(-1);\n\n /**\n * When there is no game, then make a new game\n */\n if (!latest) {\n $.update(() => ({ saves: [initial], data: klona(defaultData) as Data, meta: [getLanguage(languages), getTypewriterSpeed()] }));\n\n latest = klona(initial);\n }\n\n restoring = true, stack.value = latest;\n\n /**\n * Текущий элемент в истории\n */\n let current: any = story;\n /**\n * Текущий элемент `[null, int]`\n */\n let index = 0;\n\n /**\n * Число элементов `[null, int]`\n */\n const max = stack.value[0].reduce((acc, [type, val]) => {\n if (isNull(type) && isNumber(val)) return acc + 1;\n\n return acc;\n }, 0);\n\n const queue = [] as [any, any][];\n const keep = new Set();\n const characters = new Set();\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n if (isString(val)) {\n current = current[val];\n } else if (isNumber(val)) {\n index++;\n\n /**\n * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n */\n for (let i = 0; i <= val; i++) {\n const [action, ...meta] = current[i];\n\n /**\n * Add item to queue and action to keep\n */\n const push = () => {\n keep.add(action);\n queue.push([action, meta]);\n }\n\n /**\n * Do not remove characters that will be here anyways\n */\n if (action === 'showCharacter') characters.add(meta[0]);\n\n /**\n * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n */\n if (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n if (index === max && i === val) {\n push();\n } else {\n continue;\n }\n }\n\n push();\n }\n\n current = current[val];\n }\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n queue.forEach((value, index) => {\n /**\n * Mutate the queue item\n */\n value.push(index);\n });\n\n /**\n * This is basically made for TypeScript.\n */\n const indexedQueue = queue as unknown as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number][];\n\n /**\n * Run these exactly before the main loop.\n */\n renderer.ui.showScreen('game');\n /**\n * Provide the `keep` in there\n */\n match('clear', [keep, characters]);\n\n /**\n * Get the next actions array.\n */\n const next = (i: number) => indexedQueue.slice(i + 1);\n\n for await (const [action, meta, i] of indexedQueue) {\n if (action === 'function' || action === 'custom') {\n /**\n * When `callOnlyLatest` is `true`\n */\n if (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n /**\n * We'll calculate it is `latest` or not\n */\n const notLatest = next(i).some(([_action, _meta]) => {\n if (!_meta || !meta) return false;\n\n const c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n const c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n /**\n * Also check for `undefined`\n */\n const isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n \n /**\n * Equal by id or equal by `toString()`\n */\n return isIdenticalID || (str(c0) === str(c1));\n });\n\n if (notLatest) continue;\n }\n\n /**\n * Action can return Promise. \n */\n const result = match(action, meta);\n\n /**\n * Should wait until it resolved\n */\n if (isPromise(result)) {\n /**\n * Await it!\n */\n await result;\n }\n } else if (action === 'showCharacter') {\n const skip = next(i).some(([_action, _meta]) => {\n /**\n * Проверка на возможный `undefined`\n */\n if (!_meta || !meta) return false;\n\n /**\n * Будет ли персонаж скрыт в будущем\n * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n */\n const hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n /**\n * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n */\n const notLatest = _action === action && _meta[0] === meta[0];\n\n return hidden || notLatest;\n })\n\n if (skip) continue;\n\n match(action, meta);\n } else if (action === 'showBackground' || action === 'animateCharacter') {\n /**\n * Такая же оптимизация применяется к фонам и анимированию персонажей.\n * Если фон изменится, то нет смысла устанавливать текущий\n */\n const notLatest = next(i).some(([_action]) => action === _action);\n\n if (notLatest) continue;\n\n match(action, meta);\n } else {\n match(action, meta);\n }\n }\n\n restoring = goingBack = false, render();\n }\n\n const refer = () => {\n let current: any = story;\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n current = current[val];\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n return current;\n }\n\n const exit = () => {\n const current = stack.value;\n\n stack.clear();\n renderer.ui.showScreen('mainmenu');\n\n /**\n * First two save elements and it's type\n */\n const [[first, second], , [time, type]] = current;\n\n if (type === 'auto' && first && second) {\n /**\n * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n */\n if (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n $.update((prev) => {\n prev.saves = prev.saves.filter(save => save !== current);\n\n return prev;\n })\n }\n }\n\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n }\n\n const back = () => {\n return stack.back(), restore(stack.value);\n }\n\n const renderer = createRenderer({\n characters,\n set,\n restore,\n save,\n newGame,\n exit,\n back,\n stack,\n languages,\n t: t9n.i,\n $\n });\n\n const match = matchAction({\n wait([time]) {\n if (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n },\n showBackground([background]) {\n renderer.background(background);\n push()\n },\n playMusic([source]) {\n renderer.music(source, 'music').play();\n push()\n },\n stopMusic([source]) {\n renderer.music(source, 'music').stop();\n push()\n },\n showCharacter([character, emotion, className, style]) {\n const handle = renderer.character(character);\n\n handle.append(className, style, restoring);\n handle.withEmotion(emotion)();\n\n push()\n },\n hideCharacter([character, className, style, duration]) {\n renderer.character(character).remove(className, style, duration)(push, restoring);\n },\n dialog([character, content, emotion]) {\n /**\n * Person name\n */\n const name = (() => {\n const c = character, cs = characters;\n const lang = $.get().meta[0];\n\n return c ? c in cs ? typeof cs[c].name === 'string' ? cs[c].name as string : (cs[c].name as Record<string, string>)[lang] : c : '';\n })();\n\n renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n },\n function([fn]) {\n const result = fn(restoring, goingBack);\n\n if (!restoring) result ? result.then(push) : push();\n\n return result;\n },\n choice([question, ...choices]) {\n const isWithoutQuestion = Array.isArray(question);\n\n if (isWithoutQuestion) {\n /**\n * Первый элемент может быть как строкой, так и элементов выбора\n */\n choices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n /**\n * Значит, текст не требуется\n */\n question = '';\n }\n\n const unwrapped = choices.map(([content, action, visible]) => {\n return [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n });\n\n renderer.choices(unwrap(question), unwrapped)((selected) => {\n enmemory();\n\n /**\n * If there is a question, then `index` should be shifted by `1`\n */\n const offset = isWithoutQuestion ? 0 : 1;\n\n stack.value[0].push(['choice', selected + offset], [null, 0]);\n render();\n interactivity(true);\n });\n },\n jump([scene]) {\n /**\n * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n */\n stack.value[0] = [[null, scene], [null, -1]];\n\n match('clear', []);\n },\n clear([keep, characters]) {\n /**\n * Remove vibration\n */\n vibrate(0);\n /**\n * Call the actual `clear`\n */\n renderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n },\n condition([condition]) {\n const value = condition();\n\n if (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n },\n end() {\n /**\n * Clear the Scene\n */\n match('clear', []);\n /**\n * Go to the main menu\n */\n renderer.ui.showScreen('mainmenu');\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n },\n input([question, onInput, setup]) {\n renderer.input(unwrap(question), onInput, setup)(forward);\n },\n custom([handler]) {\n const result = renderer.custom(handler, goingBack, () => {\n if (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n if (!restoring) push();\n });\n\n return result;\n },\n vibrate(pattern) {\n vibrate(pattern);\n push()\n },\n next() {\n push();\n },\n animateCharacter([character, timeout, ...classes]) {\n const handler: CustomHandler = (get) => {\n const { clear } = get('@@internal-animate-character', false);\n const char = renderer.store.characters[character];\n\n /**\n * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n */\n if (!char) return;\n\n const target = char.canvas;\n\n /**\n * Character is not found\n */\n if (!target) return;\n\n const classNames = classes.filter(className => !target.classList.contains(className));\n\n target.classList.add(...classNames);\n\n const timeoutId = setTimeout(() => {\n target.classList.remove(...classNames);\n }, timeout);\n\n clear(() => {\n target.classList.remove(...classNames);\n \n /**\n * Clear timeout, because when you will game re-runs some callback might remove classes from character\n */\n clearTimeout(timeoutId);\n });\n }\n\n /**\n * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n */\n match('custom', [handler]);\n },\n text(text) {\n renderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n },\n exit() {\n const path = stack.value[0];\n\n for (let i = path.length - 1; i > 0; i--) {\n if (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n stack.value[0] = path.slice(0, i);\n next();\n\n break;\n }\n\n render();\n }\n });\n\n const enmemory = () => {\n if (restoring) return;\n\n const current = klona(stack.value);\n\n current[2][1] = 'auto';\n\n stack.push(current);\n\n save(true, 'auto');\n }\n\n const next = () => {\n const path = stack.value[0];\n /**\n * Последний элемент пути\n */\n const last = path[path.length - 1]!;\n\n /**\n * Если он вида `[null, int]` - увеличивает `int`\n */\n if (isNull(last[0]) && isNumber(last[1])) {\n last[1] = last[1] + 1;\n return;\n }\n\n /**\n * Иначе добавляет новое `[null int]`\n */\n path.push([null, 0]);\n }\n\n const render = () => {\n const referred = refer();\n\n if (!Array.isArray(referred)) return;\n\n const [action, ...props] = referred;\n\n match(action, props);\n }\n\n const push = () => {\n if (!restoring) next(), render();\n }\n\n const forward = () => {\n enmemory();\n push();\n interactivity(true)\n }\n\n const interactivity = (value = false) => {\n interacted = value;\n }\n\n /**\n * Unwraps translatable content to string\n * \n * @example ```\n * unwrap(t('Hello'));\n * unwrap({ en: 'Hello', ru: 'Привет' });\n * unwrap('Hello, {{name}}');\n * ```\n */\n const unwrap = (content: Unwrappable, global = false) => {\n const { data, meta: [lang] } = $.get();\n\n const obj = global ? data : state();\n const str = isFunction(content)\n ? content(lang, obj)\n : typeof content === 'object'\n ? content[lang]\n : content;\n \n return replaceT9N(str, obj);\n }\n\n function data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n function data(): DataScheme;\n function data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n if (!value) return $.get().data as DataScheme | void;\n\n const prev = $.get().data;\n const val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n $.update((prev) => {\n prev.data = val;\n\n return prev;\n });\n }\n\n return {\n /**\n * Function to set story\n */\n withStory,\n /**\n * Function to get actions\n */\n action,\n /**\n * State that belongs to games\n */\n state,\n /**\n * Unlike `state`, stored at global scope instead and shared between games\n */\n data,\n /**\n * Unwraps translatable content to a string value\n */\n unwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n return unwrap(content, true);\n },\n /**\n * Function that is used for translation\n */\n t: t9n.t as Inter['t'],\n }\n}\n\nexport { novely }\n","const SKIPPED_DURING_RESTORE = new Set([\n 'dialog',\n 'choice',\n 'input',\n 'vibrate',\n 'text'\n] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET }","import type { StorageData } from './types'\n\ninterface LocalStorageStorageSettings {\n key: string\n}\n\ninterface Storage {\n get: () => Promise<StorageData>;\n set: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n return {\n async get() {\n const value = localStorage.getItem(options.key);\n\n return value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n },\n async set(data) {\n localStorage.setItem(options.key, JSON.stringify(data));\n }\n }\n}\n\nexport type { Storage }\nexport { localStorageStorage }"],"mappings":"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","names":["data","state","stack","save","characters","action","push","index","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.4.3",
4
+ "version": "0.5.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "publishConfig": {