Proxyos Weekly 082
Laurence-042
- 3 minutes read - 431 wordsTL;DR 概览
通跑了引入的-1、0 两章,修复了相关问题。新增了完整的 Mod 侧 App 支持
本期目标
- 完整冒烟
- 第 -1、0 章
- 第 1、2 章
- 文件引用处理冒烟
- 将第三章开头补充进 demo
- 调整第二章末尾文本,引入经济系统和支线任务系统
- 通过经济系统获得通用搭载平台
- 将 demo 结束提示放在通用搭载平台的 app 里(SpiderView 实现)
- 更多内容
- 支线任务
- 更多任务
- 实用化任务时限
- 命令行内容?(等第三章?是否需要?)
- 远程访问?
- 更精细化管理事件而不是按章组织?mod 支持?
- 用英语通玩一遍
- 开个 itch
- 琢磨下宣传
进展速记
本期假设 / 预期
预期:
冒烟通跑
结果:
通跑了作为教程章前的序章的第 -1、0 章,并修复了相关问题;新增了完整的 Mod 侧 App 支持。
本期确定性变化
新增:
- 新增完整的 Mod 侧 App 支持
变更:
- 将备忘录修改为 Mod 侧 App 实现,作为给 Modder 的示例
修复:
- 修复因为 i18n 流水线错误地替换了 html 里的资源引用为到 overlay 的,导致和虚拟路由冲突导致无法加载资源的 bug
- 修复偶现的关卡切换和数据加载的时序 bug
删除:
- 主场景的切换
主要进展内容/本期关键判断点
我做出了哪些「如果错了也要付代价」的判断?
彻底移除游戏间随 stage 切换重载主场景的能力
这个其实是从项目最初遗留到现在的。
当时的计划还是模拟完整桌面环境,当时我准备靠 stage 控制游戏剧情的多个阶段,并在不同阶段加载不同的剧本控制器、加载不同的主场景。
但是随后计划改变成了模拟控制终端,并将剧本控制器的加载实现得更加解耦,而且随着教程部分的结束,剧本也将使用统一的增量加载剧本控制。
这个时候已经确立了“每次切换 stage 必须重启游戏”的叙事 lore,但是这个能力并没有被移除。
而现在随着游戏启动时,mod 侧处理的复杂性,热重载的维护难度上升到了继续维护得不偿失的程度。而这次又在 quit 前热重载的场景下,出现了 Terminal 重复加载相关的问题,这让我开始怀疑继续保留它的必要性。
于是深思熟虑后,我确定“每次切换 stage 必须重启游戏”的叙事 lore 不会调整,因为本身 stage 的切换必定伴随叙事里发生了重大的影响玩家的事件,必定会导致玩家控制的 ProxyOS 重启,那么也就必然伴随着重启终端。因此,在本期彻底移除了随 stage 切换重载主场景的能力。
Mod 侧 App
背景
在 6 月底 Mod 中心化的路线确立之后,整个 7 月基本都在将架构迁移为 Mod 提供所有游戏数据
但当时迁移的过程中,我暂缓了由 Mod 扩展新的 App 的能力
当时我的判断是可以临时用 WebView 顶一下,具体的扩展到时候游戏真的能卖出的时候再做
但是我这期在冒烟通跑的过程中,突然觉得直接用 WebView 就能做完,而且预计这期就能搞定,于是我就做了
结果证明我的判断没啥问题,大部分底层能力确实已经由 SpiderView、虚拟路由和 Mod Component 系统提供了,缺少的主要只是配置发现和生命周期整合。
架构
Mod 侧 App 的本质是基于 WebView 包装的、做了虚拟路径和剪贴板支持 polyfill 的 SpiderView。
Mod 侧通过Apps/<App>/config.yaml 声明一个由 Mod 提供的应用,整个 <App> 目录是页面根。
其典型目录结构如下
Mods/<ModId>/
├── Apps/
│ └── <App>/
│ ├── config.yaml
│ ├── icon.svg
│ ├── index.html
│ ├── css/
│ ├── js/
│ └── _overlay/<locale>/...
└── <python_package>/
└── apps/<app>/..._overlay/<locale>/ 是页面文件 overlay,目录结构直接镜像 App 页面根。
config.yaml仍使用同目录 overlay 命名的机制,比如其英文 overlay 文件就是同目录的_config.yaml.en.yaml。
使用专门_overlay 目录做页面文件映射是因为页面文件都是完整替换,完整镜像更加容易维护(生成不同目录的相同文件名 overlay 后可以直接用 python -m http.server -d ./_overlay/en/pages跑。如果是用相同目录的不同文件名就没法在脱离虚拟 url 系统的状态下调试了);而使用同目录 overlay 文件做 config 的 overlay 是因为其只需要替换几个字段。因此才在这里出现了两种 overlay 写法。
其config.yaml内容如下
id: MEMO
name: 节点上下文
icon: icon.svg
entry_page: index.html
extra:
page_size: 50| 字段 | 契约 |
|---|---|
id | AppRegistry 中保留声明值;匹配大小写不敏感且在所有 Mod App 中全局唯一。公开 scheme 使用小写。 |
name | ActivityBar、窗口标题使用的可翻译名称。 |
icon | 相对 config.yaml 的普通 Mod 资源路径;扫描期 claim 并规范化为 mod://。 |
entry_page | App 根内已存在的相对文件路径,不允许绝对路径或目录穿越。 |
extra | 可选的递归 JSON 字面值映射;原样缓存,不参与路径推断。 |
切换 locale 会重新加载名称和图标,但不会重建已打开的窗口。
而其后端则是<python_package>下面的,和浏览器网页系统那样自行注册 route 的 python 后端
可以看到其本质上就是个有config.yaml的网页,这能让 Mod 作者方便地基于网页前端技术栈做 App。
说实话做到这里我都觉得自己有点搞太远了,这甚至可以说是一个基于 Godot 的丐版 tauri 实现了……
数据流
- Mod 侧使用和网页页面类似的映射机制将 App 配置和页面结构上报给 Godot 侧
- Godot 侧会根据得到的配置实例化对应 App 的 Manager
- 本质上就是不需要打开 App 窗口也能由其他 App 调用相关 python 后端的后端服务适配器
- 游玩时使用
<app-id>://地址- 这个地址会在进入 Spider 页面体系时单向规范化为
proxy://apps.proxyos.internal/<lower-app-id>/。之后的静态页面、Python backend route、fetch、导航和注入都使用现有 proxy 流程。
- 这个地址会在进入 Spider 页面体系时单向规范化为
至此,原生 App 与 Mod App 在注册、Manager 创建和调用方式上使用同一套生命周期;区别主要只剩窗口前端是 Godot 原生界面还是基于 WebView 的 SpiderView 页面。
统一架构带来的加载顺序问题
我不想让原生 App 和 Mod WebView App 使用不同的基类和访问模式,所以我重构了 App 架构,将之前使用 autoload 的原生 App Manager(本质上是 App 的持久化后端,用于在 App 窗口不打开的时候也能使用部分 App 功能)全部移除 autoload,使用和 Mod WebView App 一样的动态创建 Manager 的机制
但这产生了新的问题:这些 App Manager 需要使用 Mod 侧的数据进行初始化(比如信息段管理器需要加载 Mod 侧上报的信息段),这就要求 App Manager 需要先实例化完成,再接受携带 Mod 数据的事件
不过好在我之前有好好管理代码质量,此前的 Mod Component 已经做了加载优先级机制。我只需要把这项优先级信息同步到 Godot 侧,就能按照相同顺序初始化对应的 App Manager 和其他功能。这样既解决了初始化依赖,也不需要额外引入一套 App 专用的依赖声明机制。
瓶颈与问题清单
哪些问题还没解,但也许我已经知道“它们不是什么”?
- mod meta、mod list、pylock.toml、依赖安装与版本回滚之间还需要形成稳定流程,否则后续 mod 管理会变成新的技术债。
下期计划
- 完整冒烟
- 第 1、2 章
- 文件引用处理冒烟
- 第 1、2 章
- 将第三章开头补充进 demo
- 调整第二章末尾文本,引入经济系统和支线任务系统
- 通过经济系统获得通用搭载平台
- 将 demo 结束提示放在通用搭载平台的 app 里(SpiderView 实现)
- 更多内容
- 支线任务
- 更多任务
- 实用化任务时限
- 命令行内容?(等第三章?是否需要?)
- 远程访问?
- 更精细化管理事件而不是按章组织?mod 支持?
- 用英语通玩一遍
- 开个 itch
- 琢磨下宣传
试玩版
暂缓,第一次上传需要做好准备,等进入 beta 阶段再说