启动器:移除服务端工具/支援兵/插件页面,支援兵模板独立保存

- 删除服务端工具、支援兵、插件三个页面(侧边栏入口 + HTML section)
- server.py: 删除 servertool(9个)、companion/basic-attack 相关接口及常量
- native.py: 删除无人引用的 get_server_features/save_server_features/
  companion_state/companion_save(保留 GM 工具依赖的 gameplay 方法)
- shell.js: 删除 loadServerTool/loadCompanion 全部逻辑及状态变量
- shell.css: 清理 st-/cp- 相关样式
- templates/支援兵页面模板.md: 支援兵页面完整导出为独立模板
- 侧边栏「更新日志」更名为「游戏更新」
This commit is contained in:
hanfuit committed 2026-11-04 19:32:01 +08:00
1 parent 56236496a0
commit 977a4a1196
6 files changed
+410 -869

No files matched your search

+1 -203
View File
@@ -111,12 +111,8 @@ LOADOUT_EXE = os.path.join(LOADOUT_DIR, "换装工具.exe")
if not os.path.exists(LOADOUT_EXE):
LOADOUT_EXE = os.path.join(LOADOUT_DIR, "DNFLoadout.exe")
# 一键换装 / 服务端工具的持久化配置路径
# 一键换装的持久化配置路径
LOADOUT_CONFIG = os.path.join(LOADOUT_DIR, "config.json")
SERVER_CONFIG_DIR = os.path.join(SERVER_ROOT, "Server", "runtime", "config")
SERVER_FEATURES_PATH = os.path.join(SERVER_CONFIG_DIR, "server-features.json")
ACTIVITY_CONFIG_PATH = os.path.join(SERVER_CONFIG_DIR, "activity.json")
RAW_CONFIG_NAMES = ("instance.json", "dnfbridge.toml", "logic.toml", "plan.json")
# 赞助二维码图片路径(放启动器目录下 sponsor.png)
SPONSOR_IMG = os.path.join(BASE_DIR, "sponsor.png")
@@ -547,23 +543,6 @@ class Handler(BaseHTTPRequestHandler):
self._api_loadout_characters()
elif path == "/api/loadout/equipment":
self._api_loadout_equipment(qs)
elif path == "/api/servertool/features":
self._api_servertool_features()
elif path == "/api/servertool/activity":
self._api_servertool_activity()
elif path == "/api/servertool/info":
self._api_servertool_info()
elif path == "/api/servertool/raw":
self._api_servertool_raw(qs)
elif path == "/api/servertool/gameplay":
self._api_servertool_gameplay()
elif path == "/api/servertool/batch-pickup":
self._api_servertool_batch_pickup()
elif path == "/api/companion":
self._api_companion(qs)
elif path == "/api/basic-attack":
self._json({"ok": True, "enabled": not os.path.exists(
os.path.join(CLIENT_DIR, "90CN_basic_attack.disabled"))})
elif path == "/api/logs":
self._api_logs()
elif path == "/api/gm/health":
@@ -629,32 +608,6 @@ class Handler(BaseHTTPRequestHandler):
self._api_save_loadout_config(data)
elif path == "/api/loadout/apply":
self._api_loadout_apply(data)
elif path == "/api/servertool/features":
self._api_save_servertool_features(data)
elif path == "/api/servertool/activity":
self._api_save_servertool_activity(data)
elif path == "/api/servertool/raw":
self._api_save_servertool_raw(data)
elif path == "/api/servertool/gameplay":
self._api_save_servertool_gameplay(data)
elif path == "/api/servertool/batch-pickup":
self._api_save_servertool_batch_pickup(data)
elif path == "/api/companion":
self._api_save_companion(data)
elif path == "/api/basic-attack":
enabled = bool(data.get("enabled", True))
flag = os.path.join(CLIENT_DIR, "90CN_basic_attack.disabled")
try:
if enabled:
if os.path.exists(flag):
os.remove(flag)
else:
os.makedirs(CLIENT_DIR, exist_ok=True)
with open(flag, "w", encoding="utf-8") as f:
f.write("disabled\n")
self._json({"ok": True, "enabled": enabled})
except Exception as e:
self._json({"ok": False, "error": str(e)}, 500)
elif path == "/api/accounts-config":
self._api_accounts_config_post(data)
elif path == "/api/source":
@@ -868,161 +821,6 @@ class Handler(BaseHTTPRequestHandler):
except Exception as e:
self._json({"ok": False, "error": str(e)}, 502)
# ==================== 服务端工具 ====================
def _api_servertool_features(self):
if NATIVE is not None and server_running():
try:
self._json({"ok": True, "source": "native",
"data": NATIVE.get_server_features()})
return
except Exception:
pass
cfg = _read_json_file(SERVER_FEATURES_PATH, {})
self._json({"ok": True, "source": "file", "data": cfg})
def _api_save_servertool_features(self, data):
if NATIVE is not None and server_running():
try:
self._json({"ok": True, "source": "native",
"data": NATIVE.save_server_features(data)})
return
except Exception as e:
fallback_error = str(e)
else:
fallback_error = "Native API 不可用"
_write_json_file(SERVER_FEATURES_PATH, data)
self._json({"ok": True, "source": "file",
"warning": fallback_error, "data": data})
def _api_servertool_activity(self):
self._json({"ok": True,
"data": _read_json_file(ACTIVITY_CONFIG_PATH, {})})
def _api_save_servertool_activity(self, data):
_write_json_file(ACTIVITY_CONFIG_PATH, data)
self._json({"ok": True, "data": data})
def _api_servertool_info(self):
self._json({
"ok": True,
"features_path": SERVER_FEATURES_PATH,
"activity_path": ACTIVITY_CONFIG_PATH,
"config_dir": SERVER_CONFIG_DIR,
"raw_names": list(RAW_CONFIG_NAMES),
"server_running": server_running(),
})
def _api_servertool_raw(self, qs):
name = (qs.get("name") or [""])[0]
if name not in RAW_CONFIG_NAMES:
self._json({"error": "invalid config name"}, 400)
return
path = os.path.join(SERVER_CONFIG_DIR, name)
try:
text = ""
if os.path.exists(path):
with open(path, "r", encoding="utf-8-sig") as f:
text = f.read()
self._json({"ok": True, "name": name, "path": path, "text": text})
except Exception as e:
self._json({"error": str(e)}, 500)
def _api_save_servertool_raw(self, data):
name = str(data.get("name", ""))
text = str(data.get("text", ""))
if name not in RAW_CONFIG_NAMES:
self._json({"error": "invalid config name"}, 400)
return
path = os.path.join(SERVER_CONFIG_DIR, name)
try:
os.makedirs(SERVER_CONFIG_DIR, exist_ok=True)
if os.path.exists(path):
shutil.copy2(path, path + ".bak_tool")
with open(path, "w", encoding="utf-8", newline="\n") as f:
f.write(text)
self._json({"ok": True, "name": name, "path": path})
except Exception as e:
self._json({"error": str(e)}, 500)
def _api_servertool_gameplay(self):
if NATIVE is not None and server_running():
try:
self._json({"ok": True, "source": "native",
"data": NATIVE.get_gameplay_settings()})
return
except Exception:
pass
self._json({"ok": True, "source": "file", "data": {}})
def _api_save_servertool_gameplay(self, data):
if NATIVE is None or not server_running():
self._json({"error": "服务端未运行,无法写入玩法参数"}, 400)
return
try:
if data.get("hellEpicDropRatePercent") is not None:
NATIVE.set_hell_drop_rate(int(data["hellEpicDropRatePercent"]))
if data.get("epicPotionMultiplierPercent") is not None:
NATIVE.set_epic_potion_multiplier(int(data["epicPotionMultiplierPercent"]))
self._json({"ok": True, "data": data})
except Exception as e:
self._json({"error": str(e)}, 502)
def _batch_pickup_path(self):
return INSTANCE_PATH if INSTANCE_PATH else os.path.join(
SERVER_CONFIG_DIR, "instance.json")
def _api_servertool_batch_pickup(self):
path = self._batch_pickup_path()
cfg = _read_json_file(path, {})
value = True
try:
value = bool(cfg.get("game", {}).get("dungeonBatchPickupEnabled", True))
except Exception:
value = True
self._json({"ok": True, "data": {"enabled": value}, "path": path})
def _api_save_servertool_batch_pickup(self, data):
path = self._batch_pickup_path()
cfg = _read_json_file(path, None)
if not isinstance(cfg, dict):
self._json({"error": "instance.json 不存在或格式错误"}, 400)
return
game = cfg.get("game")
if not isinstance(game, dict):
game = {}
cfg["game"] = game
game["dungeonBatchPickupEnabled"] = bool(data.get("enabled", True))
try:
if os.path.exists(path):
shutil.copy2(path, path + ".bak_tool")
_write_json_file(path, cfg)
self._json({"ok": True, "data": {"enabled": game["dungeonBatchPickupEnabled"]}})
except Exception as e:
self._json({"error": str(e)}, 500)
# ==================== 支援兵 ====================
def _api_companion(self, qs):
if NATIVE is None or not server_running():
self._json({"ok": False, "error": "服务端未运行,支援兵配置不可用"}, 400)
return
character = (qs.get("character") or qs.get("id") or [""])[0].strip()
if not character:
self._json({"ok": False, "error": "缺少角色 ID"}, 400)
return
try:
self._json({"ok": True, "data": NATIVE.companion_state(character)})
except Exception as e:
self._json({"ok": False, "error": str(e)}, 502)
def _api_save_companion(self, data):
if NATIVE is None or not server_running():
self._json({"ok": False, "error": "服务端未运行,无法保存支援兵配置"}, 400)
return
try:
self._json({"ok": True, "data": NATIVE.companion_save(data)})
except Exception as e:
self._json({"ok": False, "error": str(e)}, 502)
# ==================== 自定义账号配置 ====================
def _api_accounts_config(self):
"""返回账号列表(含默认标记)。"""