2026-08-29 21:10:24 +08:00

4.7 KiB
Raw Blame History

name description
runtime 元景 W-10 运行时执行引擎模块(前端 JS 引擎 + 可选服务端辅助)。世界运行时初始化、实体状态、脚本执行调度、事件分发、定时器、碰撞检测、暂停恢复、错误降级、独立世界本地引擎。开发/修改 runtime 相关功能前必读。

runtime 模块W-10 运行时执行引擎)

架构

wwwroot/runtime.js         前端核心引擎RuntimeEngine 类,事件循环 tick 驱动)
wwwroot/play.html          游戏运行页(画布 + 日志 + 控件,验收入口)
wwwroot/index.ui           模块入口页bricks
wwwroot/api/*.dspy         可选服务端辅助load_world / runtime_status / runtime_event / runtime_control
runtime/runtime_service.py 服务端辅助实现ServerEnv 注册,无自有数据表,只读复用 world 模块)
scripts/load_path.py       RBAC 路径注册any/logined 分层,禁通配符)
  • 运行时引擎核心在前端 JS(浏览器本地执行,事件循环 + 实体状态 + 脚本执行)。
  • 服务端辅助是可选的:/runtime/api/load_world.dspy 从 world 模块读取世界与实体; 后端不可用/查无数据时前端自动降级独立模式W-10i本地构建演示世界继续运行。
  • 本模块为交互层模块,无自有数据表(无 models/、json/、init/)。

功能点映射W-10a ~ W-10i

功能点 实现位置 验收口径
W-10a 世界运行时初始化(构建运行态实体树) runtime.js initWorld/buildTree + api/load_world.dspy 开始玩即初始化实体树,实体可点击
W-10b 实体运行时状态管理 makeEntity / state 机idle/active/done/failed 点击后实体 state 变化并绘制
W-10c 脚本运行时执行调度 executeScript/executeAction(与 script_engine 编译产物 actions 对接) 点击触发脚本动作执行
W-10d 事件分发(路由到对应脚本) dispatchEvent/processEvents/_routeEvent click/timer/collide 事件路由到实体绑定脚本
W-10e 定时器管理 addTimer/processTimerstick 驱动,非 setInterval 定时器按间隔触发脚本
W-10f 碰撞检测 checkCollisionsAABB 两两检测) 移动后实体碰撞触发 onCollide
W-10g 运行时暂停/恢复 pause/resume/stop + api/runtime_control.dspy 暂停后 tick 挂起,恢复继续
W-10h 错误处理与降级 handleErrortry/catch 捕获,单脚本失败不整页崩溃) 故意抛错脚本 → 日志记录错误,引擎继续运行
W-10i 独立世界本地引擎 _localWorldEntities + initWorld 降级分支 后端不可用仍可本地构建世界运行

脚本对接契约script_engine 编译产物格式)

{ "id": "script_click", "name": "点击响应",
  "actions": [
    {"op": "log", "message": "..."},
    {"op": "set_state", "state": "active"},
    {"op": "move", "dx": 12, "dy": 0},
    {"op": "emit", "event": "active_changed", "entity_id": "hero", "payload": {}},
    {"op": "delay", "ms": 1000},
    {"op": "fail", "message": "故意抛错"}
  ]}

实体绑定脚本:props.scripts = ["script_click", ...];碰撞回调:props.onCollide = "script_id"

DSPY 端点

  • GET /runtime/api/load_world.dspy?world_id=xxx{ok, degraded, mode, world, entities}
  • GET /runtime/api/runtime_status.dspy?runtime_id=xxx{runtime_id, running, paused, mode, entities, events, errors}
  • POST /runtime/api/runtime_event.dspyevent_type/entity_id/payload{ok, queued}
  • POST /runtime/api/runtime_control.dspyaction=start/pause/resume{ok, action, running, paused}

RBAC 路径scripts/load_path.py 已注册)

  • any/runtime/runtime.js
  • logined/runtime/runtime/index.ui/runtime/play.html/runtime/api/*.dspy4 个显式)

陷阱

  1. dspy 禁项dspy 内禁 import / f-string / print / uuid —— 全部用 ServerEnv 注入全局 load_world_runtime 等),return 显式返回。
  2. 三处同步注册:新增服务端函数必须同步 ① runtime_service.py ② runtime/init.py ③ runtime/init.py env.xxx = xxx,漏一处 → NameError。
  3. 取库名禁硬编码:服务端辅助用 ServerEnv().get_module_dbname('world'),禁止写死 DBNAME。
  4. DictObject 不可 dict():读 world 记录用 _row_to_dict 逐字段 getattr。
  5. 前端引擎不依赖 setInterval:定时器/帧循环用 setTimeout 自调度 + tick 驱动, bricks script actiontype 禁止 fetch/setIntervalplay.html 是独立 HTML不受此限
  6. 降级优先:服务端任何异常都返回 ok=True, degraded=True,绝不抛 500 —— 前端据此切独立模式。