'use client'; import { useEffect, useState, lazy, Suspense } from 'react'; import type { JSX } from 'react'; // Import from new modular stores import { useGameStore, useUIStore, useManaStore, useSkillStore, useCombatStore, usePrestigeStore, useCraftingStore, fmt, computeMaxMana, computeRegen, computeClickMana, getMeditationBonus, getIncursionStrength, } from '@/lib/game/stores'; import { useGameLoop } from '@/lib/game/stores/gameHooks'; import { getUnifiedEffects } from '@/lib/game/effects'; import { getStudySpeedMultiplier, getStudyCostMultiplier, SPELLS_DEF, ELEMENTS, GUARDIANS, } from '@/lib/game/constants'; import { getActiveEquipmentSpells, getTotalDPS } from '@/lib/game/computed-stats'; import { TimeDisplay } from '@/components/game'; import { hasSpecial, SPECIAL_EFFECTS } from '@/lib/game/effects'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { ScrollArea } from '@/components/ui/scroll-area'; import { RotateCcw, Mountain } from 'lucide-react'; import { TooltipProvider } from '@/components/ui/tooltip'; import { ErrorBoundary } from '@/components/ErrorBoundary'; // Import extracted components import { GameOverScreen } from './components/GameOverScreen'; import { LeftPanel } from './components/LeftPanel'; // Lazy load tab components const SpireTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.SpireTab }))); const SkillsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.SkillsTab }))); const SpellsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.SpellsTab }))); const LabTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.LabTab }))); const StatsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.StatsTab }))); const EquipmentTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.EquipmentTab }))); const AttunementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AttunementsTab }))); const DebugTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.DebugTab }))); const LootTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.LootTab }))); const AchievementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AchievementsTab }))); const GolemancyTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.GolemancyTab }))); const CraftingTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.CraftingTab }))); const TabLoadingFallback = () =>
Loading...
; // ============================================================================ // Grimoire Tab Component // ============================================================================ function GrimoireTab() { // Handle SSR - dont access SPELLS_DEF during server-side rendering // Use state and useEffect to only access on client-side const [grimoireSpells, setGrimoireSpells] = useState([]); useEffect(() => { // Only access SPELLS_DEF on client-side if (typeof window !== 'undefined' && SPELLS_DEF) { const filtered = Object.values(SPELLS_DEF || {}).filter((s: any) => s.grimoire); // eslint-disable-next-line react-hooks/set-state-in-effect setGrimoireSpells(filtered); } }, []); if (!grimoireSpells.length) { return
Loading grimoire...
; } const availablePages = Math.ceil(grimoireSpells.length / 12); return (

A vast tome of arcane knowledge. Study carefully — each spell costs insight to transcribe into your repertoire.

Available pages: {availablePages}. Spells in grimoire: {grimoireSpells.length}.

{grimoireSpells.map((spell: any) => (
{spell.name} {spell.element}

{spell.desc}

Cost: {(spell.cost as any[]).map((c: any) => `${c.amount} ${c.type}`).join(', ')}
Power: {spell.power}
{spell.effect &&
Effect: {spell.effect}
}
))}
); } // ============================================================================ // Main Game Component // ============================================================================ export default function ManaLoopGame() { const [selectedManaType, setSelectedManaType] = useState(''); const [activeTab, setActiveTab] = useState('spire'); // ALL hooks must be called before any conditional returns const day = useGameStore((s) => s.day); const hour = useGameStore((s) => s.hour); const initGame = useGameStore((s) => s.initGame); useGameLoop(); const skills = useSkillStore((s) => s.skills); const skillTiers = useSkillStore((s) => s.skillTiers); const skillUpgrades = useSkillStore((s) => s.skillUpgrades); const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades); const insight = usePrestigeStore((s) => s.insight); const rawMana = useManaStore((s) => s.rawMana); const meditateTicks = useManaStore((s) => s.meditateTicks); const maxFloorReached = useCombatStore((s) => s.maxFloorReached); const spells = useCombatStore((s) => s.spells); const gameOver = useUIStore((s) => s.gameOver); // Get equipment state from crafting store const equippedInstances = useCraftingStore((s) => s.equippedInstances); const equipmentInstances = useCraftingStore((s) => s.equipmentInstances); // Derived state const upgradeEffects = getUnifiedEffects({ skillUpgrades, skillTiers, equippedInstances, equipmentInstances }); const maxMana = computeMaxMana({ skills, prestigeUpgrades, skillUpgrades, skillTiers }, upgradeEffects); const baseRegen = computeRegen({ skills, prestigeUpgrades, skillUpgrades, skillTiers }, upgradeEffects); const clickMana = computeClickMana({ skills, prestigeUpgrades, skillUpgrades, skillTiers }); const meditationMultiplier = getMeditationBonus(meditateTicks, skills, upgradeEffects.meditationEfficiency); const incursionStrength = getIncursionStrength(day, hour); // Effective regen with incursion penalty const effectiveRegenWithSpecials = baseRegen * (1 - incursionStrength); // Mana Cascade bonus const manaCascadeBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_CASCADE) ? Math.floor(maxMana / 100) * 0.1 : 0; // Mana Waterfall bonus const manaWaterfallBonus = hasSpecial(upgradeEffects, SPECIAL_EFFECTS.MANA_WATERFALL) ? Math.floor(maxMana / 100) * 0.25 : 0; // Effective regen const effectiveRegen = (effectiveRegenWithSpecials + manaCascadeBonus + manaWaterfallBonus) * meditationMultiplier; // Initialize game on mount useEffect(() => { initGame(); }, [initGame]); // Conditional returns AFTER all hooks if (gameOver) { return ; } if (typeof window === 'undefined') { return
Loading...
; } return (
{/* Header */}

MANA LOOP

{/* Main Content */}
⚔️ Spire ✨ Attune 🗿 Golems 📚 Skills 🔮 Spells 🛡️ Gear 🔧 Craft 💎 Loot 🏆 Achieve 🔬 Lab 📊 Stats 🐛 Debug 📖 Grimoire spire tab failed to load.
}> }> attunements tab failed to load.
}> }>
golemancy tab failed to load.}> }> skills tab failed to load.}> }> spells tab failed to load.}> }> equipment tab failed to load.}> }> crafting tab failed to load.}> }> loot tab failed to load.}> }> achievements tab failed to load.}> }> lab tab failed to load.}> }> stats tab failed to load.}> }> debug tab failed to load.}> }> ); }