diff --git a/Doc/G-LAUNCHER-HANDOFF.md b/Doc/G-LAUNCHER-HANDOFF.md index 90eaf28..75bb57a 100644 --- a/Doc/G-LAUNCHER-HANDOFF.md +++ b/Doc/G-LAUNCHER-HANDOFF.md @@ -68,6 +68,15 @@ * **สาเหตุ:** Git พยายามเปิด Interactive Prompt เพื่อถาม Username/Password ในเทอร์มินัลที่ไม่มี TTY * **แนวทางแก้ไข:** ต้องตั้งค่า `$env:GIT_TERMINAL_PROMPT = "0"` ใน PowerShell หรือ `os.Setenv("GIT_TERMINAL_PROMPT", "0")` ใน Go ก่อนเรียกคำสั่ง Git เสมอ +### กับดักที่ 6: โครงสร้างไฟล์ GaCy-GO (for ship/sdkserver) และการตัด Firefly Proxy +* **อาการ:** ตัวเกม Star Rail ฟ้อง `Network connection error: Please check your network state, disable any network proxies...` และ Launcher หาเซิร์ฟเวอร์ไม่พบ +* **สาเหตุ:** + 1. ไฟล์ Zip ของ `gacy 4.6.54.zip` แตกไฟล์ออกมามีโฟลเดอร์ย่อยชื่อ `for ship` บรรจุ `sdkserver-go.exe` หากค้นหาเฉพาะโฟลเดอร์ root จะมองไม่เห็น SDK Server ทำให้ Dispatch Server ไม่ถูกเปิด + 2. โค้ดเดิมยังคงสั่งรัน `firefly-go-proxy.exe` เข้าไปดักจับและเปลี่ยนระบบ Proxy ของ Windows ทำให้ Client ของ Star Rail ตรวจจับว่ามี Proxy แปลกปลอมและปฏิเสธการเชื่อมต่อ +* **แนวทางแก้ไข:** + 1. ปรับปรุง `FindServerExecutables()` ใน Go ให้ค้นหาไฟล์ไบนารีแบบ **Recursive Search** ทุกโฟลเดอร์ย่อย (`for ship`, `sdkserver`) และทำ Auto-Sync ไฟล์จาก `for ship` ขึ้นมาที่ root ของ `server/` + 2. ตัดระบบ `firefly-go-proxy` ออกจากการเริ่มเล่น GaCy PS 100% โดยเรียงลำดับการเปิด: **SDK Server (Dispatch) -> รอ 800ms -> Game Server -> รอ 1000ms -> เปิดตัวเกม** + --- ## 3. รายละเอียดสถาปัตยกรรมระบบอัปเดต (Isolated Updater Architecture) diff --git a/frontend/src/helper/server.ts b/frontend/src/helper/server.ts index b7d577a..f0cf87c 100644 --- a/frontend/src/helper/server.ts +++ b/frontend/src/helper/server.ts @@ -9,14 +9,20 @@ export async function CheckUpdateServer( serverVersion: string ): Promise<{ isUpdate: boolean; isExists: boolean; version: string }> { const [ok, latestVersion, error] = await GitService.GetLatestServerVersion() - let isExists = await FSService.FileExists(serverPath) + let isExists = false - if (!isExists) { - const [gameServer] = await GitService.FindServerExecutables() - if (gameServer) { - useSettingStore.getState().setServerPath(gameServer) - isExists = true - } + const [gameServer, sdkServer] = await GitService.FindServerExecutables() + if (gameServer) { + useSettingStore.getState().setServerPath(gameServer) + isExists = true + } + if (sdkServer) { + useSettingStore.getState().setSdkServerPath(sdkServer) + isExists = true + } + + if (!isExists && serverPath) { + isExists = await FSService.FileExists(serverPath) } if (!ok) { @@ -39,7 +45,9 @@ export async function UpdateServer(serverVersion: string) : Promise { const [gameServer, sdkServer] = await GitService.FindServerExecutables() setDownloadType("Download server successfully") setServerVersion(serverVersion) - setServerPath(gameServer || "./server/gameserver-go.exe") + if (gameServer) { + setServerPath(gameServer) + } if (sdkServer) { setSdkServerPath(sdkServer) } diff --git a/frontend/src/pages/launcher/index.tsx b/frontend/src/pages/launcher/index.tsx index 1003b8e..dd51b2f 100644 --- a/frontend/src/pages/launcher/index.tsx +++ b/frontend/src/pages/launcher/index.tsx @@ -10,7 +10,7 @@ import useModalStore from '@/stores/modalStore'; import useLauncherStore from '@/stores/launcherStore'; import { motion } from 'motion/react'; import { Link } from '@tanstack/react-router'; -import { CheckUpdateLauncher, CheckUpdateProxy, CheckUpdateServer, sleep, UpdateLauncher, UpdateProxy, UpdateServer } from '@/helper'; +import { CheckUpdateLauncher, CheckUpdateServer, sleep, UpdateLauncher, UpdateProxy, UpdateServer } from '@/helper'; import UpdateModal from '@/components/updateModal'; import { BackgroundSelector } from '@/components/backgroudModal'; import { useTranslation } from 'react-i18next'; @@ -25,11 +25,9 @@ export default function LauncherPage() { setServerPath, sdkServerPath, setSdkServerPath, - proxyPath, - gameDir, + gameDir, serverVersion, - proxyVersion, - background, + background, selectedServer, setSelectedServer } = useSettingStore() @@ -48,8 +46,7 @@ export default function LauncherPage() { downloadType, isDownloading, serverRunning, - proxyRunning, - gameRunning, + gameRunning, progressDownload, downloadSpeed, updateData, @@ -60,8 +57,7 @@ export default function LauncherPage() { setProxyReady, setIsDownloading, setServerRunning, - setProxyRunning, - setGameRunning, + setGameRunning, setUpdateData, } = useLauncherStore() @@ -88,31 +84,25 @@ export default function LauncherPage() { useEffect(() => { const check = async () => { - if (!serverVersion || !proxyVersion) { - setServerReady(false) - setProxyReady(false) - return + const [gameServer, sdkServer] = await GitService.FindServerExecutables() + let serverExists = false + if (gameServer) { + setServerPath(gameServer) + serverExists = true } - - let serverExists = await FSService.FileExists(serverPath) - if (!serverExists) { - const [gameServer, sdkServer] = await GitService.FindServerExecutables() - if (gameServer) { - setServerPath(gameServer) - serverExists = true - } - if (sdkServer) { - setSdkServerPath(sdkServer) - } + if (sdkServer) { + setSdkServerPath(sdkServer) + serverExists = true + } + if (!serverExists && serverPath) { + serverExists = await FSService.FileExists(serverPath) } - - const proxyExists = await FSService.FileExists(proxyPath) setServerReady(serverExists) - setProxyReady(proxyExists) + setProxyReady(true) } check() - }, [serverPath, proxyPath, serverVersion, proxyVersion]) + }, [serverPath, serverVersion]) useEffect(() => { const checkStartUp = async (): Promise => { @@ -122,34 +112,30 @@ export default function LauncherPage() { if (launcherData.isUpdate) { setUpdateData({ server: { isUpdate: false, isExists: false, version: "" }, - proxy: { isUpdate: false, isExists: false, version: "" }, + proxy: { isUpdate: false, isExists: true, version: "" }, launcher: launcherData }) setIsOpenSelfUpdateModal(true) return } const serverData = await CheckUpdateServer(serverPath, serverVersion) - const proxyData = await CheckUpdateProxy(proxyPath, proxyVersion) - setUpdateData({ + setUpdateData({ server: serverData, - proxy: proxyData, + proxy: { isUpdate: false, isExists: true, version: "" }, launcher: launcherData }) - if (!serverData.isExists || !proxyData.isExists) { + if (!serverData.isExists) { setServerReady(false) - setProxyReady(false) return } - if (serverData.isUpdate || proxyData.isUpdate) { + if (serverData.isUpdate) { setServerReady(true) - setProxyReady(true) setIsOpenUpdateDataModal(true) return } setServerReady(true) - setProxyReady(true) } checkStartUp() }, []); @@ -188,7 +174,7 @@ export default function LauncherPage() { } const handleStartGame = async () => { - await FSService.LogMessage("INFO", "handleStartGame initiated: selectedServer=" + selectedServer + ", gamePath=" + gamePath + ", serverPath=" + serverPath + ", proxyPath=" + proxyPath) + await FSService.LogMessage("INFO", "handleStartGame initiated: selectedServer=" + selectedServer + ", gamePath=" + gamePath + ", serverPath=" + serverPath) if (!gamePath) { await FSService.LogMessage("WARN", "handleStartGame aborted: gamePath is empty") toast.info("Please select the game executable first") @@ -205,46 +191,33 @@ export default function LauncherPage() { await FSService.LogMessage("INFO", "handleStartGame: querying GaCy PS server executables...") const [gameServer, sdkServer] = await GitService.FindServerExecutables() const activeServer = gameServer || serverPath - await FSService.LogMessage("INFO", "handleStartGame: found gameServer=" + gameServer + ", sdkServer=" + sdkServer + ", activeServer=" + activeServer) + const activeSdk = sdkServer || sdkServerPath + await FSService.LogMessage("INFO", "handleStartGame: found gameServer=" + gameServer + ", sdkServer=" + sdkServer + ", activeServer=" + activeServer + ", activeSdk=" + activeSdk) - if (!activeServer) { - await FSService.LogMessage("ERROR", "handleStartGame: activeServer missing. Opening download modal.") + if (!activeServer && !activeSdk) { + await FSService.LogMessage("ERROR", "handleStartGame: neither gameServer nor sdkServer found. Opening download modal.") toast.error("Please download GaCy PS server files first") setIsOpenDownloadDataModal(true) return } - // 1. Start Proxy - const activeProxy = proxyPath || "./proxy/firefly-go-proxy.exe" - await FSService.LogMessage("INFO", "handleStartGame: activeProxy=" + activeProxy + ", proxyRunning=" + proxyRunning) - if (!proxyRunning && !gamePath.endsWith("launcher.exe")) { - await FSService.LogMessage("INFO", "handleStartGame: starting proxy via StartWithConsole(" + activeProxy + ")") - const [resultProxy, error] = await FSService.StartWithConsole(activeProxy) - if (!resultProxy) { - await FSService.LogMessage("ERROR", "handleStartGame: proxy start failed: " + error) - toast.error(t("home.toast_start_proxy_failed") + ": " + error) - return - } - await FSService.LogMessage("INFO", "handleStartGame: proxy started successfully") - setProxyRunning(true) - } - await sleep(500) - - // 2. Start SDK Server if exists - const activeSdk = sdkServer || sdkServerPath + // 1. Start SDK Server first (handles dispatch & login) if (activeSdk) { - await FSService.LogMessage("INFO", "handleStartGame: starting SDK server via StartWithConsole(" + activeSdk + ")") + await FSService.LogMessage("INFO", "handleStartGame: starting SDK Server via StartWithConsole(" + activeSdk + ")") const [resultSdk, sdkErr] = await FSService.StartWithConsole(activeSdk) if (!resultSdk) { - await FSService.LogMessage("WARN", "handleStartGame: SDK server start warning: " + sdkErr) - } else { - await FSService.LogMessage("INFO", "handleStartGame: SDK server started successfully") + await FSService.LogMessage("ERROR", "handleStartGame: SDK server start failed: " + sdkErr) + toast.error("Failed to start SDK Server: " + sdkErr) + return } - await sleep(400) + await FSService.LogMessage("INFO", "handleStartGame: SDK server started successfully") + await sleep(800) + } else { + await FSService.LogMessage("WARN", "handleStartGame: activeSdk not found! Proceeding with gameServer only.") } - // 3. Start Game Server - if (!serverRunning) { + // 2. Start Game Server second + if (activeServer && !serverRunning) { await FSService.LogMessage("INFO", "handleStartGame: starting Game server via StartWithConsole(" + activeServer + ")") const [resultServer, error] = await FSService.StartWithConsole(activeServer) if (!resultServer) { @@ -254,10 +227,10 @@ export default function LauncherPage() { } await FSService.LogMessage("INFO", "handleStartGame: Game server started successfully") setServerRunning(true) + await sleep(1000) } - await sleep(1000) } else { - await FSService.LogMessage("INFO", "handleStartGame: running in Official Server mode (no proxy/PS)") + await FSService.LogMessage("INFO", "handleStartGame: running in Official Server mode (no PS)") } // 4. Start Game @@ -473,18 +446,17 @@ export default function LauncherPage() { -
  • - -