v0.1.0 360 TESTS 86.86% COV WS v1

剧本即数据,
状态即存档。

.story 纯数据剧本语言驱动服务端:可序列化执行态、种子可复现战报、带权限边界的插件系统。

引擎不难,难的是存档与复现

状态不可序列化

闭包与回调让存档变成玄学。执行到一半的剧情,dump 不出来,也 restore 不回去。

战斗不可复现

随机数四处开花,bug 无法重放。玩家报来的战报,你连第一步都走不回去。

插件权限失控

第三方代码摸到 globalThis,一个 require 就能改写整个运行时,边界形同虚设。

.story:剧本即数据

纯文本、纯数据、可 diff、可版本管理。编译产物是确定性的节点图,没有隐藏状态。

chapter1.story
=== chapter1 ===
旁白: 门虚掩着,里面有光。
set 勇气 = 3
if 勇气 >= 3
旁白: 你推开门。
end
* 推门进去 -> room
* [has_item("钥匙")] 撬锁 -> pick_lock
@sfx("door_open")
wait 0.5
emit("player_entered", "room")
标签
=== name ===
对白
说话人: 台词文本
赋值
set 变量 = 表达式
条件
if … elif … else … end
选项
* [条件] 文本 -> 标签
宿主调用
@sfx("door_open")
等待 / 事件
wait 0.5 · emit("e") · await e

同一颗种子,
同一份战报。

左栏固定,右侧滚动——三个机制共用同一个承诺:给同样的输入,永远给你同样的输出。

RUN #8848 → SAME RESULT
$ start_combat(seed = 0x5F3A91)
wolves ×3 · round 7 · win
$ start_combat(seed = 0x5F3A91)
wolves ×3 · round 7 · win # 逐帧一致

种子可复现战报

一局游戏的全部随机性收敛到单个种子。同种子同战报,bug 可重放,战报即存证。

DETERMINISTIC BT
BT root
├─ [hp < 30] retreat
├─ [dist > 3] chase(path_find)
└─ attack(crit = 0.12)

行为树 AI

敌人决策确定性遍历,同样的局面永远走出同样的分支——可预测,才可测试。

A* · 17 STEPS
path_find(16,16,"5,3;5,4", 1,1, 14,9)
→ "1,1>2,1>…>14,9"
can_see(3,3, 10,8) → true

A* 寻路 + 视线检测

寻路、视线、碰撞全部经宿主 API 暴露,剧本里一行调用即可使用。

断线重连,一字不丢

出站消息带单调递增 seq:断线重连时按 lastSeq 补发缺口,一帧不丢。

安全与持久化

插件系统

第三方代码跑在声明的权限里,而不是你的进程里。能力即令牌,越权即拒绝。

manifest · 权限声明 resource:action:scope HMAC-SHA256 · 能力令牌,可按会话撤销 Proxy 隔离上下文 · 通道逃逸已封死 健康熔断 · 连续异常 3 降级 / 5 卸载 配额 · 订阅 ≤50 · 调用 ≤100/s · 存储 ≤1MB

存档与恢复

存档就是纯数据 JSON,没有魔法字段。停机、热重载、续玩,执行态从不丢失。

存档 = 纯数据 JSON · structuredClone 可整取 版本迁移链 · v1→v2 静态注册,断链即拒 .sav 导入 / 导出 · slot 路径监狱 重启恢复 · 旧 sessionId 续玩 优雅停机全量存档 · 热重载保 pc / vars

快速开始

01 克隆仓库 02 安装依赖 03 启动引擎 04 连接会话
360 TESTS 86.86% LINE COV 60Hz SCHEDULER 0 EVAL

在线试玩

内置真实 .story 剧本(对话 / 谜题 / 探索 / 战斗),选择即可运行,无需部署服务端。编译与执行均来自仓库同源代码。

  • 真实 .story 剧本(对话 / 谜题 / 探索 / 战斗)
  • 真实编译器:编译期诊断、标签解析、指令表
  • 真实 VM:选项 / 计时等待 / 事件 / 宿主调用
0 服务器 0 网络请求 同源引擎源码