小井盖改为自绘 GM 窗口(WebView2)+ 背包可见 + 启动器互斥

- 90CN.dll:新增 90CN_gm_window.cpp,自绘标题栏/边框的置顶窗口,内嵌 WebView2 承载 gmweb 页面
- 点小井盖时隐藏游戏内嵌 IE 面板、弹出控制台;关掉后还原,独占全屏压不住时可选 minimize_game
- 窗口每轮确认置顶,避免游戏抢窗口栈后消失
- gmweb:新增背包页,发放后自动跳转并高亮新入包的行(GET /local/dnf-gm/inventory/list)
- 启动器:新增 /console-status,控制台运行时置灰 GM 工具入口并阻止进入
- 服务端指纹回绑新 DLL(1258496 / 7A179B1B…)
This commit is contained in:
hanfuit committed 2026-11-05 13:16:52 +08:00
1 parent e9a3952a9d
commit b22579658e
10 files changed
+1246 -97

No files matched your search

+32
View File
@@ -41,6 +41,28 @@ DETACHED_PROCESS = 0x00000008
DEFAULT_PORT = 19527 # 启动器本地端口
# 游戏内「简易 GM 控制台」的窗口类名(90CN.dll 自绘窗口,见 client-patch/90CN_gm_window.cpp)。
# 它和这里的完整 GM 工具是两套东西:控制台是精简版、只能发物品/调角色,
# 同时开着会互相覆盖同一个角色的数据,所以控制台在运行时把 GM 工具入口锁掉。
CONSOLE_WINDOW_CLASS = "90CN_GMHostWindow"
def console_running() -> bool:
"""游戏内简易 GM 控制台是否正在显示(跨进程按窗口类名查,不需要共享状态文件)。"""
try:
u32 = ctypes.WinDLL("user32", use_last_error=True)
u32.FindWindowW.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p]
u32.FindWindowW.restype = ctypes.c_void_p
u32.IsWindowVisible.argtypes = [ctypes.c_void_p]
u32.IsWindowVisible.restype = ctypes.c_bool
hwnd = u32.FindWindowW(CONSOLE_WINDOW_CLASS, None)
if not hwnd:
return False
return bool(u32.IsWindowVisible(hwnd))
except Exception:
return False
# 更新检查配置:Gitea 自托管仓库的 Releases 地址
UPDATE_REPO_API = "https://git.hanfuit.com/api/v1/repos/Lingbao/90CNServer/releases"
UPDATE_REPO_WEB = "https://git.hanfuit.com/Lingbao/90CNServer/releases"
@@ -549,6 +571,8 @@ class Handler(BaseHTTPRequestHandler):
# 静态资源
if path in ("/", "/index.html"):
self._send_file(os.path.join(RES_DIR, "index.html"), "text/html; charset=utf-8")
elif path == "/console-status":
self._api_console_status()
elif path == "/style.css":
self._send_file(os.path.join(RES_DIR, "style.css"), "text/css; charset=utf-8")
elif path == "/shell.css":
@@ -712,6 +736,14 @@ class Handler(BaseHTTPRequestHandler):
self._json({"error": "not found"}, 404)
# ==================== 启动器接口 ====================
def _api_console_status(self):
running = console_running()
self._json({
"ok": True,
"running": running,
"reason": "游戏内简易 GM 控制台正在运行,先关掉它再用完整 GM 工具" if running else "",
})
def _api_status(self):
server_dir = os.path.join(SERVER_ROOT, "Server")
client_dir = os.path.join(SERVER_ROOT, "Client")