diff --git a/src/App.tsx b/src/App.tsx
index e5dd764..5f7c60d 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,10 +1,12 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import { Tabs, TabsContent, TabsList, TabsTrigger } from './components/CustomTabs';
import { useGameTick } from './hooks/useGameTick';
import Field from './components/Field';
import Warehouse from './components/Warehouse';
import Market from './components/Market';
import { ActionCooldown } from './components/ActionCooldown';
+import { useGameStore } from './store/useGameStore';
+import { hasSaveInSlot } from './utils/saveSystem';
const appContainerStyle: React.CSSProperties = {
maxWidth: '1200px',
@@ -20,6 +22,33 @@ const tabsListStyles: React.CSSProperties = {
function App() {
useGameTick();
+ const { saveToSlot, loadFromSlot } = useGameStore();
+
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ const slot = {
+ '1': 1,
+ '2': 2,
+ '3': 3,
+ '!': 1,
+ '@': 2,
+ '#': 3
+ }[e.key] ?? null
+
+ if (slot !== null) {
+ if (e.shiftKey) {
+ saveToSlot(slot);
+ console.log(`Game saved to slot ${slot}`);
+ } else if (hasSaveInSlot(slot)) {
+ loadFromSlot(slot);
+ console.log(`Game loaded from slot ${slot}`);
+ }
+ }
+ }
+
+ window.addEventListener('keydown', handleKeyDown)
+ return () => window.removeEventListener('keydown', handleKeyDown)
+ }, [saveToSlot, loadFromSlot])
return (
diff --git a/src/store/useGameStore.ts b/src/store/useGameStore.ts
index 13358a3..de94914 100644
--- a/src/store/useGameStore.ts
+++ b/src/store/useGameStore.ts
@@ -11,6 +11,7 @@ import {
MARKET_ITEMS
} from '../constants';
import { GameState, PlotState } from '../types';
+import { saveGame, loadGame } from '../utils/saveSystem';
const initializeField = (size: number): PlotState[][] => {
return Array(size).fill(0).map(() =>
@@ -31,6 +32,8 @@ export const useGameStore = create void;
buyItem: (itemId: string) => void;
sellItem: (itemId: string) => void;
+ saveToSlot: (slot: number) => void;
+ loadFromSlot: (slot: number) => void;
}>((set, get) => ({
cash: INITIAL_CASH,
inventory: INITIAL_INVENTORY,
@@ -40,6 +43,7 @@ export const useGameStore = create {
set(produce(state => {
@@ -137,11 +141,6 @@ export const useGameStore = create {
set(produce(state => {
- // Update cooldown
- if (state.actionCooldown > 0) {
- state.actionCooldown = Math.max(0, state.actionCooldown - (COOLDOWN_DURATION / 20));
- }
-
// Update plots
state.plots.forEach((row: PlotState[], rowIndex: number) => {
row.forEach((plot: PlotState, colIndex: number) => {
@@ -162,6 +161,8 @@ export const useGameStore = create {
+ const state = get();
+ const { plant, water, harvest, tick, assignCrop, upgradeField, setGameSpeed, setActionCooldown, buyItem, sellItem, saveToSlot, loadFromSlot, ...gameState } = state;
+ saveGame(slot, gameState);
+ },
+
+ loadFromSlot: (slot: number) => {
+ const savedState = loadGame(slot);
+ if (savedState) {
+ set(savedState);
+ }
}
}));
diff --git a/src/utils/saveSystem.ts b/src/utils/saveSystem.ts
new file mode 100644
index 0000000..0f045c9
--- /dev/null
+++ b/src/utils/saveSystem.ts
@@ -0,0 +1,29 @@
+import { GameState } from '../types';
+
+const SAVE_SLOT_PREFIX = 'dionysian_idle_save_';
+
+export const saveGame = (slot: number, state: GameState) => {
+ try {
+ const saveData = JSON.stringify(state);
+ localStorage.setItem(`${SAVE_SLOT_PREFIX}${slot}`, saveData);
+ return true;
+ } catch (error) {
+ console.error('Failed to save game:', error);
+ return false;
+ }
+};
+
+export const loadGame = (slot: number): GameState | null => {
+ try {
+ const saveData = localStorage.getItem(`${SAVE_SLOT_PREFIX}${slot}`);
+ if (!saveData) return null;
+ return JSON.parse(saveData);
+ } catch (error) {
+ console.error('Failed to load game:', error);
+ return null;
+ }
+};
+
+export const hasSaveInSlot = (slot: number): boolean => {
+ return !!localStorage.getItem(`${SAVE_SLOT_PREFIX}${slot}`);
+};
\ No newline at end of file