Add a simple save system

This commit is contained in:
Ryan Lanny Jenkins 2025-05-18 10:08:52 -05:00
parent d4dda5b3e4
commit 39309aa9e7
3 changed files with 78 additions and 6 deletions

View file

@ -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 (
<div>

View file

@ -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<GameState & {
setActionCooldown: (cooldown: number) => 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<GameState & {
plots: initializeField(INITIAL_FIELD_SIZE),
gameSpeed: INITIAL_GAME_SPEED,
actionCooldown: 0,
tickCount: 0,
assignCrop: (row, col, cropId) => {
set(produce(state => {
@ -137,11 +141,6 @@ export const useGameStore = create<GameState & {
tick: () => {
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<GameState & {
}
});
});
state.tickCount = state.tickCount + 1;
}));
},
@ -228,5 +229,18 @@ export const useGameStore = create<GameState & {
state.cash += item.sellPrice;
state.inventory[itemId] -= 1;
}));
},
saveToSlot: (slot: number) => {
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);
}
}
}));

29
src/utils/saveSystem.ts Normal file
View file

@ -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}`);
};