"use client"; // 回响星核 / Echo Nexus — 主循环 hook import { useEffect, useRef } from "react"; import { useGameStore } from "@/store/gameStore"; /** 250ms tick:产能 + 自动产晶体 + 自动解码 + 星潮 + 成就检测 */ export function useGameLoop() { const tick = useGameStore((s) => s.tick); const autoDecodeTick = useGameStore((s) => s.autoDecodeTick); const tickTide = useGameStore((s) => s.tickTide); const checkAchievements = useGameStore((s) => s.checkAchievements); const init = useGameStore((s) => s.init); const inited = useRef(false); useEffect(() => { // 等待 persist rehydrate 完成后再 init(v0.5.2 修复离线收益不弹窗 BUG) // Zustand persist 即使用同步 localStorage,rehydrate 也是异步(Promise.resolve 包装) const doInit = () => { if (!inited.current) { init(); inited.current = true; } }; let unsub: (() => void) | null = null; let fallback: ReturnType | null = null; if (useGameStore.persist.hasHydrated()) { doInit(); } else { unsub = useGameStore.persist.onFinishHydration(doInit); // 兜底:500ms 后强制 init(防止 hydrated 状态异常) fallback = setTimeout(doInit, 500); } let counter = 0; const id = setInterval(() => { const now = Date.now(); tick(now); autoDecodeTick(); // 星潮检测每 tick 都查(结束/触发判定需及时) tickTide(now); counter++; // 成就检测每秒执行一次(降低开销) if (counter % 4 === 0) { checkAchievements(); } }, 250); return () => { clearInterval(id); if (unsub) unsub(); if (fallback) clearTimeout(fallback); }; }, [tick, autoDecodeTick, tickTide, checkAchievements, init]); // 页面可见性:切回时补 tick + 星潮 + 成就 useEffect(() => { const onVis = () => { if (document.visibilityState === "visible") { tick(Date.now()); tickTide(Date.now()); checkAchievements(); } }; document.addEventListener("visibilitychange", onVis); return () => document.removeEventListener("visibilitychange", onVis); }, [tick, tickTide, checkAchievements]); }