"""唤景平台世界模式(scense)——应用唯一入口。 一个应用 = 一个入口 = 一个端口。 标准 ahserver + rbac 提供注册/登录/会话管理,应用不自行实现鉴权中间件。 """ from ahserver.webapp import webapp from ahserver.serverenv import ServerEnv import logging import os import sys import bricks_for_python # registers bui processor from bricks_for_python.init import load_pybricks # registers UiWindow etc. from appbase.init import load_appbase from rbac.init import load_rbac log = logging.getLogger("scense.entry") _APP_DIR = os.path.dirname(os.path.abspath(__file__)) _DEPLOY_DIR = os.path.dirname(_APP_DIR) for _p in (_APP_DIR, _DEPLOY_DIR): while _p in sys.path: sys.path.remove(_p) sys.path.insert(0, _DEPLOY_DIR) sys.path.append(_APP_DIR) def get_module_dbname(m): """返回模块 m 对应的数据库名(本项目单库:全部落 scense)。""" return "scense" def password_encode(s): if s is None: return "" from ahserver.globalEnv import password_encode as _orig return _orig(s) def _healthz(request, params_kw, *args, **kw): """/healthz 健康探针(标准 ahserver FunctionProcessor 注册,config.website.startswiths)。""" from aiohttp import web return web.json_response({ "ok": True, "status": 200, "app": "scense", "entry": "app/scense.py", }) def _drive(_aw): """驱动异步加载器(entity.init.load_entity / world_snapshot.init.load_world_snapshot 是 async def)。""" if not hasattr(_aw, "__await__"): return _aw import asyncio try: asyncio.get_running_loop() except RuntimeError: return asyncio.run(_aw) import concurrent.futures with concurrent.futures.ThreadPoolExecutor(max_workers=1) as _ex: return _ex.submit(lambda: asyncio.run(_aw)).result() def init(): # `python app/scense.py` 会把脚本目录置于 sys.path[0],遮蔽同名业务模块包 _script_dir = os.path.join(_DEPLOY_DIR, "app") while _script_dir in sys.path: sys.path.remove(_script_dir) sys.path.append(_script_dir) if _DEPLOY_DIR not in sys.path: sys.path.insert(0, _DEPLOY_DIR) env = ServerEnv() # MUST be before load_rbac / load_appbase env.get_module_dbname = get_module_dbname env.password_encode = password_encode load_appbase() load_rbac() load_pybricks() # ── 业务模块导入(一个入口一个端口,所有模块挂在这里)── from world.init import load_world from scene.init import load_scene from entity.init import load_entity from script_engine.init import load_script_engine from world_snapshot.init import load_world_snapshot from world_sync.init import load_world_sync from scense_demo.init import load_demo from scense.init import load_scense from scense_game.init import load_scense_game from scense_drag.init import load_drag from runtime.init import load_runtime load_world() load_scene() _drive(load_entity()) load_script_engine() _drive(load_world_snapshot()) load_world_sync() load_demo(env) load_scense(env) load_scense_game(env) load_drag() load_runtime(env) # ── 命名空间接线(业务模块 dispatch + 只读基础模块 handler 补齐)── # rbac/appbase/bricks 是只读基础模块,其 dspy 依赖 env.; # 未挂载时表现为 TypeError: 'NoneType' object is not callable。 # 只在运行时 setattr,不改基础模块源码。 try: from app.ns_wiring import wire_ns_shim wire_ns_shim(env) except Exception as _exc: import logging as _logging _logging.getLogger(__name__).error("[ns-wiring] wire_ns_shim failed: %s", _exc) # ── 标准函数处理器注册(配合 conf/config.json website.startswiths)── from appPublic.registerfunction import RegisterFunction RegisterFunction().register("healthz", _healthz) if __name__ == "__main__": webapp(init)