import { useState, useEffect, useCallback, useMemo } from "react"; import { getCurrentWindow } from "@tauri-apps/api/window"; import { TauriService } from "../services/TauriService"; const appWindow = getCurrentWindow(); const BASE_EDITIONS = [ { id: "legacy_evolved", name: "Legacy Evolved", desc: "Backporting the newer title updates back to the LCE", url: "https://codeberg.org/piebot/LegacyEvolved/releases/download/nightly/LCEWindows64.zip", titleImage: "/images/minecraft_title_LegacyEvolved.png", }, { id: "revelations", name: "Legacy Revelations", desc: "QoL, performance, hardcore mode, & security features for LCE.", url: "https://github.com/itsRevela/MinecraftConsoles/releases/download/Nightly/LCREWindows64.zip", titleImage: "/images/minecraft_title_revelations.png" }, { id: "vanilla_tu19", name: "Title Update 19", desc: "Leaked 4J Studios build. (smartcmd)", url: "https://github.com/smartcmd/MinecraftConsoles/releases/download/nightly/LCEWindows64.zip", titleImage: "/images/minecraft_title_tu19.png", }, { id: "360revived", name: "360Revived", desc: "PC port of Xbox 360 Edition TU19", url: "https://github.com/BluTac10/360Revived/releases/download/nightly/LCEWindows64.zip", titleImage: "/images/minecraft_title_360revived.png", }, ]; const PARTNERSHIP_SERVERS = [ { name: "Kowhaifans Clubhouse", ip: "kowhaifan.ddns.net", port: 25565, }, ]; interface GameManagerProps { profile: string; setProfile: (id: string) => void; customEditions: any[]; setCustomEditions: (editions: any[]) => void; keepLauncherOpen: boolean; } export function useGameManager({ profile, setProfile, customEditions, setCustomEditions, keepLauncherOpen }: GameManagerProps) { const [installs, setInstalls] = useState([]); const [isGameRunning, setIsGameRunning] = useState(false); const [downloadProgress, setDownloadProgress] = useState(null); const [downloadingId, setDownloadingId] = useState(null); const [isRunnerDownloading, setIsRunnerDownloading] = useState(false); const [runnerDownloadProgress, setRunnerDownloadProgress] = useState(null); const [error, setError] = useState(null); const editions = useMemo(() => [...BASE_EDITIONS, ...customEditions], [customEditions]); const checkInstalls = useCallback(async () => { const results = await Promise.all( editions.map(async (e) => { const isInstalled = await TauriService.checkGameInstalled(e.id); return isInstalled ? e.id : null; }), ); setInstalls(results.filter((id): id is string => id !== null)); }, [editions]); useEffect(() => { checkInstalls(); const unlistenDownload = TauriService.onDownloadProgress((p) => setDownloadProgress(p)); const unlistenRunner = TauriService.onRunnerDownloadProgress((p) => setRunnerDownloadProgress(p)); return () => { unlistenDownload.then((u) => u()); unlistenRunner.then((u) => u()); }; }, [customEditions, checkInstalls]); const downloadRunner = useCallback(async (name: string, url: string) => { if (isRunnerDownloading) return; setIsRunnerDownloading(true); setRunnerDownloadProgress(0); setError(null); try { await TauriService.downloadRunner(name, url); setRunnerDownloadProgress(null); } catch (e: any) { console.error(e); setError(typeof e === 'string' ? e : e.message || "Failed to download runner"); } finally { setIsRunnerDownloading(false); } }, [isRunnerDownloading]); const toggleInstall = useCallback(async (id: string) => { if (downloadingId) return; const edition = editions.find((e) => e.id === id); if (!edition) return; setError(null); try { setDownloadingId(id); setDownloadProgress(0); await TauriService.downloadAndInstall(edition.url, id); await TauriService.syncDlc(id); await checkInstalls(); setProfile(id); setDownloadProgress(null); setDownloadingId(null); } catch (e: any) { console.error(e); setError(typeof e === 'string' ? e : e.message || "Failed to install version"); setDownloadProgress(null); setDownloadingId(null); } }, [downloadingId, editions, checkInstalls, setProfile]); const handleUninstall = useCallback(async (id: string) => { await TauriService.deleteInstance(id); await checkInstalls(); }, [checkInstalls]); const handleLaunch = useCallback(async () => { if (isGameRunning) return; setError(null); setIsGameRunning(true); try { if (!keepLauncherOpen) { await appWindow.hide(); } await TauriService.launchGame(profile, PARTNERSHIP_SERVERS); } catch (e: any) { console.error(e); setError(typeof e === 'string' ? e : e.message || "Failed to launch game"); } finally { setIsGameRunning(false); await appWindow.show(); await appWindow.unminimize(); await appWindow.setFocus(); } }, [isGameRunning, profile]); const stopGame = useCallback(async () => { try { await TauriService.stopGame(profile); setIsGameRunning(false); } catch (e) { console.error(e); } }, [profile]); const addCustomEdition = useCallback((edition: { name: string; desc: string; url: string }) => { const id = `custom_${Date.now()}`; const newEdition = { ...edition, id, titleImage: "/images/minecraft_title_tucustom.png" }; setCustomEditions([...customEditions, newEdition]); return id; }, [customEditions, setCustomEditions]); const deleteCustomEdition = useCallback((id: string) => { setCustomEditions(customEditions.filter((e) => e.id !== id)); TauriService.deleteInstance(id).catch(console.error); }, [customEditions, setCustomEditions]); const updateCustomEdition = useCallback((id: string, updated: { name: string; desc: string; url: string }) => { setCustomEditions(customEditions.map((e) => e.id === id ? { ...e, ...updated } : e)); }, [customEditions, setCustomEditions]); return { installs, isGameRunning, downloadProgress, downloadingId, isRunnerDownloading, runnerDownloadProgress, error, setError, editions, toggleInstall, handleUninstall, handleLaunch, stopGame, addCustomEdition, deleteCustomEdition, updateCustomEdition, downloadRunner, checkInstalls, }; }