| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- """环境注入: L_GameEnvManager / FileUtils / LuaBridgeCtl / gameEnviroment / 杂项全局函数。
- Task 5 契约: EnvData + install_env; 不引入 python.eval, FileUtils 走 AP_* 直挂。
- """
- from __future__ import annotations
- import os
- from typing import Any
- SWITCHES_DEFAULT: dict[int, int] = {2: 1} # Modules_Index_Enable_Check_Heart_Beat=1(心跳开)
- class EnvData:
- """游戏环境数据: 登录态/账号/渠道/签名等。data 透传给 L_GameEnvManager.GetEnvDataByKey; switches / settings 独立 dict。"""
- def __init__(self, data: dict[str, Any]) -> None:
- self.data: dict[str, Any] = dict(data)
- self.switches: dict[int, int] = dict(SWITCHES_DEFAULT)
- self.settings: dict[int, list[Any]] = {}
- def _safe_join(abs_state: str, rel: str) -> str:
- """join 后必须仍在 abs_state 内(防 rel 形如 ../escape)。返回 abspath。"""
- p = os.path.abspath(os.path.join(abs_state, rel))
- if os.path.commonpath([p, abs_state]) != abs_state:
- raise ValueError(f"path escape: {rel!r} not under state_dir")
- return p
- def install_env(lua: Any, env: EnvData, state_dir: str) -> None:
- """注入环境: L_GameEnvManager / LuaBridgeCtl / FileUtils / gameEnviroment / 杂项全局。"""
- os.makedirs(state_dir, exist_ok=True)
- abs_state = os.path.abspath(state_dir)
- g = lua.globals()
- g["_PY_ENV"] = env
- g["_PY_STATE_DIR"] = state_dir
- # Lupa 不翻译 KeyError -> nil, 暴露 get/switch helper 规避
- def _get_env_key(k: str) -> Any:
- return env.data.get(k)
- def _get_switch(i: int) -> int:
- return env.switches.get(int(i), 0)
- def _set_switch(i: int, v: int) -> None:
- env.switches[int(i)] = int(v)
- def _get_setting(i: int) -> Any:
- return env.settings.get(int(i))
- def _set_setting(i: int, v: Any) -> None:
- env.settings[int(i)] = v
- g["AP_getEnvKey"] = _get_env_key
- g["AP_getSwitch"] = _get_switch
- g["AP_setSwitch"] = _set_switch
- g["AP_getSetting"] = _get_setting
- g["AP_setSetting"] = _set_setting
- # Lua 侧: env manager / bridge ctl / 杂项全局
- # 冒号定义使 self 显式, 兼容游戏里 L_GameEnvManager:GetEnvDataByKey(...) / LuaBridgeCtl:Inst():...
- lua.execute(r"""
- L_GameEnvManager = {}
- function L_GameEnvManager:GetEnvDataByKey(k) return AP_getEnvKey(k) end
- LuaBridgeCtl = {}
- function LuaBridgeCtl:Inst() return self end
- function LuaBridgeCtl:GetModulesSwitch(i) return AP_getSwitch(i) end
- function LuaBridgeCtl:SetModulesSwitch(i, v) AP_setSwitch(i, v) end
- function release_print(...) end
- releasePrint = release_print
- function GET_STRING(id) return "" end
- function JUMPTO(...) end
- function GET_SETTING(i) return AP_getSetting(i) end
- function CHECK_SETTING(i)
- local s = AP_getSetting(i)
- return s ~= nil and s[1] == 1 or false
- end
- function CHANGE_SETTING(i, v) AP_setSetting(i, v) end
- """)
- # FileUtils: Python 静态方法暴露为 Lua 全局, cc.FileUtils Lua 薄壳包一层
- class _FU:
- @staticmethod
- def getInstance() -> "type[_FU]": # noqa: N802
- return _FU
- @staticmethod
- def getWritablePath() -> str: # noqa: N802
- return abs_state + os.sep
- @staticmethod
- def writeStringToFile(s: str, rel: str) -> None: # noqa: N802
- p = _safe_join(abs_state, rel)
- os.makedirs(os.path.dirname(p), exist_ok=True)
- with open(p, "w", encoding="utf-8") as f:
- f.write(s)
- @staticmethod
- def isFileExist(rel: str) -> bool: # noqa: N802
- try:
- return os.path.exists(_safe_join(abs_state, rel))
- except ValueError:
- return False
- g["AP_writeStringToFile"] = _FU.writeStringToFile
- g["AP_isFileExist"] = _FU.isFileExist
- g["AP_getWritablePath"] = _FU.getWritablePath
- lua.execute("""
- cc = cc or {}
- cc.FileUtils = {getInstance = function() return cc.FileUtils end}
- function cc.FileUtils:writeStringToFile(s, rel) AP_writeStringToFile(s, rel) end
- function cc.FileUtils:isFileExist(rel) return AP_isFileExist(rel) end
- function cc.FileUtils:getWritablePath() return AP_getWritablePath() end
- """)
- # gameEnviroment(小写 e) - 全局 C++ 单例, 最小面
- lua.execute(r"""
- gameEnviroment = gameEnviroment or {__netClient = nil}
- function gameEnviroment:Inst() return self end
- function gameEnviroment:SetNetClient(nc) self.__netClient = nc end
- function gameEnviroment:GetNetClient() return self.__netClient end
- function gameEnviroment.SetLoginAccount(a) end
- function gameEnviroment.GetDownloadRootURL() return "" end
- """)
|