From f2a36fe1882d23b1a8d87f3887b3c6a739528dbd Mon Sep 17 00:00:00 2001 From: CAtlas0784 Date: Fri, 18 Sep 2026 13:45:27 +0700 Subject: [PATCH] feat(minigame): add multi-arcade minigame catalog (KOF97, Metal Slug, Piano, Drumkit, Bowling, Basketball) and fix in-engine panel launcher --- .../proxy/public/fastpatch_4229938.zip | Bin 11167 -> 11966 bytes .../tools/generate_client_config_patch.js | 120 +++++++++++++++--- Ananta.Server/Ananta.App/DebugApiServer.cs | 51 +++++++- .../Ananta.App/DebugPanel/index.html | 61 ++++++++- 4 files changed, 207 insertions(+), 25 deletions(-) diff --git a/Ananta.Proxy/proxy/public/fastpatch_4229938.zip b/Ananta.Proxy/proxy/public/fastpatch_4229938.zip index e79d75d06a23342a9b9984bb50c4d636cab167fd..61ef2224648ce34e36d84c8464086625ab55f61c 100644 GIT binary patch delta 10208 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 a00000wt+AylPxATlZh)32DB{z0000bbGw-U delta 9372 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 Wwt*2QlT0Z#lc+8b29+uR0002uGC)`W diff --git a/Ananta.Proxy/proxy/tools/generate_client_config_patch.js b/Ananta.Proxy/proxy/tools/generate_client_config_patch.js index 9858e6e..1f1f5b0 100644 --- a/Ananta.Proxy/proxy/tools/generate_client_config_patch.js +++ b/Ananta.Proxy/proxy/tools/generate_client_config_patch.js @@ -825,25 +825,115 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` end\n` + ` end)\n` + ` end)\n` + -` elseif cmd == "LAUNCH_MINIGAME:FIGHTER" then\n` + +` elseif string.sub(cmd, 1, 16) == "LAUNCH_MINIGAME:" or string.sub(cmd, 1, 20) == "CMD:LAUNCH_MINIGAME:" or string.sub(cmd, 1, 9) == "MINIGAME:" or string.sub(cmd, 1, 13) == "CMD:MINIGAME:" then\n` + +` local rawGame = string.match(cmd, "MINIGAME:([^:]+)") or "KOF97"\n` + +` local gameType = string.upper(rawGame)\n` + ` pcall(function()\n` + -` if gPanelManager and gPanelId and gPanelId.S_FIGHTER_MINIGAME_PANEL then\n` + -` gPanelManager:OpenWindow(gPanelId.S_FIGHTER_MINIGAME_PANEL)\n` + -` elseif CS and CS.L18 and CS.L18.MiniGame and CS.L18.MiniGame.Fighter and CS.L18.MiniGame.Fighter.FighterMinigame then\n` + -` local mg = CS.L18.MiniGame.Fighter.FighterMinigame.Instance\n` + -` if mg then\n` + -` mg.GameStarted = true\n` + -` pcall(function() mg:CreatePlayer() end)\n` + -` pcall(function() mg:CreateEnemy() end)\n` + +` local function forceShow(panelId, data)\n` + +` if not panelId or not gPanelManager then return false end\n` + +` local ok = false\n` + +` pcall(function()\n` + +` if gPanelManager.panelData then\n` + +` gPanelManager.panelData[panelId] = data\n` + +` end\n` + +` if LX6 and LX6.Manager and LX6.Manager.PanelManager and LX6.Manager.PanelManager.Instance then\n` + +` LX6.Manager.PanelManager.Instance:CheckShowFromLua(panelId, nil, nil, -1, -1)\n` + +` ok = true\n` + +` elseif gPanelManager.CheckShow then\n` + +` ok = gPanelManager:CheckShow(panelId, data)\n` + +` end\n` + +` end)\n` + +` return ok\n` + +` end\n` + +` local myUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + +` local pObj = myUnit and myUnit.PlayerObj\n` + +` local pPos = (pObj and pObj.transform and pObj.transform.position) or (UnityEngine and UnityEngine.Vector3 and UnityEngine.Vector3.zero) or Vector3.zero\n` + +` local pRot = (pObj and pObj.transform and pObj.transform.rotation) or (UnityEngine and UnityEngine.Quaternion and UnityEngine.Quaternion.identity) or Quaternion.identity\n` + +` local pScale = (UnityEngine and UnityEngine.Vector3 and UnityEngine.Vector3.one) or Vector3.one\n` + +` local fArgs = {\n` + +` position = pPos,\n` + +` rotation = pRot,\n` + +` localScale = pScale,\n` + +` forbidClickExit = false,\n` + +` autoCloseAfterWin = -1,\n` + +` ignoreCountdown = false\n` + +` }\n` + +` local tip = "Launched Minigame: " .. tostring(gameType)\n` + +` if gameType == "KOF97" then\n` + +` if gPanelId and gPanelId.LIBRETRO_PANEL then\n` + +` forceShow(gPanelId.LIBRETRO_PANEL, { gameType = 1 })\n` + +` tip = "Opened Arcade: The King of Fighters 97 (ตู้เกม KOF '97)"\n` + +` end\n` + +` elseif gameType == "METALSLUG" then\n` + +` if gPanelId and gPanelId.LIBRETRO_PANEL then\n` + +` forceShow(gPanelId.LIBRETRO_PANEL, { gameType = 0 })\n` + +` tip = "Opened Arcade: Metal Slug (ตู้เกม Metal Slug)"\n` + +` end\n` + +` elseif gameType == "FIGHTER" then\n` + +` local shown = false\n` + +` if gPanelId and gPanelId.FIGHTER_MAIN_PANEL then\n` + +` shown = forceShow(gPanelId.FIGHTER_MAIN_PANEL, fArgs)\n` + +` end\n` + +` if gPanelId and gPanelId.FIGHTER_HUD_PANEL then\n` + +` forceShow(gPanelId.FIGHTER_HUD_PANEL, fArgs)\n` + +` end\n` + +` if not shown and gPanelId and gPanelId.LIBRETRO_PANEL then\n` + +` forceShow(gPanelId.LIBRETRO_PANEL, { gameType = 1 })\n` + +` tip = "Opened Arcade: The King of Fighters 97 (KOF)"\n` + +` else\n` + +` tip = "Opened 3D Arcade Fighter Minigame"\n` + +` end\n` + +` elseif gameType == "PIANO" then\n` + +` if gPanelId and gPanelId.UI_PANEL__INSTRUMENT__PIANO then\n` + +` forceShow(gPanelId.UI_PANEL__INSTRUMENT__PIANO)\n` + +` tip = "Opened Grand Piano Minigame"\n` + +` end\n` + +` elseif gameType == "DRUMKIT" then\n` + +` if gPanelId and gPanelId.UI_PANEL__INSTRUMENT__DRUMKIT then\n` + +` forceShow(gPanelId.UI_PANEL__INSTRUMENT__DRUMKIT)\n` + +` tip = "Opened Drumkit Minigame"\n` + +` end\n` + +` elseif gameType == "BOWLING" then\n` + +` if gPanelId and gPanelId.MINI_GAMES_BOWLING_MAIN_PANEL then\n` + +` forceShow(gPanelId.MINI_GAMES_BOWLING_MAIN_PANEL)\n` + +` tip = "Opened Bowling Minigame"\n` + +` end\n` + +` elseif gameType == "BASKETBALL" then\n` + +` if gPanelId and gPanelId.BASKETBALL_SHOOT_PANEL then\n` + +` forceShow(gPanelId.BASKETBALL_SHOOT_PANEL)\n` + +` tip = "Opened Basketball Shoot Minigame"\n` + ` end\n` + ` end\n` + -` local tip = "Launched Arcade Fighter Minigame"\n` + -` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + -` gDisplayMessageMgr:ShowMessageContent(tip)\n` + -` end\n` + -` if gCS and gCS.MessageTipsMgr and gCS.MessageTipsMgr.ShowMessageTips then\n` + -` gCS.MessageTipsMgr:ShowMessageTips(tip)\n` + +` pcall(function()\n` + +` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + +` gDisplayMessageMgr:ShowMessageContent(tip)\n` + +` end\n` + +` if gCS and gCS.MessageTipsMgr and gCS.MessageTipsMgr.ShowMessageTips then\n` + +` gCS.MessageTipsMgr:ShowMessageTips(tip)\n` + +` end\n` + +` end)\n` + +` end)\n` + +` elseif cmd == "CLOSE_MINIGAME" or cmd == "CMD:CLOSE_MINIGAME" then\n` + +` pcall(function()\n` + +` local toClose = {\n` + +` gPanelId and gPanelId.LIBRETRO_PANEL,\n` + +` gPanelId and gPanelId.FIGHTER_MAIN_PANEL,\n` + +` gPanelId and gPanelId.FIGHTER_HUD_PANEL,\n` + +` gPanelId and gPanelId.UI_PANEL__INSTRUMENT__PIANO,\n` + +` gPanelId and gPanelId.UI_PANEL__INSTRUMENT__DRUMKIT,\n` + +` gPanelId and gPanelId.MINI_GAMES_BOWLING_MAIN_PANEL,\n` + +` gPanelId and gPanelId.BASKETBALL_SHOOT_PANEL\n` + +` }\n` + +` for _, pid in ipairs(toClose) do\n` + +` if pid and gPanelManager then\n` + +` pcall(function() gPanelManager:Close(pid) end)\n` + +` end\n` + ` end\n` + +` pcall(function()\n` + +` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + +` gDisplayMessageMgr:ShowMessageContent("Closed Minigame")\n` + +` end\n` + +` end)\n` + ` end)\n` + ` elseif cmd == "TOGGLE_CLOTHES" then\n` + ` pcall(function()\n` + diff --git a/Ananta.Server/Ananta.App/DebugApiServer.cs b/Ananta.Server/Ananta.App/DebugApiServer.cs index c6cbead..36204f6 100644 --- a/Ananta.Server/Ananta.App/DebugApiServer.cs +++ b/Ananta.Server/Ananta.App/DebugApiServer.cs @@ -139,6 +139,10 @@ internal sealed class DebugApiServer(PrivateServerConfig config, GameSessionHub await WriteJsonAsync(ctx, await PlayTimelineAsync(await ReadBodyAsync(ctx.Request, token), token), token); else if (method == "POST" && path == "/api/minigame/launch") await WriteJsonAsync(ctx, await LaunchMinigameAsync(await ReadBodyAsync(ctx.Request, token), token), token); + else if (method == "POST" && path == "/api/minigame/close") + await WriteJsonAsync(ctx, await CloseMinigameAsync(token), token); + else if (method == "GET" && path == "/api/minigame/catalog") + await WriteJsonAsync(ctx, MinigameCatalog(), token); else if (method == "GET" && path == "/api/cutscene/catalog") await WriteJsonAsync(ctx, CutsceneCatalog(), token); else if (method == "POST" && path == "/api/npc/spawn") @@ -1349,11 +1353,52 @@ internal sealed class DebugApiServer(PrivateServerConfig config, GameSessionHub if (session is null) return new { ok = false, error = "no live game session (is the client in the world?)" }; - var cmd = "CMD:LAUNCH_MINIGAME:FIGHTER"; + string game = "KOF97"; + try + { + using var doc = JsonDocument.Parse(string.IsNullOrWhiteSpace(json) ? "{}" : json); + var root = doc.RootElement; + if (root.TryGetProperty("game", out var pg)) game = pg.GetString() ?? "KOF97"; + else if (root.TryGetProperty("id", out var pi)) game = pi.GetString() ?? "KOF97"; + } + catch { } + + var cmd = $"CMD:LAUNCH_MINIGAME:{game.ToUpperInvariant()}"; await session.NotifyAsync(MethodId.SyncNotice, UxSerializer.Serialize(cmd), token); - session.Log.Info("[DEBUG-API] launch arcade minigame fighter dispatched"); - return new { ok = true, game = "FIGHTER" }; + session.Log.Info($"[DEBUG-API] launch minigame game={game}"); + return new { ok = true, game }; + } + + private async Task CloseMinigameAsync(CancellationToken token) + { + var session = hub.Current; + if (session is null) + return new { ok = false, error = "no live game session (is the client in the world?)" }; + + var cmd = "CMD:CLOSE_MINIGAME"; + await session.NotifyAsync(MethodId.SyncNotice, UxSerializer.Serialize(cmd), token); + + session.Log.Info("[DEBUG-API] close minigame dispatched"); + return new { ok = true }; + } + + private static object MinigameCatalog() + { + return new + { + ok = true, + items = new[] + { + new { id = "KOF97", name = "🕹️ Arcade: The King of Fighters '97 (ตู้เกม KOF '97)", category = "arcade" }, + new { id = "METALSLUG", name = "🕹️ Arcade: Metal Slug (ตู้เกม Metal Slug ลุยด่าน)", category = "arcade" }, + new { id = "FIGHTER", name = "🥊 3D Arcade Fighter (มินิเกมต่อสู้ 3D)", category = "arcade" }, + new { id = "PIANO", name = "🎹 Grand Piano Interactive (เล่นเปียโนสด)", category = "music" }, + new { id = "DRUMKIT", name = "🥁 Drumkit Interactive (ตีกลองชุดสด)", category = "music" }, + new { id = "BOWLING", name = "🎳 Bowling Alley (โยนโบว์ลิ่ง)", category = "sports" }, + new { id = "BASKETBALL", name = "🏀 Street Basketball (ชูตบาสเกตบอล)", category = "sports" }, + } + }; } private static async Task ReadBodyAsync(HttpListenerRequest request, CancellationToken token) diff --git a/Ananta.Server/Ananta.App/DebugPanel/index.html b/Ananta.Server/Ananta.App/DebugPanel/index.html index 385fabc..9c22f13 100644 --- a/Ananta.Server/Ananta.App/DebugPanel/index.html +++ b/Ananta.Server/Ananta.App/DebugPanel/index.html @@ -264,12 +264,35 @@
-

🕹️ Arcade Minigame (ตู้เกมต่อสู้อาร์เคด)

-
- - L18 Street Fighter +

🕹️ Arcade & Interactive Minigames (ตู้เกมอาร์เคด & มินิเกมในโลก)

+
+ + +
-
เปิดระบบมินิเกมตู้เกม Arcade Fighter ในฉาก
+
+ + + + + + +
+
เปิดตู้เกมอาร์เคด (KOF '97, Metal Slug) หรือมินิเกมดนตรี/กีฬาในโลกได้ทันที พร้อมปุ่มควบคุมแบบเต็มหน้าจอ
@@ -739,9 +762,33 @@ async function playSelectedCutscene() { log('play cutscene: ' + JSON.stringify(r)); } +async function launchSelectedMinigame() { + const sel = document.getElementById('minigameSelect'); + const game = sel ? sel.value : 'KOF97'; + const r = await api('/api/minigame/launch', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ game }) + }); + log('launch minigame (' + game + '): ' + JSON.stringify(r)); +} + +async function launchMinigameQuick(game) { + const r = await api('/api/minigame/launch', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ game }) + }); + log('quick launch minigame (' + game + '): ' + JSON.stringify(r)); +} + +async function closeActiveMinigame() { + const r = await api('/api/minigame/close', { method: 'POST' }); + log('close minigame: ' + JSON.stringify(r)); +} + async function launchArcadeMinigame() { - const r = await api('/api/minigame/launch', { method: 'POST' }); - log('launch arcade minigame: ' + JSON.stringify(r)); + await launchSelectedMinigame(); } async function setTimePreset(hour, minute) {