@react-text-game/core 0.1.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.
Files changed (178) hide show
  1. package/README.md +744 -0
  2. package/dist/baseGameObject.d.ts +90 -0
  3. package/dist/baseGameObject.d.ts.map +1 -0
  4. package/dist/baseGameObject.js +109 -0
  5. package/dist/baseGameObject.js.map +1 -0
  6. package/dist/constants.d.ts +12 -0
  7. package/dist/constants.d.ts.map +1 -0
  8. package/dist/constants.js +12 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/game.d.ts +294 -0
  11. package/dist/game.d.ts.map +1 -0
  12. package/dist/game.js +489 -0
  13. package/dist/game.js.map +1 -0
  14. package/dist/helpers.d.ts +2 -0
  15. package/dist/helpers.d.ts.map +1 -0
  16. package/dist/helpers.js +6 -0
  17. package/dist/helpers.js.map +1 -0
  18. package/dist/hooks/index.d.ts +4 -0
  19. package/dist/hooks/index.d.ts.map +1 -0
  20. package/dist/hooks/index.js +4 -0
  21. package/dist/hooks/index.js.map +1 -0
  22. package/dist/hooks/useCurrentPassage.d.ts +10 -0
  23. package/dist/hooks/useCurrentPassage.d.ts.map +1 -0
  24. package/dist/hooks/useCurrentPassage.js +17 -0
  25. package/dist/hooks/useCurrentPassage.js.map +1 -0
  26. package/dist/hooks/useGameEntity.d.ts +21 -0
  27. package/dist/hooks/useGameEntity.d.ts.map +1 -0
  28. package/dist/hooks/useGameEntity.js +70 -0
  29. package/dist/hooks/useGameEntity.js.map +1 -0
  30. package/dist/hooks/useGameIsStarted.d.ts +12 -0
  31. package/dist/hooks/useGameIsStarted.d.ts.map +1 -0
  32. package/dist/hooks/useGameIsStarted.js +18 -0
  33. package/dist/hooks/useGameIsStarted.js.map +1 -0
  34. package/dist/index.d.ts +12 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +10 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/logger.d.ts +8 -0
  39. package/dist/logger.d.ts.map +1 -0
  40. package/dist/logger.js +36 -0
  41. package/dist/logger.js.map +1 -0
  42. package/dist/options.d.ts +13 -0
  43. package/dist/options.d.ts.map +1 -0
  44. package/dist/options.js +15 -0
  45. package/dist/options.js.map +1 -0
  46. package/dist/passages/interactiveMap/fabric.d.ts +4 -0
  47. package/dist/passages/interactiveMap/fabric.d.ts.map +1 -0
  48. package/dist/passages/interactiveMap/fabric.js +3 -0
  49. package/dist/passages/interactiveMap/fabric.js.map +1 -0
  50. package/dist/passages/interactiveMap/index.d.ts +4 -0
  51. package/dist/passages/interactiveMap/index.d.ts.map +1 -0
  52. package/dist/passages/interactiveMap/index.js +4 -0
  53. package/dist/passages/interactiveMap/index.js.map +1 -0
  54. package/dist/passages/interactiveMap/interactiveMap.d.ts +89 -0
  55. package/dist/passages/interactiveMap/interactiveMap.d.ts.map +1 -0
  56. package/dist/passages/interactiveMap/interactiveMap.js +103 -0
  57. package/dist/passages/interactiveMap/interactiveMap.js.map +1 -0
  58. package/dist/passages/interactiveMap/types.d.ts +822 -0
  59. package/dist/passages/interactiveMap/types.d.ts.map +1 -0
  60. package/dist/passages/interactiveMap/types.js +2 -0
  61. package/dist/passages/interactiveMap/types.js.map +1 -0
  62. package/dist/passages/passage.d.ts +57 -0
  63. package/dist/passages/passage.d.ts.map +1 -0
  64. package/dist/passages/passage.js +64 -0
  65. package/dist/passages/passage.js.map +1 -0
  66. package/dist/passages/story/fabric.d.ts +4 -0
  67. package/dist/passages/story/fabric.d.ts.map +1 -0
  68. package/dist/passages/story/fabric.js +3 -0
  69. package/dist/passages/story/fabric.js.map +1 -0
  70. package/dist/passages/story/index.d.ts +5 -0
  71. package/dist/passages/story/index.d.ts.map +1 -0
  72. package/dist/passages/story/index.js +5 -0
  73. package/dist/passages/story/index.js.map +1 -0
  74. package/dist/passages/story/start.d.ts +14 -0
  75. package/dist/passages/story/start.d.ts.map +1 -0
  76. package/dist/passages/story/start.js +22 -0
  77. package/dist/passages/story/start.js.map +1 -0
  78. package/dist/passages/story/story.d.ts +84 -0
  79. package/dist/passages/story/story.d.ts.map +1 -0
  80. package/dist/passages/story/story.js +88 -0
  81. package/dist/passages/story/story.js.map +1 -0
  82. package/dist/passages/story/types.d.ts +911 -0
  83. package/dist/passages/story/types.d.ts.map +1 -0
  84. package/dist/passages/story/types.js +2 -0
  85. package/dist/passages/story/types.js.map +1 -0
  86. package/dist/passages/types/index.d.ts +3 -0
  87. package/dist/passages/types/index.d.ts.map +1 -0
  88. package/dist/passages/types/index.js +2 -0
  89. package/dist/passages/types/index.js.map +1 -0
  90. package/dist/passages/widget.d.ts +62 -0
  91. package/dist/passages/widget.d.ts.map +1 -0
  92. package/dist/passages/widget.js +66 -0
  93. package/dist/passages/widget.js.map +1 -0
  94. package/dist/saves/constants.d.ts +17 -0
  95. package/dist/saves/constants.d.ts.map +1 -0
  96. package/dist/saves/constants.js +17 -0
  97. package/dist/saves/constants.js.map +1 -0
  98. package/dist/saves/db.d.ts +119 -0
  99. package/dist/saves/db.d.ts.map +1 -0
  100. package/dist/saves/db.js +231 -0
  101. package/dist/saves/db.js.map +1 -0
  102. package/dist/saves/helpers.d.ts +28 -0
  103. package/dist/saves/helpers.d.ts.map +1 -0
  104. package/dist/saves/helpers.js +84 -0
  105. package/dist/saves/helpers.js.map +1 -0
  106. package/dist/saves/hooks/index.d.ts +10 -0
  107. package/dist/saves/hooks/index.d.ts.map +1 -0
  108. package/dist/saves/hooks/index.js +10 -0
  109. package/dist/saves/hooks/index.js.map +1 -0
  110. package/dist/saves/hooks/useDeleteAllSlots.d.ts +18 -0
  111. package/dist/saves/hooks/useDeleteAllSlots.d.ts.map +1 -0
  112. package/dist/saves/hooks/useDeleteAllSlots.js +18 -0
  113. package/dist/saves/hooks/useDeleteAllSlots.js.map +1 -0
  114. package/dist/saves/hooks/useDeleteGame.d.ts +22 -0
  115. package/dist/saves/hooks/useDeleteGame.d.ts.map +1 -0
  116. package/dist/saves/hooks/useDeleteGame.js +33 -0
  117. package/dist/saves/hooks/useDeleteGame.js.map +1 -0
  118. package/dist/saves/hooks/useExportSaves.d.ts +27 -0
  119. package/dist/saves/hooks/useExportSaves.d.ts.map +1 -0
  120. package/dist/saves/hooks/useExportSaves.js +54 -0
  121. package/dist/saves/hooks/useExportSaves.js.map +1 -0
  122. package/dist/saves/hooks/useImportSaves.d.ts +29 -0
  123. package/dist/saves/hooks/useImportSaves.d.ts.map +1 -0
  124. package/dist/saves/hooks/useImportSaves.js +108 -0
  125. package/dist/saves/hooks/useImportSaves.js.map +1 -0
  126. package/dist/saves/hooks/useLastLoadGame.d.ts +39 -0
  127. package/dist/saves/hooks/useLastLoadGame.d.ts.map +1 -0
  128. package/dist/saves/hooks/useLastLoadGame.js +72 -0
  129. package/dist/saves/hooks/useLastLoadGame.js.map +1 -0
  130. package/dist/saves/hooks/useLoadGame.d.ts +22 -0
  131. package/dist/saves/hooks/useLoadGame.d.ts.map +1 -0
  132. package/dist/saves/hooks/useLoadGame.js +40 -0
  133. package/dist/saves/hooks/useLoadGame.js.map +1 -0
  134. package/dist/saves/hooks/useRestartGame.d.ts +20 -0
  135. package/dist/saves/hooks/useRestartGame.d.ts.map +1 -0
  136. package/dist/saves/hooks/useRestartGame.js +29 -0
  137. package/dist/saves/hooks/useRestartGame.js.map +1 -0
  138. package/dist/saves/hooks/useSaveGame.d.ts +22 -0
  139. package/dist/saves/hooks/useSaveGame.d.ts.map +1 -0
  140. package/dist/saves/hooks/useSaveGame.js +34 -0
  141. package/dist/saves/hooks/useSaveGame.js.map +1 -0
  142. package/dist/saves/hooks/useSaveSlots.d.ts +45 -0
  143. package/dist/saves/hooks/useSaveSlots.d.ts.map +1 -0
  144. package/dist/saves/hooks/useSaveSlots.js +42 -0
  145. package/dist/saves/hooks/useSaveSlots.js.map +1 -0
  146. package/dist/saves/index.d.ts +4 -0
  147. package/dist/saves/index.d.ts.map +1 -0
  148. package/dist/saves/index.js +3 -0
  149. package/dist/saves/index.js.map +1 -0
  150. package/dist/saves/types.d.ts +52 -0
  151. package/dist/saves/types.d.ts.map +1 -0
  152. package/dist/saves/types.js +2 -0
  153. package/dist/saves/types.js.map +1 -0
  154. package/dist/storage.d.ts +124 -0
  155. package/dist/storage.d.ts.map +1 -0
  156. package/dist/storage.js +229 -0
  157. package/dist/storage.js.map +1 -0
  158. package/dist/tests/game.test.d.ts +2 -0
  159. package/dist/tests/game.test.d.ts.map +1 -0
  160. package/dist/tests/game.test.js +602 -0
  161. package/dist/tests/game.test.js.map +1 -0
  162. package/dist/tests/interactiveMap.test.d.ts +2 -0
  163. package/dist/tests/interactiveMap.test.d.ts.map +1 -0
  164. package/dist/tests/interactiveMap.test.js +1003 -0
  165. package/dist/tests/interactiveMap.test.js.map +1 -0
  166. package/dist/tests/storage.test.d.ts +2 -0
  167. package/dist/tests/storage.test.d.ts.map +1 -0
  168. package/dist/tests/storage.test.js +328 -0
  169. package/dist/tests/storage.test.js.map +1 -0
  170. package/dist/tests/story.test.d.ts +2 -0
  171. package/dist/tests/story.test.d.ts.map +1 -0
  172. package/dist/tests/story.test.js +698 -0
  173. package/dist/tests/story.test.js.map +1 -0
  174. package/dist/types.d.ts +19 -0
  175. package/dist/types.d.ts.map +1 -0
  176. package/dist/types.js +2 -0
  177. package/dist/types.js.map +1 -0
  178. package/package.json +60 -0
@@ -0,0 +1,84 @@
1
+ import CryptoJS from "crypto-js";
2
+ import { _getOptions } from "../options";
3
+ import { ITERATIONS, KEY_SIZE, SAVE_POSTFIX } from "./constants";
4
+ /**
5
+ * Generates the encryption password by combining game ID with save postfix
6
+ * @returns Password string for encryption/decryption
7
+ */
8
+ const getPassword = () => `${_getOptions().gameId}.${SAVE_POSTFIX}`;
9
+ /**
10
+ * Encodes (encrypts) data using AES encryption with PBKDF2 key derivation.
11
+ * The output is a byte array that can be saved to a file.
12
+ *
13
+ * @template T - Type of data to encode
14
+ * @param data - Data to encrypt
15
+ * @returns Uint8Array containing encrypted data with salt and IV prepended
16
+ */
17
+ export const encodeSf = (data) => {
18
+ const salt = CryptoJS.lib.WordArray.random(128 / 8);
19
+ const key = CryptoJS.PBKDF2(getPassword(), salt, {
20
+ keySize: KEY_SIZE,
21
+ iterations: ITERATIONS,
22
+ });
23
+ const iv = CryptoJS.lib.WordArray.random(128 / 8);
24
+ const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), key, {
25
+ iv: iv,
26
+ padding: CryptoJS.pad.Pkcs7,
27
+ mode: CryptoJS.mode.CBC,
28
+ });
29
+ const transitMessage = salt.toString(CryptoJS.enc.Base64) +
30
+ iv.toString(CryptoJS.enc.Base64) +
31
+ encrypted.toString();
32
+ return new TextEncoder().encode(transitMessage);
33
+ };
34
+ /**
35
+ * Decodes (decrypts) data that was encrypted using encodeSf.
36
+ * Extracts salt and IV from the encrypted data and uses them to decrypt.
37
+ *
38
+ * @template T - Expected type of the decrypted data
39
+ * @param data - ArrayBuffer containing encrypted data
40
+ * @returns Decrypted data of type T
41
+ * @throws Error if decryption fails (corrupted data or password mismatch)
42
+ */
43
+ export const decodeSf = (data) => {
44
+ const transitMessage = new TextDecoder().decode(data);
45
+ const saltString = transitMessage.substring(0, 24);
46
+ const ivString = transitMessage.substring(24, 48);
47
+ const encryptedString = transitMessage.substring(48);
48
+ const salt = CryptoJS.enc.Base64.parse(saltString);
49
+ const iv = CryptoJS.enc.Base64.parse(ivString);
50
+ const key = CryptoJS.PBKDF2(getPassword(), salt, {
51
+ keySize: KEY_SIZE,
52
+ iterations: ITERATIONS,
53
+ });
54
+ const decrypted = CryptoJS.AES.decrypt(encryptedString, key, {
55
+ iv: iv,
56
+ padding: CryptoJS.pad.Pkcs7,
57
+ mode: CryptoJS.mode.CBC,
58
+ });
59
+ const jsonString = decrypted.toString(CryptoJS.enc.Utf8);
60
+ if (!jsonString) {
61
+ throw new Error("Failed to decrypt. Data might be corrupted or the password/logic has changed.");
62
+ }
63
+ return JSON.parse(jsonString);
64
+ };
65
+ /**
66
+ * Formats a Date object into a human-readable string.
67
+ * Format: "DD of MONTH, YYYY HH:MM" (24-hour format)
68
+ *
69
+ * @param timestamp - Date to format
70
+ * @returns Formatted date string (e.g., "15 of January, 2025 14:30")
71
+ */
72
+ export const getDateString = (timestamp) => {
73
+ const date = new Date(timestamp);
74
+ const day = date.getDate();
75
+ const month = date.toLocaleString("default", { month: "long" });
76
+ const year = date.getFullYear();
77
+ const time = date.toLocaleTimeString("default", {
78
+ hour: "2-digit",
79
+ minute: "2-digit",
80
+ hour12: false,
81
+ });
82
+ return `${day} of ${month}, ${year} ${time}`;
83
+ };
84
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/saves/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export * from "./useDeleteAllSlots";
2
+ export * from "./useDeleteGame";
3
+ export * from "./useExportSaves";
4
+ export * from "./useImportSaves";
5
+ export * from "./useLastLoadGame";
6
+ export * from "./useLoadGame";
7
+ export * from "./useRestartGame";
8
+ export * from "./useSaveGame";
9
+ export * from "./useSaveSlots";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export * from "./useDeleteAllSlots";
2
+ export * from "./useDeleteGame";
3
+ export * from "./useExportSaves";
4
+ export * from "./useImportSaves";
5
+ export * from "./useLastLoadGame";
6
+ export * from "./useLoadGame";
7
+ export * from "./useRestartGame";
8
+ export * from "./useSaveGame";
9
+ export * from "./useSaveSlots";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/saves/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { deleteAllGameSaves } from "../../saves";
2
+ /**
3
+ * React hook that provides a function to delete all game saves.
4
+ * This function clears all saved game data from the database.
5
+ *
6
+ * @returns Callback function that deletes all game saves
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const deleteAllSaves = useDeleteAllSaves();
11
+ * const handleDeleteAll = async () => {
12
+ * await deleteAllSaves();
13
+ * console.log('All game saves have been deleted.');
14
+ * };
15
+ * ```
16
+ */
17
+ export declare const useDeleteAllSaves: () => typeof deleteAllGameSaves;
18
+ //# sourceMappingURL=useDeleteAllSlots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeleteAllSlots.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useDeleteAllSlots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE5C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,iCAA2B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { deleteAllGameSaves } from "../../saves";
2
+ /**
3
+ * React hook that provides a function to delete all game saves.
4
+ * This function clears all saved game data from the database.
5
+ *
6
+ * @returns Callback function that deletes all game saves
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const deleteAllSaves = useDeleteAllSaves();
11
+ * const handleDeleteAll = async () => {
12
+ * await deleteAllSaves();
13
+ * console.log('All game saves have been deleted.');
14
+ * };
15
+ * ```
16
+ */
17
+ export const useDeleteAllSaves = () => deleteAllGameSaves;
18
+ //# sourceMappingURL=useDeleteAllSlots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeleteAllSlots.js","sourceRoot":"","sources":["../../../src/saves/hooks/useDeleteAllSlots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE5C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,kBAAkB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * React hook that provides a function to delete a saved game by its ID.
3
+ * Removes the save from IndexedDB storage.
4
+ *
5
+ * @returns Function that accepts a save ID and deletes the game, returning a result object on failure
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const deleteGame = useDeleteGame();
10
+ * const handleDelete = async () => {
11
+ * const result = await deleteGame(saveId);
12
+ * if (result?.success === false) {
13
+ * console.error('Delete failed:', result.message);
14
+ * }
15
+ * };
16
+ * ```
17
+ */
18
+ export declare const useDeleteGame: () => (id: number) => Promise<{
19
+ success: boolean;
20
+ message: string;
21
+ } | undefined>;
22
+ //# sourceMappingURL=useDeleteGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeleteGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useDeleteGame.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,SAAgB,IAAI,MAAM;;;cAYnD,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { logger } from "../../logger";
2
+ import { deleteSave } from "../../saves";
3
+ /**
4
+ * React hook that provides a function to delete a saved game by its ID.
5
+ * Removes the save from IndexedDB storage.
6
+ *
7
+ * @returns Function that accepts a save ID and deletes the game, returning a result object on failure
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const deleteGame = useDeleteGame();
12
+ * const handleDelete = async () => {
13
+ * const result = await deleteGame(saveId);
14
+ * if (result?.success === false) {
15
+ * console.error('Delete failed:', result.message);
16
+ * }
17
+ * };
18
+ * ```
19
+ */
20
+ export const useDeleteGame = () => async (id) => {
21
+ try {
22
+ await deleteSave(id);
23
+ }
24
+ catch (e) {
25
+ logger.error("Failed to delete save:", e);
26
+ return {
27
+ success: false,
28
+ message: e.message ||
29
+ "Failed to delete save. Check console for more info.",
30
+ };
31
+ }
32
+ };
33
+ //# sourceMappingURL=useDeleteGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeleteGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useDeleteGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;IACpD,IAAI,CAAC;QACD,MAAM,UAAU,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EACF,CAAW,CAAC,OAAO;gBACpB,qDAAqD;SAC5D,CAAC;IACN,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * React hook that provides a function to export all game saves to an encrypted file.
3
+ * The exported file is downloaded with the game name, version, and .sx extension.
4
+ *
5
+ * @returns Callback function that exports saves and returns a result object
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const exportSaves = useExportSaves();
10
+ * const handleExport = async () => {
11
+ * const result = await exportSaves();
12
+ * if (result.success) {
13
+ * console.log('Saves exported successfully');
14
+ * } else {
15
+ * console.error('Export failed:', result.error);
16
+ * }
17
+ * };
18
+ * ```
19
+ */
20
+ export declare const useExportSaves: () => () => Promise<{
21
+ success: boolean;
22
+ error: string;
23
+ } | {
24
+ success: boolean;
25
+ error: null;
26
+ }>;
27
+ //# sourceMappingURL=useExportSaves.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useExportSaves.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useExportSaves.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc;;;;;;EA+B1B,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { useCallback } from "react";
2
+ import { _getOptions } from "../../options";
3
+ import { SAFE_FILE_EXTENSION } from "../../saves/constants";
4
+ import { getAllSaves } from "../../saves/db";
5
+ import { encodeSf } from "../../saves/helpers";
6
+ /**
7
+ * React hook that provides a function to export all game saves to an encrypted file.
8
+ * The exported file is downloaded with the game name, version, and .sx extension.
9
+ *
10
+ * @returns Callback function that exports saves and returns a result object
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const exportSaves = useExportSaves();
15
+ * const handleExport = async () => {
16
+ * const result = await exportSaves();
17
+ * if (result.success) {
18
+ * console.log('Saves exported successfully');
19
+ * } else {
20
+ * console.error('Export failed:', result.error);
21
+ * }
22
+ * };
23
+ * ```
24
+ */
25
+ export const useExportSaves = () => {
26
+ return useCallback(async () => {
27
+ const options = _getOptions();
28
+ const allSaves = await getAllSaves();
29
+ if (allSaves.length === 0) {
30
+ return { success: false, error: "No saves found" };
31
+ }
32
+ try {
33
+ const data = encodeSf(allSaves);
34
+ const blob = new Blob([data], { type: "application/octet-stream" });
35
+ const url = URL.createObjectURL(blob);
36
+ const a = document.createElement("a");
37
+ a.href = url;
38
+ a.download = `${options.gameName}-${options.gameVersion}${SAFE_FILE_EXTENSION}`;
39
+ a.click();
40
+ a.remove();
41
+ URL.revokeObjectURL(url);
42
+ return { success: true, error: null };
43
+ }
44
+ catch (e) {
45
+ console.error(e);
46
+ return {
47
+ success: false,
48
+ error: e.message ||
49
+ "Unknown error, check console for more info",
50
+ };
51
+ }
52
+ }, []);
53
+ };
54
+ //# sourceMappingURL=useExportSaves.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useExportSaves.js","sourceRoot":"","sources":["../../../src/saves/hooks/useExportSaves.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IAC/B,OAAO,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;QAE9B,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACpE,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;YACtC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;YACb,CAAC,CAAC,QAAQ,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,WAAW,GAAG,mBAAmB,EAAE,CAAC;YAChF,CAAC,CAAC,KAAK,EAAE,CAAC;YACV,CAAC,CAAC,MAAM,EAAE,CAAC;YACX,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAEzB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjB,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EACA,CAAW,CAAC,OAAO;oBACpB,4CAA4C;aACnD,CAAC;QACN,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * React hook that provides a function to import game saves from an encrypted file.
3
+ * Opens a file picker, decrypts the selected file, and replaces all existing saves.
4
+ *
5
+ * @returns Callback function that imports saves and returns a result object with success status, count, and error
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const importSaves = useImportSaves();
10
+ * const handleImport = async () => {
11
+ * const result = await importSaves();
12
+ * if (result.success) {
13
+ * console.log(`Successfully imported ${result.count} saves`);
14
+ * } else {
15
+ * console.error('Import failed:', result.error);
16
+ * }
17
+ * };
18
+ * ```
19
+ */
20
+ export declare const useImportSaves: () => () => Promise<{
21
+ success: boolean;
22
+ count: number;
23
+ error: string;
24
+ } | {
25
+ success: boolean;
26
+ count: number;
27
+ error: null;
28
+ }>;
29
+ //# sourceMappingURL=useImportSaves.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImportSaves.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useImportSaves.ts"],"names":[],"mappings":"AA2BA;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc;;;;;;;;EA+E1B,CAAC"}
@@ -0,0 +1,108 @@
1
+ import { useCallback } from "react";
2
+ import { deleteAllGameSaves, saveGame } from "../../saves";
3
+ import { SAFE_FILE_EXTENSION } from "../../saves/constants";
4
+ import { decodeSf } from "../../saves/helpers";
5
+ /**
6
+ * Helper function to create a file picker and wait for user selection
7
+ * @param input - HTMLInputElement configured as file picker
8
+ * @returns Promise resolving to selected File or null if cancelled
9
+ */
10
+ const createFile = async (input) => new Promise((resolve) => {
11
+ input.onchange = (event) => {
12
+ const target = event.target;
13
+ const selectedFile = target.files?.[0] || null;
14
+ resolve(selectedFile);
15
+ };
16
+ input.oncancel = () => {
17
+ resolve(null);
18
+ };
19
+ // Trigger file explorer
20
+ input.click();
21
+ });
22
+ /**
23
+ * React hook that provides a function to import game saves from an encrypted file.
24
+ * Opens a file picker, decrypts the selected file, and replaces all existing saves.
25
+ *
26
+ * @returns Callback function that imports saves and returns a result object with success status, count, and error
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * const importSaves = useImportSaves();
31
+ * const handleImport = async () => {
32
+ * const result = await importSaves();
33
+ * if (result.success) {
34
+ * console.log(`Successfully imported ${result.count} saves`);
35
+ * } else {
36
+ * console.error('Import failed:', result.error);
37
+ * }
38
+ * };
39
+ * ```
40
+ */
41
+ export const useImportSaves = () => {
42
+ return useCallback(async () => {
43
+ const input = document.createElement("input");
44
+ input.type = "file";
45
+ input.accept = SAFE_FILE_EXTENSION;
46
+ input.multiple = false;
47
+ const file = await createFile(input);
48
+ if (!file) {
49
+ return { success: false, count: 0, error: "No file selected" };
50
+ }
51
+ if (!file.name.endsWith(SAFE_FILE_EXTENSION)) {
52
+ return {
53
+ success: false,
54
+ count: 0,
55
+ error: `Invalid file type. Please select a file with ${SAFE_FILE_EXTENSION} extension.`,
56
+ };
57
+ }
58
+ const arrayBuffer = await file.arrayBuffer();
59
+ let saves = [];
60
+ try {
61
+ saves = decodeSf(arrayBuffer);
62
+ }
63
+ catch (e) {
64
+ console.error(e);
65
+ return {
66
+ success: false,
67
+ count: 0,
68
+ error: e.message ||
69
+ "Failed to decode save file. Check console for more info.",
70
+ };
71
+ }
72
+ if (!saves || !Array.isArray(saves)) {
73
+ return {
74
+ success: false,
75
+ count: 0,
76
+ error: "Invalid save file format",
77
+ };
78
+ }
79
+ try {
80
+ await deleteAllGameSaves();
81
+ }
82
+ catch (e) {
83
+ console.error(e);
84
+ return {
85
+ success: false,
86
+ count: 0,
87
+ error: e.message ||
88
+ "Failed to clear existing saves. Check console for more info.",
89
+ };
90
+ }
91
+ let count = 0;
92
+ for (const save of saves) {
93
+ try {
94
+ await saveGame(save.name, save.gameData, save.description, save.screenshot);
95
+ count++;
96
+ }
97
+ catch (e) {
98
+ console.error(e);
99
+ }
100
+ }
101
+ return {
102
+ success: true,
103
+ count,
104
+ error: null,
105
+ };
106
+ }, []);
107
+ };
108
+ //# sourceMappingURL=useImportSaves.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImportSaves.js","sourceRoot":"","sources":["../../../src/saves/hooks/useImportSaves.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { GameSave } from "../../saves";
2
+ /**
3
+ * A custom hook for managing the loading of the last saved game state.
4
+ *
5
+ * This hook provides functionality to determine the availability of the last saved game, as well as to load and restore the game data from the saved state.
6
+ * It uses reactive data fetching and caching mechanisms to seamlessly manage game state retrieval.
7
+ *
8
+ * @function useLastLoadGame
9
+ * @returns Returns an object containing:
10
+ * - `hasLastSave` {boolean}: Indicates whether a last saved game exists.
11
+ * - `loadLastGame` {Function}: Asynchronous function to load the last saved game state.
12
+ * - `isLoading` {boolean}: Represents whether the last save status is currently being determined.
13
+ * - `lastSave` {Object|null}: The last saved game data object, or null if not available.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * const { hasLastSave, loadLastGame, isLoading } = useGetLastLoadGame();
18
+ *
19
+ * if (isLoading) {
20
+ * return <div>Loading...</div>;
21
+ * }
22
+ *
23
+ * return (
24
+ * <button onClick={loadLastGame} disabled={!hasLastSave}>
25
+ * Continue Last Game
26
+ * </button>
27
+ * );
28
+ * ```
29
+ */
30
+ export declare const useLastLoadGame: () => {
31
+ hasLastSave: boolean;
32
+ loadLastGame: () => Promise<{
33
+ success: boolean;
34
+ error: string;
35
+ } | undefined>;
36
+ isLoading: boolean;
37
+ lastSave: GameSave | null;
38
+ };
39
+ //# sourceMappingURL=useLastLoadGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLastLoadGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useLastLoadGame.ts"],"names":[],"mappings":"AAIA,OAAO,EAAM,QAAQ,EAAY,MAAM,QAAQ,CAAC;AAUhD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,eAAe;;;;;;;;CAkC3B,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { useLiveQuery } from "dexie-react-hooks";
2
+ import { useCallback } from "react";
3
+ import { Game } from "../../game";
4
+ import { db, loadGame } from "../../saves";
5
+ const getLastSave = async () => {
6
+ const save = await db.saves
7
+ .filter((save) => !save.isSystemSave)
8
+ .reverse()
9
+ .sortBy("timestamp");
10
+ return save[0] ?? null;
11
+ };
12
+ /**
13
+ * A custom hook for managing the loading of the last saved game state.
14
+ *
15
+ * This hook provides functionality to determine the availability of the last saved game, as well as to load and restore the game data from the saved state.
16
+ * It uses reactive data fetching and caching mechanisms to seamlessly manage game state retrieval.
17
+ *
18
+ * @function useLastLoadGame
19
+ * @returns Returns an object containing:
20
+ * - `hasLastSave` {boolean}: Indicates whether a last saved game exists.
21
+ * - `loadLastGame` {Function}: Asynchronous function to load the last saved game state.
22
+ * - `isLoading` {boolean}: Represents whether the last save status is currently being determined.
23
+ * - `lastSave` {Object|null}: The last saved game data object, or null if not available.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const { hasLastSave, loadLastGame, isLoading } = useGetLastLoadGame();
28
+ *
29
+ * if (isLoading) {
30
+ * return <div>Loading...</div>;
31
+ * }
32
+ *
33
+ * return (
34
+ * <button onClick={loadLastGame} disabled={!hasLastSave}>
35
+ * Continue Last Game
36
+ * </button>
37
+ * );
38
+ * ```
39
+ */
40
+ export const useLastLoadGame = () => {
41
+ const lastSave = useLiveQuery(getLastSave, [], null);
42
+ const loadLastGame = useCallback(async () => {
43
+ if (!lastSave?.id)
44
+ return;
45
+ const saveId = Number(lastSave.name);
46
+ if (isNaN(saveId)) {
47
+ throw new Error("Invalid save ID");
48
+ }
49
+ try {
50
+ const data = await loadGame(saveId);
51
+ if (!data) {
52
+ return { success: false, error: "Game data not found" };
53
+ }
54
+ Game.setState(data.gameData);
55
+ }
56
+ catch (e) {
57
+ console.error("Failed to load last game:", e);
58
+ return {
59
+ success: false,
60
+ error: e.message ||
61
+ "Unknown error occurred while loading the game, please, check console for more info",
62
+ };
63
+ }
64
+ }, [lastSave?.id]);
65
+ return {
66
+ hasLastSave: !!lastSave,
67
+ loadLastGame,
68
+ isLoading: lastSave === undefined,
69
+ lastSave: lastSave ?? null,
70
+ };
71
+ };
72
+ //# sourceMappingURL=useLastLoadGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLastLoadGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useLastLoadGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAY,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEhD,MAAM,WAAW,GAAG,KAAK,IAA8B,EAAE;IACrD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK;SACtB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;SACpC,OAAO,EAAE;SACT,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE;IAChC,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC,QAAQ,EAAE,EAAE;YAAE,OAAO;QAE1B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACR,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;YAC5D,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAC;YAC9C,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EACA,CAAW,CAAC,OAAO;oBACpB,oFAAoF;aAC3F,CAAC;QACN,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAEnB,OAAO;QACH,WAAW,EAAE,CAAC,CAAC,QAAQ;QACvB,YAAY;QACZ,SAAS,EAAE,QAAQ,KAAK,SAAS;QACjC,QAAQ,EAAE,QAAQ,IAAI,IAAI;KAC7B,CAAC;AACN,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * React hook that provides a function to load a saved game by its ID.
3
+ * Restores the game state from the specified save.
4
+ *
5
+ * @returns Function that accepts an optional save ID and loads the game, returning a result object on failure
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const loadGame = useLoadGame();
10
+ * const handleLoad = async () => {
11
+ * const result = await loadGame(saveId);
12
+ * if (result?.success === false) {
13
+ * console.error('Load failed:', result.message);
14
+ * }
15
+ * };
16
+ * ```
17
+ */
18
+ export declare const useLoadGame: () => (id: number) => Promise<{
19
+ success: boolean;
20
+ message: string;
21
+ } | undefined>;
22
+ //# sourceMappingURL=useLoadGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useLoadGame.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,SAAgB,IAAI,MAAM;;;cAmBjD,CAAC"}