@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.
- package/README.md +744 -0
- package/dist/baseGameObject.d.ts +90 -0
- package/dist/baseGameObject.d.ts.map +1 -0
- package/dist/baseGameObject.js +109 -0
- package/dist/baseGameObject.js.map +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +12 -0
- package/dist/constants.js.map +1 -0
- package/dist/game.d.ts +294 -0
- package/dist/game.d.ts.map +1 -0
- package/dist/game.js +489 -0
- package/dist/game.js.map +1 -0
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +6 -0
- package/dist/helpers.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useCurrentPassage.d.ts +10 -0
- package/dist/hooks/useCurrentPassage.d.ts.map +1 -0
- package/dist/hooks/useCurrentPassage.js +17 -0
- package/dist/hooks/useCurrentPassage.js.map +1 -0
- package/dist/hooks/useGameEntity.d.ts +21 -0
- package/dist/hooks/useGameEntity.d.ts.map +1 -0
- package/dist/hooks/useGameEntity.js +70 -0
- package/dist/hooks/useGameEntity.js.map +1 -0
- package/dist/hooks/useGameIsStarted.d.ts +12 -0
- package/dist/hooks/useGameIsStarted.d.ts.map +1 -0
- package/dist/hooks/useGameIsStarted.js +18 -0
- package/dist/hooks/useGameIsStarted.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +36 -0
- package/dist/logger.js.map +1 -0
- package/dist/options.d.ts +13 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +15 -0
- package/dist/options.js.map +1 -0
- package/dist/passages/interactiveMap/fabric.d.ts +4 -0
- package/dist/passages/interactiveMap/fabric.d.ts.map +1 -0
- package/dist/passages/interactiveMap/fabric.js +3 -0
- package/dist/passages/interactiveMap/fabric.js.map +1 -0
- package/dist/passages/interactiveMap/index.d.ts +4 -0
- package/dist/passages/interactiveMap/index.d.ts.map +1 -0
- package/dist/passages/interactiveMap/index.js +4 -0
- package/dist/passages/interactiveMap/index.js.map +1 -0
- package/dist/passages/interactiveMap/interactiveMap.d.ts +89 -0
- package/dist/passages/interactiveMap/interactiveMap.d.ts.map +1 -0
- package/dist/passages/interactiveMap/interactiveMap.js +103 -0
- package/dist/passages/interactiveMap/interactiveMap.js.map +1 -0
- package/dist/passages/interactiveMap/types.d.ts +822 -0
- package/dist/passages/interactiveMap/types.d.ts.map +1 -0
- package/dist/passages/interactiveMap/types.js +2 -0
- package/dist/passages/interactiveMap/types.js.map +1 -0
- package/dist/passages/passage.d.ts +57 -0
- package/dist/passages/passage.d.ts.map +1 -0
- package/dist/passages/passage.js +64 -0
- package/dist/passages/passage.js.map +1 -0
- package/dist/passages/story/fabric.d.ts +4 -0
- package/dist/passages/story/fabric.d.ts.map +1 -0
- package/dist/passages/story/fabric.js +3 -0
- package/dist/passages/story/fabric.js.map +1 -0
- package/dist/passages/story/index.d.ts +5 -0
- package/dist/passages/story/index.d.ts.map +1 -0
- package/dist/passages/story/index.js +5 -0
- package/dist/passages/story/index.js.map +1 -0
- package/dist/passages/story/start.d.ts +14 -0
- package/dist/passages/story/start.d.ts.map +1 -0
- package/dist/passages/story/start.js +22 -0
- package/dist/passages/story/start.js.map +1 -0
- package/dist/passages/story/story.d.ts +84 -0
- package/dist/passages/story/story.d.ts.map +1 -0
- package/dist/passages/story/story.js +88 -0
- package/dist/passages/story/story.js.map +1 -0
- package/dist/passages/story/types.d.ts +911 -0
- package/dist/passages/story/types.d.ts.map +1 -0
- package/dist/passages/story/types.js +2 -0
- package/dist/passages/story/types.js.map +1 -0
- package/dist/passages/types/index.d.ts +3 -0
- package/dist/passages/types/index.d.ts.map +1 -0
- package/dist/passages/types/index.js +2 -0
- package/dist/passages/types/index.js.map +1 -0
- package/dist/passages/widget.d.ts +62 -0
- package/dist/passages/widget.d.ts.map +1 -0
- package/dist/passages/widget.js +66 -0
- package/dist/passages/widget.js.map +1 -0
- package/dist/saves/constants.d.ts +17 -0
- package/dist/saves/constants.d.ts.map +1 -0
- package/dist/saves/constants.js +17 -0
- package/dist/saves/constants.js.map +1 -0
- package/dist/saves/db.d.ts +119 -0
- package/dist/saves/db.d.ts.map +1 -0
- package/dist/saves/db.js +231 -0
- package/dist/saves/db.js.map +1 -0
- package/dist/saves/helpers.d.ts +28 -0
- package/dist/saves/helpers.d.ts.map +1 -0
- package/dist/saves/helpers.js +84 -0
- package/dist/saves/helpers.js.map +1 -0
- package/dist/saves/hooks/index.d.ts +10 -0
- package/dist/saves/hooks/index.d.ts.map +1 -0
- package/dist/saves/hooks/index.js +10 -0
- package/dist/saves/hooks/index.js.map +1 -0
- package/dist/saves/hooks/useDeleteAllSlots.d.ts +18 -0
- package/dist/saves/hooks/useDeleteAllSlots.d.ts.map +1 -0
- package/dist/saves/hooks/useDeleteAllSlots.js +18 -0
- package/dist/saves/hooks/useDeleteAllSlots.js.map +1 -0
- package/dist/saves/hooks/useDeleteGame.d.ts +22 -0
- package/dist/saves/hooks/useDeleteGame.d.ts.map +1 -0
- package/dist/saves/hooks/useDeleteGame.js +33 -0
- package/dist/saves/hooks/useDeleteGame.js.map +1 -0
- package/dist/saves/hooks/useExportSaves.d.ts +27 -0
- package/dist/saves/hooks/useExportSaves.d.ts.map +1 -0
- package/dist/saves/hooks/useExportSaves.js +54 -0
- package/dist/saves/hooks/useExportSaves.js.map +1 -0
- package/dist/saves/hooks/useImportSaves.d.ts +29 -0
- package/dist/saves/hooks/useImportSaves.d.ts.map +1 -0
- package/dist/saves/hooks/useImportSaves.js +108 -0
- package/dist/saves/hooks/useImportSaves.js.map +1 -0
- package/dist/saves/hooks/useLastLoadGame.d.ts +39 -0
- package/dist/saves/hooks/useLastLoadGame.d.ts.map +1 -0
- package/dist/saves/hooks/useLastLoadGame.js +72 -0
- package/dist/saves/hooks/useLastLoadGame.js.map +1 -0
- package/dist/saves/hooks/useLoadGame.d.ts +22 -0
- package/dist/saves/hooks/useLoadGame.d.ts.map +1 -0
- package/dist/saves/hooks/useLoadGame.js +40 -0
- package/dist/saves/hooks/useLoadGame.js.map +1 -0
- package/dist/saves/hooks/useRestartGame.d.ts +20 -0
- package/dist/saves/hooks/useRestartGame.d.ts.map +1 -0
- package/dist/saves/hooks/useRestartGame.js +29 -0
- package/dist/saves/hooks/useRestartGame.js.map +1 -0
- package/dist/saves/hooks/useSaveGame.d.ts +22 -0
- package/dist/saves/hooks/useSaveGame.d.ts.map +1 -0
- package/dist/saves/hooks/useSaveGame.js +34 -0
- package/dist/saves/hooks/useSaveGame.js.map +1 -0
- package/dist/saves/hooks/useSaveSlots.d.ts +45 -0
- package/dist/saves/hooks/useSaveSlots.d.ts.map +1 -0
- package/dist/saves/hooks/useSaveSlots.js +42 -0
- package/dist/saves/hooks/useSaveSlots.js.map +1 -0
- package/dist/saves/index.d.ts +4 -0
- package/dist/saves/index.d.ts.map +1 -0
- package/dist/saves/index.js +3 -0
- package/dist/saves/index.js.map +1 -0
- package/dist/saves/types.d.ts +52 -0
- package/dist/saves/types.d.ts.map +1 -0
- package/dist/saves/types.js +2 -0
- package/dist/saves/types.js.map +1 -0
- package/dist/storage.d.ts +124 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +229 -0
- package/dist/storage.js.map +1 -0
- package/dist/tests/game.test.d.ts +2 -0
- package/dist/tests/game.test.d.ts.map +1 -0
- package/dist/tests/game.test.js +602 -0
- package/dist/tests/game.test.js.map +1 -0
- package/dist/tests/interactiveMap.test.d.ts +2 -0
- package/dist/tests/interactiveMap.test.d.ts.map +1 -0
- package/dist/tests/interactiveMap.test.js +1003 -0
- package/dist/tests/interactiveMap.test.js.map +1 -0
- package/dist/tests/storage.test.d.ts +2 -0
- package/dist/tests/storage.test.d.ts.map +1 -0
- package/dist/tests/storage.test.js +328 -0
- package/dist/tests/storage.test.js.map +1 -0
- package/dist/tests/story.test.d.ts +2 -0
- package/dist/tests/story.test.d.ts.map +1 -0
- package/dist/tests/story.test.js +698 -0
- package/dist/tests/story.test.js.map +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Game } from "../../game";
|
|
2
|
+
import { loadGame } from "../../saves";
|
|
3
|
+
/**
|
|
4
|
+
* React hook that provides a function to load a saved game by its ID.
|
|
5
|
+
* Restores the game state from the specified save.
|
|
6
|
+
*
|
|
7
|
+
* @returns Function that accepts an optional save ID and loads the game, returning a result object on failure
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const loadGame = useLoadGame();
|
|
12
|
+
* const handleLoad = async () => {
|
|
13
|
+
* const result = await loadGame(saveId);
|
|
14
|
+
* if (result?.success === false) {
|
|
15
|
+
* console.error('Load failed:', result.message);
|
|
16
|
+
* }
|
|
17
|
+
* };
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const useLoadGame = () => async (id) => {
|
|
21
|
+
try {
|
|
22
|
+
const data = await loadGame(id);
|
|
23
|
+
if (!data) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
message: "The requested game save does not exist",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
Game.setState(data.gameData);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
console.error("Failed to load game:", e);
|
|
33
|
+
return {
|
|
34
|
+
success: false,
|
|
35
|
+
message: e.message ||
|
|
36
|
+
"Failed to load game. Check console for more info.",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=useLoadGame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLoadGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useLoadGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;IAClD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,wCAAwC;aACpD,CAAC;QACN,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EACF,CAAW,CAAC,OAAO;gBACpB,mDAAmD;SAC1D,CAAC;IACN,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook that provides a function to restart the game from the initial state.
|
|
3
|
+
* Loads the system save (initial game state), clears auto-save, and navigates to start passage.
|
|
4
|
+
*
|
|
5
|
+
* @returns Callback function that restarts the game
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const restartGame = useRestartGame();
|
|
10
|
+
* <button onClick={restartGame}>Restart Game</button>
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare const useRestartGame: () => () => Promise<{
|
|
14
|
+
success: boolean;
|
|
15
|
+
error: string;
|
|
16
|
+
} | {
|
|
17
|
+
success: boolean;
|
|
18
|
+
error: null;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=useRestartGame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRestartGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useRestartGame.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc;;;;;;EAe1B,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { SYSTEM_PASSAGE_NAMES } from "../../constants";
|
|
3
|
+
import { Game } from "../../game";
|
|
4
|
+
import { getSystemSave } from "../../saves";
|
|
5
|
+
/**
|
|
6
|
+
* React hook that provides a function to restart the game from the initial state.
|
|
7
|
+
* Loads the system save (initial game state), clears auto-save, and navigates to start passage.
|
|
8
|
+
*
|
|
9
|
+
* @returns Callback function that restarts the game
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const restartGame = useRestartGame();
|
|
14
|
+
* <button onClick={restartGame}>Restart Game</button>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export const useRestartGame = () => {
|
|
18
|
+
return useCallback(async () => {
|
|
19
|
+
const systemSave = await getSystemSave();
|
|
20
|
+
if (!systemSave) {
|
|
21
|
+
return { success: false, error: "System save not found. Cannot restart game." };
|
|
22
|
+
}
|
|
23
|
+
Game.clearAutoSave();
|
|
24
|
+
Game.setState(systemSave.gameData);
|
|
25
|
+
Game.jumpTo(SYSTEM_PASSAGE_NAMES.START_MENU);
|
|
26
|
+
return { success: true, error: null };
|
|
27
|
+
}, []);
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=useRestartGame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRestartGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useRestartGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IAC/B,OAAO,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,UAAU,GAAG,MAAM,aAAa,EAAE,CAAC;QAEzC,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAA;QACnF,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEnC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAE7C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook that provides a function to save the current game state to a specific slot.
|
|
3
|
+
* The save is stored in IndexedDB with the slot number as the save name.
|
|
4
|
+
*
|
|
5
|
+
* @returns Function that accepts a slot number and saves the game, returning a result object on failure
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const saveGame = useSaveGame();
|
|
10
|
+
* const handleSave = async () => {
|
|
11
|
+
* const result = await saveGame(1);
|
|
12
|
+
* if (result?.success === false) {
|
|
13
|
+
* console.error('Save failed:', result.message);
|
|
14
|
+
* }
|
|
15
|
+
* };
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const useSaveGame: () => (id: number) => Promise<{
|
|
19
|
+
success: boolean;
|
|
20
|
+
message: string;
|
|
21
|
+
} | undefined>;
|
|
22
|
+
//# sourceMappingURL=useSaveGame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSaveGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveGame.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,SAAgB,IAAI,MAAM;;;cAcjD,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Game } from "../../game";
|
|
2
|
+
import { saveGame } from "../../saves";
|
|
3
|
+
/**
|
|
4
|
+
* React hook that provides a function to save the current game state to a specific slot.
|
|
5
|
+
* The save is stored in IndexedDB with the slot number as the save name.
|
|
6
|
+
*
|
|
7
|
+
* @returns Function that accepts a slot number and saves the game, returning a result object on failure
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const saveGame = useSaveGame();
|
|
12
|
+
* const handleSave = async () => {
|
|
13
|
+
* const result = await saveGame(1);
|
|
14
|
+
* if (result?.success === false) {
|
|
15
|
+
* console.error('Save failed:', result.message);
|
|
16
|
+
* }
|
|
17
|
+
* };
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const useSaveGame = () => async (id) => {
|
|
21
|
+
const data = Game.getState();
|
|
22
|
+
try {
|
|
23
|
+
await saveGame(id, data);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.error("Failed to save game:", e);
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
message: e.message ||
|
|
30
|
+
"Failed to save game. Check console for more info.",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=useSaveGame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSaveGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAE7B,IAAI,CAAC;QACD,MAAM,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EACF,CAAW,CAAC,OAAO;gBACpB,mDAAmD;SAC1D,CAAC;IACN,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { GameSave } from "../../saves";
|
|
2
|
+
/**
|
|
3
|
+
* React hook that provides an array of save slots with live updates from IndexedDB.
|
|
4
|
+
* Each slot includes the save data and methods to save, load, and delete.
|
|
5
|
+
*
|
|
6
|
+
* @param config - Configuration object
|
|
7
|
+
* @param config.count - Number of save slots to create (defaults to 1)
|
|
8
|
+
* @returns Array of save slot objects, each containing data and action methods
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const slots = useSaveSlots({ count: 5 });
|
|
13
|
+
*
|
|
14
|
+
* return (
|
|
15
|
+
* <div>
|
|
16
|
+
* {slots.map((slot, index) => (
|
|
17
|
+
* <div key={index}>
|
|
18
|
+
* <p>Slot {index}: {slot.data ? 'Saved' : 'Empty'}</p>
|
|
19
|
+
* <button onClick={() => slot.save()}>Save</button>
|
|
20
|
+
* <button onClick={() => slot.load()} disabled={!slot.data}>Load</button>
|
|
21
|
+
* <button onClick={() => slot.delete()} disabled={!slot.data}>Delete</button>
|
|
22
|
+
* </div>
|
|
23
|
+
* ))}
|
|
24
|
+
* </div>
|
|
25
|
+
* );
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const useSaveSlots: ({ count }?: {
|
|
29
|
+
count: number;
|
|
30
|
+
}) => {
|
|
31
|
+
data: GameSave | null;
|
|
32
|
+
save: () => Promise<{
|
|
33
|
+
success: boolean;
|
|
34
|
+
message: string;
|
|
35
|
+
} | undefined>;
|
|
36
|
+
load: () => Promise<{
|
|
37
|
+
success: boolean;
|
|
38
|
+
message: string;
|
|
39
|
+
} | undefined>;
|
|
40
|
+
delete: () => Promise<{
|
|
41
|
+
success: boolean;
|
|
42
|
+
message: string;
|
|
43
|
+
} | undefined>;
|
|
44
|
+
}[];
|
|
45
|
+
//# sourceMappingURL=useSaveSlots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSaveSlots.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveSlots.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAwD,MAAM,QAAQ,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY,GAAI;;CAAwB;;;;;;;;;;;;;;GAkBpD,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useLiveQuery } from "dexie-react-hooks";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { getAllSaves, useDeleteGame, useLoadGame, useSaveGame } from "../../saves";
|
|
4
|
+
/**
|
|
5
|
+
* React hook that provides an array of save slots with live updates from IndexedDB.
|
|
6
|
+
* Each slot includes the save data and methods to save, load, and delete.
|
|
7
|
+
*
|
|
8
|
+
* @param config - Configuration object
|
|
9
|
+
* @param config.count - Number of save slots to create (defaults to 1)
|
|
10
|
+
* @returns Array of save slot objects, each containing data and action methods
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const slots = useSaveSlots({ count: 5 });
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <div>
|
|
18
|
+
* {slots.map((slot, index) => (
|
|
19
|
+
* <div key={index}>
|
|
20
|
+
* <p>Slot {index}: {slot.data ? 'Saved' : 'Empty'}</p>
|
|
21
|
+
* <button onClick={() => slot.save()}>Save</button>
|
|
22
|
+
* <button onClick={() => slot.load()} disabled={!slot.data}>Load</button>
|
|
23
|
+
* <button onClick={() => slot.delete()} disabled={!slot.data}>Delete</button>
|
|
24
|
+
* </div>
|
|
25
|
+
* ))}
|
|
26
|
+
* </div>
|
|
27
|
+
* );
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const useSaveSlots = ({ count } = { count: 1 }) => {
|
|
31
|
+
const data = useLiveQuery(() => getAllSaves(), [], []);
|
|
32
|
+
const deleteGameHandler = useDeleteGame();
|
|
33
|
+
const saveGameHandler = useSaveGame();
|
|
34
|
+
const loadGameHandler = useLoadGame();
|
|
35
|
+
return useMemo(() => Array.from({ length: count }).map((_, index) => ({
|
|
36
|
+
data: data?.find((slot) => slot.name === `${index}`) || null,
|
|
37
|
+
save: async () => saveGameHandler(index),
|
|
38
|
+
load: async () => loadGameHandler(index),
|
|
39
|
+
delete: async () => deleteGameHandler(index),
|
|
40
|
+
})), [data, count, deleteGameHandler, loadGameHandler, saveGameHandler]);
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=useSaveSlots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSaveSlots.js","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveSlots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAY,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;IACrD,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,EAAgB,CAAC,CAAC;IACrE,MAAM,iBAAiB,GAAG,aAAa,EAAE,CAAC;IAC1C,MAAM,eAAe,GAAG,WAAW,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,WAAW,EAAE,CAAC;IAEtC,OAAO,OAAO,CACV,GAAG,EAAE,CACD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAC7B,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACX,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC,IAAI,IAAI;QAC5D,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;QACxC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;QACxC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC;KAC/C,CAAC,CACL,EACL,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,CAAC,CACrE,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/saves/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC;AACxB,mBAAmB,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/saves/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a saved game state
|
|
3
|
+
*/
|
|
4
|
+
export interface GameSave {
|
|
5
|
+
/** Database auto-generated ID */
|
|
6
|
+
id?: number;
|
|
7
|
+
/** User-defined name for the save */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Serialized game state data */
|
|
10
|
+
gameData: Record<string, unknown>;
|
|
11
|
+
/** When the save was created */
|
|
12
|
+
timestamp: Date;
|
|
13
|
+
/** Game version when the save was created */
|
|
14
|
+
version: string;
|
|
15
|
+
/** Base64 encoded screenshot (optional) */
|
|
16
|
+
screenshot?: string;
|
|
17
|
+
/** User-provided description (optional) */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Mark as system save (won't be shown in UI) */
|
|
20
|
+
isSystemSave?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Represents a game setting stored in the database
|
|
24
|
+
*/
|
|
25
|
+
export interface GameSettings {
|
|
26
|
+
/** Database auto-generated ID */
|
|
27
|
+
id?: number;
|
|
28
|
+
/** Unique key for the setting */
|
|
29
|
+
key: string;
|
|
30
|
+
/** Setting value (can be string, number, boolean, or object) */
|
|
31
|
+
value: string | number | boolean | object;
|
|
32
|
+
/** When the setting was last updated */
|
|
33
|
+
timestamp: Date;
|
|
34
|
+
/** Game version when the setting was created/updated */
|
|
35
|
+
version: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Represents the state of save slots, used by React hooks
|
|
39
|
+
*/
|
|
40
|
+
export type SaveSlotsData = {
|
|
41
|
+
/** Whether there are no saves */
|
|
42
|
+
isEmpty: boolean;
|
|
43
|
+
/** Whether saves are currently being loaded */
|
|
44
|
+
isLoading: boolean;
|
|
45
|
+
/** Whether there was an error loading saves */
|
|
46
|
+
isError: boolean;
|
|
47
|
+
/** Error object if an error occurred */
|
|
48
|
+
error: Error | null;
|
|
49
|
+
/** Array of game saves */
|
|
50
|
+
data: GameSave[];
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/saves/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,gCAAgC;IAChC,SAAS,EAAE,IAAI,CAAC;IAChB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC1C,wCAAwC;IACxC,SAAS,EAAE,IAAI,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IACxB,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,0BAA0B;IAC1B,IAAI,EAAE,QAAQ,EAAE,CAAC;CACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/saves/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { GameSaveState, JsonPath } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* JSONPath-based storage system for game state persistence.
|
|
4
|
+
*
|
|
5
|
+
* The Storage class provides a flexible way to store and retrieve game state using
|
|
6
|
+
* JSONPath queries. It supports nested data structures and protects system paths
|
|
7
|
+
* from accidental modification.
|
|
8
|
+
*
|
|
9
|
+
* @see https://www.npmjs.com/package/jsonpath-plus - JSONPath Plus library documentation
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // Set values
|
|
14
|
+
* Storage.setValue('$.player.health', 100);
|
|
15
|
+
* Storage.setValue('$.inventory.items', ['sword', 'shield']);
|
|
16
|
+
*
|
|
17
|
+
* // Get values
|
|
18
|
+
* const health = Storage.getValue<number>('$.player.health');
|
|
19
|
+
* const items = Storage.getValue<string[]>('$.inventory.items');
|
|
20
|
+
*
|
|
21
|
+
* // Full state
|
|
22
|
+
* const state = Storage.getState();
|
|
23
|
+
* Storage.setState(state);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class Storage {
|
|
27
|
+
/**
|
|
28
|
+
* Retrieves values from storage using a JSONPath query.
|
|
29
|
+
*
|
|
30
|
+
* Returns an array of matching values. If no matches are found, returns an empty array.
|
|
31
|
+
* The JSONPath Plus library supports complex queries including wildcards, filters, and deep scanning.
|
|
32
|
+
*
|
|
33
|
+
* @template T - The expected type of values to retrieve
|
|
34
|
+
* @param jsonPath - The JSONPath query string (e.g., '$.player.health', '$.inventory.items[*]')
|
|
35
|
+
* @returns Array of values matching the JSONPath query
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // Get a single value (returns array with one element)
|
|
40
|
+
* const health = Storage.getValue<number>('$.player.health');
|
|
41
|
+
* if (health.length > 0) {
|
|
42
|
+
* console.log(health[0]); // 100
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* // Get multiple values with wildcard
|
|
46
|
+
* const allItems = Storage.getValue<string>('$.inventory.*.name');
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
static getValue<T>(jsonPath: JsonPath): Array<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Sets a value in storage at the specified JSONPath.
|
|
52
|
+
*
|
|
53
|
+
* If the path exists, updates the value. If the path doesn't exist, creates it.
|
|
54
|
+
* System paths (prefixed with STORAGE_SYSTEM_PATH) are protected from external modification.
|
|
55
|
+
*
|
|
56
|
+
* @template T - The type of value to set
|
|
57
|
+
* @param jsonPath - The JSONPath where the value should be set
|
|
58
|
+
* @param value - The value to set at the specified JSONPath
|
|
59
|
+
* @param _isSystem - Internal flag to allow system path modification (default: false)
|
|
60
|
+
* @throws Error if attempting to modify a system path without _isSystem flag
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* // Set a simple value
|
|
65
|
+
* Storage.setValue('$.player.health', 75);
|
|
66
|
+
*
|
|
67
|
+
* // Set a complex object
|
|
68
|
+
* Storage.setValue('$.player.stats', { str: 10, dex: 8 });
|
|
69
|
+
*
|
|
70
|
+
* // System paths are protected
|
|
71
|
+
* Storage.setValue('$._system.game', {}); // Throws error
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
static setValue<T>(jsonPath: JsonPath, value: T, _isSystem?: boolean): void;
|
|
75
|
+
/**
|
|
76
|
+
* Retrieves the entire storage state as a plain object.
|
|
77
|
+
*
|
|
78
|
+
* @returns The complete storage state, ready for serialization
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const state = Storage.getState();
|
|
83
|
+
* localStorage.setItem('save', JSON.stringify(state));
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
static getState(): GameSaveState;
|
|
87
|
+
/**
|
|
88
|
+
* Replaces the entire storage state with a new state object.
|
|
89
|
+
*
|
|
90
|
+
* Clears all existing storage data and replaces it with the provided state.
|
|
91
|
+
* Useful for loading saved games or resetting to a specific state.
|
|
92
|
+
*
|
|
93
|
+
* @param state - The new state to set for the storage
|
|
94
|
+
* @throws Error if state is not a valid object
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const savedState = JSON.parse(localStorage.getItem('save'));
|
|
99
|
+
* Storage.setState(savedState);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
static setState(state: GameSaveState): void;
|
|
103
|
+
/**
|
|
104
|
+
* Creates a nested path in storage and assigns a value.
|
|
105
|
+
*
|
|
106
|
+
* Parses the JSONPath and creates all necessary intermediate objects/arrays
|
|
107
|
+
* to build the path if it doesn't exist. Supports both object properties and array indices.
|
|
108
|
+
*
|
|
109
|
+
* @private - Used internally by setValue when creating new paths
|
|
110
|
+
* @template T - The type of value to set at the path
|
|
111
|
+
* @param obj - The target object where the path will be created
|
|
112
|
+
* @param jsonPath - The JSONPath string specifying the location
|
|
113
|
+
* @param value - The value to set at the specified location
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* // Creates $.player.inventory.items[0] = 'sword'
|
|
118
|
+
* // Will create player object, inventory object, items array automatically
|
|
119
|
+
* Storage.createPath(storage, '$.player.inventory.items[0]', 'sword');
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
private static createPath;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,OAAO;IAChB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC;IAIhD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EACb,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,CAAC,EACR,SAAS,GAAE,OAAe,GAC3B,IAAI;IAkCP;;;;;;;;;;OAUG;IACH,MAAM,CAAC,QAAQ,IAAI,aAAa;IAIhC;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAY3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CA8E5B"}
|