refactor: resolve structural inconsistencies and dead code
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 55s

- Fix broken barrel exports in components/game/index.ts
- Remove skill system from stores (gameStore, gameActions, gameLoopActions, gameHooks, craftingStore, combat)
- Remove skill system from components (page.tsx, LeftPanel, StatsTab, SpellsTab, EnchantmentDesigner, EnchantmentPreparer, GameContext/Provider)
- Delete dead code: stats/ directory, attunements/ directory, layout/ Header+TabBar, shared/ StudyProgress+UpgradeDialog duplicates, effects.ts.fix, study-slice.ts, navigation-slice.ts
- Delete legacy store/ and store-modules/ directories, redirect remaining callers
- Merge root formatting.ts into utils/formatting.ts
- Move effects files (dynamic-compute, upgrade-effects, special-effects, upgrade-effects.types) into effects/ directory
- Move debug-context.tsx into components/game/debug/
- Create tabs/index.ts barrel for tab components
- Fix page.tsx lazy imports to use tabs barrel
- Fix all broken import paths across codebase
- Remove SKILLS_DEF and skill-evolution references
- Trim store.ts to under 400 lines by removing dead skill actions
This commit is contained in:
2026-05-18 14:21:59 +02:00
parent 2805f75f5e
commit ca86b6268c
57 changed files with 405 additions and 3726 deletions
+80 -116
View File
@@ -1,41 +1,96 @@
// ─── Game Store (Refactored) ──────────────────────────────────────────────
// Main entry point - imports from modular store components
// Target: Under 400 lines
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { GameState, GameAction, StudyTarget, SpellCost, SkillUpgradeChoice, ActivityLogEntry } from './types';
import type { GameState, GameAction, ActivityLogEntry } from './types';
// Import from modular store components
import { makeInitial } from './store-modules/initial-state';
import { addActivityLogEntry } from './store-modules/activity-log';
import {
computeMaxMana, computeRegen, computeClickMana, calcDamage, calcInsight,
getMeditationBonus, getIncursionStrength, canAffordSpellCost
} from './store-modules/computed-stats';
import { generateFloorState, getPuzzleProgressSpeed } from './store-modules/room-utils';
import { addActivityLogEntry } from './utils/activity-log';
import {
computeMaxMana, computeRegen, computeClickMana,
getMeditationBonus,
} from './utils/mana-utils';
import {
calcDamage, calcInsight, getIncursionStrength, canAffordSpellCost, deductSpellCost,
} from './utils/combat-utils';
import { generateFloorState } from './utils/room-utils';
// Re-export formatting functions for backward compatibility
export { fmt, fmtDec } from './utils/formatting';
export { getFloorMaxHP, getFloorElement } from './utils/floor-utils';
// Re-export computed stats functions for backward compatibility and tests
export { computeMaxMana, computeElementMax, computeRegen, computeClickMana, calcDamage, calcInsight, getMeditationBonus, getIncursionStrength, canAffordSpellCost, deductSpellCost } from './store-modules/computed-stats';
export {
computeMaxMana, computeRegen, computeClickMana,
getMeditationBonus,
} from './utils/mana-utils';
export {
calcDamage, calcInsight, getIncursionStrength, canAffordSpellCost, deductSpellCost,
} from './utils/combat-utils';
// ─── Initial State ───────────────────────────────────────────────────────
interface MakeInitialOptions {
loopCount?: number;
totalInsight?: number;
insight?: number;
prestigeUpgrades?: Record<string, number>;
}
export function makeInitial(opts?: MakeInitialOptions): GameState {
return {
day: 1,
hour: 0,
rawMana: 100,
maxMana: 100,
elements: {},
skills: {},
skillUpgrades: {},
skillTiers: {},
spells: {},
currentAction: 'meditate' as GameAction,
currentStudyTarget: null,
parallelStudyTarget: null,
activeSpell: null,
currentFloor: 100,
floorHP: 1000,
floorMaxHP: 1000,
currentRoom: generateFloorState(100),
maxFloorReached: 100,
paused: false,
gameOver: false,
victory: false,
loopCount: opts?.loopCount ?? 0,
totalInsight: opts?.totalInsight ?? 0,
insight: opts?.insight ?? 0,
loopInsight: 0,
prestigeUpgrades: opts?.prestigeUpgrades ?? {},
signedPacts: [],
attunements: {},
golemancy: { enabledGolems: [] },
memories: [],
memorySlots: 0,
log: [],
activityLog: [],
meditateTicks: 0,
totalManaGathered: 0,
equippedInstances: {},
equipmentInstances: {},
lootInventory: {},
blueprints: {},
spireMode: false,
};
}
// ─── Game Store Interface ─────────────────────────────────────────────────
export interface GameStore extends GameState {
// Actions
tick: () => void;
gatherMana: () => void;
setAction: (action: GameAction) => void;
addActivityLog: (eventType: string, message: string, details?: ActivityLogEntry['details']) => void;
setSpell: (spellId: string) => void;
startStudyingSkill: (skillId: string) => void;
startStudyingSpell: (spellId: string) => void;
startParallelStudySkill: (skillId: string) => void;
cancelStudy: () => void;
cancelParallelStudy: () => void;
convertMana: (element: string, amount: number) => void;
unlockElement: (element: string) => void;
doPrestige: (id: string, selectedManaType?: string) => void;
@@ -43,36 +98,21 @@ export interface GameStore extends GameState {
togglePause: () => void;
resetGame: () => void;
addLog: (message: string) => void;
selectSkillUpgrade: (skillId: string, upgradeId: string) => void;
deselectSkillUpgrade: (skillId: string, upgradeId: string) => void;
commitSkillUpgrades: (skillId: string, upgradeIds: string[], milestone?: 5 | 10) => void;
tierUpSkill: (skillId: string) => void;
// Attunement XP and leveling
addAttunementXP: (attunementId: string, amount: number) => void;
// Golemancy actions
toggleGolem: (golemId: string) => void;
setEnabledGolems: (golemIds: string[]) => void;
// Debug functions
debugUnlockAttunement: (attunementId: string) => void;
debugAddElementalMana: (element: string, amount: number) => void;
debugSetTime: (day: number, hour: number) => void;
debugAddAttunementXP: (attunementId: string, amount: number) => void;
debugSetFloor: (floor: number) => void;
resetFloorHP: () => void;
// Computed getters
getMaxMana: () => number;
getRegen: () => number;
getClickMana: () => number;
getDamage: (spellId: string) => number;
getMeditationMultiplier: () => number;
canCastSpell: (spellId: string) => boolean;
getSkillUpgradeChoices: (skillId: string, milestone: 5 | 10) => { available: SkillUpgradeChoice[]; selected: string[] };
// Spire Mode actions
enterSpireMode: () => void;
climbDownFloor: () => void;
exitSpireMode: () => void;
@@ -85,18 +125,16 @@ export const useGameStore = create<GameStore>()(
(set, get) => ({
...makeInitial(),
// Computed getters
getMaxMana: () => computeMaxMana(get()),
getRegen: () => computeRegen(get()),
getClickMana: () => computeClickMana(get()),
getDamage: (spellId: string) => calcDamage(get(), spellId),
getMeditationMultiplier: () => getMeditationBonus(get().meditateTicks, get().skills),
getMeditationMultiplier: () => getMeditationBonus(get().meditateTicks, {}),
canCastSpell: (spellId: string) => {
const state = get();
const spell = state.spells?.[spellId];
if (!spell) return false;
// Would check spell cost here
return true;
},
@@ -112,23 +150,18 @@ export const useGameStore = create<GameStore>()(
}));
},
// ─── Core Tick Logic ───────────────────────────────────────────
tick: () => {
const state = get();
if (state.gameOver || state.paused) return;
// Import and use tick logic from module
// For now, simplified version here
const maxMana = computeMaxMana(state);
const baseRegen = computeRegen(state);
// Time progression
let hour = state.hour + 1; // Simplified: HOURS_PER_TICK
let hour = state.hour + 1;
let day = state.day;
if (hour >= 24) { hour -= 24; day += 1; }
// Check for loop end
if (day > 100) { // MAX_DAY
if (day > 100) {
const insightGained = calcInsight(state);
set({
day, hour, gameOver: true, victory: false, loopInsight: insightGained,
@@ -137,7 +170,6 @@ export const useGameStore = create<GameStore>()(
return;
}
// Calculate regen
let rawMana = state.rawMana + baseRegen;
rawMana = Math.min(rawMana, maxMana);
@@ -147,7 +179,6 @@ export const useGameStore = create<GameStore>()(
});
},
// ─── Actions ────────────────────────────────────────────────
gatherMana: () => {
const state = get();
const clickMana = computeClickMana(state);
@@ -166,34 +197,10 @@ export const useGameStore = create<GameStore>()(
set({ activeSpell: spellId });
},
startStudyingSkill: (skillId: string) => {
set({
currentStudyTarget: { type: 'skill', id: skillId, progress: 0, required: 60 },
currentAction: 'study',
});
},
startStudyingSpell: (spellId: string) => {
set({
currentStudyTarget: { type: 'spell', id: spellId, progress: 0, required: 60 },
currentAction: 'study',
});
},
startParallelStudySkill: (skillId: string) => {
set({
parallelStudyTarget: { type: 'skill', id: skillId, progress: 0, required: 120 },
});
},
cancelStudy: () => {
set({ currentStudyTarget: null, currentAction: 'meditate' });
},
cancelParallelStudy: () => {
set({ parallelStudyTarget: null });
},
convertMana: (element: string, amount: number) => {
set((s) => {
const elem = s.elements?.[element];
@@ -216,7 +223,6 @@ export const useGameStore = create<GameStore>()(
},
doPrestige: (id: string, selectedManaType?: string) => {
// Simplified prestige logic
set((s) => ({
prestigeUpgrades: { ...s.prestigeUpgrades, [id]: (s.prestigeUpgrades[id] || 0) + 1 },
}));
@@ -226,8 +232,8 @@ export const useGameStore = create<GameStore>()(
const state = get();
const insightGained = state.loopInsight || 0;
set({
...makeInitial({
loopCount: state.loopCount + 1,
...makeInitial({
loopCount: state.loopCount + 1,
totalInsight: (state.totalInsight || 0) + insightGained,
insight: (state.insight || 0) + insightGained,
prestigeUpgrades: state.prestigeUpgrades,
@@ -243,39 +249,6 @@ export const useGameStore = create<GameStore>()(
set(makeInitial());
},
selectSkillUpgrade: (skillId: string, upgradeId: string) => {
set((s) => {
const currentUpgrades = s.skillUpgrades?.[skillId] || { selected: [], available: [] };
return {
skillUpgrades: { ...s.skillUpgrades, [skillId]: { ...currentUpgrades, selected: [...currentUpgrades.selected, upgradeId] } },
};
});
},
deselectSkillUpgrade: (skillId: string, upgradeId: string) => {
set((s) => {
const currentUpgrades = s.skillUpgrades?.[skillId] || { selected: [], available: [] };
return {
skillUpgrades: { ...s.skillUpgrades, [skillId]: { ...currentUpgrades, selected: currentUpgrades.selected.filter(id => id !== upgradeId) } },
};
});
},
commitSkillUpgrades: (skillId: string, upgradeIds: string[], milestone?: 5 | 10) => {
set((s) => {
const currentUpgrades = s.skillUpgrades?.[skillId] || { selected: [], available: [] };
return {
skillUpgrades: { ...s.skillUpgrades, [skillId]: { ...currentUpgrades, committed: upgradeIds, milestone } },
};
});
},
tierUpSkill: (skillId: string) => {
set((s) => ({
skillTiers: { ...s.skillTiers, [skillId]: (s.skillTiers?.[skillId] || 1) + 1 },
}));
},
addAttunementXP: (attunementId: string, amount: number) => {
set((s) => {
const attState = s.attunements?.[attunementId];
@@ -302,7 +275,6 @@ export const useGameStore = create<GameStore>()(
}));
},
// Debug functions
debugUnlockAttunement: (attunementId: string) => {
set((s) => ({
attunements: { ...s.attunements, [attunementId]: { id: attunementId, active: true, level: 1, experience: 0 } },
@@ -331,7 +303,7 @@ export const useGameStore = create<GameStore>()(
set((s) => ({
currentFloor: floor,
currentRoom: generateFloorState(floor),
floorMaxHP: 100 + floor * 50, // Simplified getFloorMaxHP
floorMaxHP: 100 + floor * 50,
floorHP: 100 + floor * 50,
}));
},
@@ -343,14 +315,6 @@ export const useGameStore = create<GameStore>()(
}));
},
getSkillUpgradeChoices: (skillId: string, milestone: 5 | 10) => {
const state = get();
const skillDef = state.spells?.[skillId];
// Simplified - would return actual upgrade choices
return { available: [], selected: [] };
},
// Spire Mode actions
enterSpireMode: () => {
set({ spireMode: true });
},
@@ -362,7 +326,7 @@ export const useGameStore = create<GameStore>()(
return {
currentFloor: newFloor,
currentRoom: generateFloorState(newFloor),
floorMaxHP: 100 + newFloor * 50, // Simplified
floorMaxHP: 100 + newFloor * 50,
floorHP: 100 + newFloor * 50,
};
});
@@ -384,7 +348,7 @@ export function useGameLoop() {
const tick = useGameStore((s) => s.tick);
return {
start: () => {
const interval = setInterval(tick, 1000); // TICK_MS
const interval = setInterval(tick, 1000);
return () => clearInterval(interval);
},
};