From 39309aa9e754857ba60a125adcba3327c8318827 Mon Sep 17 00:00:00 2001 From: Ryan Lanny Jenkins Date: Sun, 18 May 2025 10:08:52 -0500 Subject: [PATCH] Add a simple save system --- src/App.tsx | 31 ++++++++++++++++++++++++++++++- src/store/useGameStore.ts | 24 +++++++++++++++++++----- src/utils/saveSystem.ts | 29 +++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 src/utils/saveSystem.ts 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