AskaEth
|
8c67e4eca6
|
fix(presenter,app-iced): 「游戏在跑」挡在落 core 之前(M247 r2)
塔裁决:三个写操作在实例启动/运行时必须拒,判据不能只靠界面灰按钮 ——
Windows 上是 os error 32 兜底,**Linux 上删一个正在跑的世界会成功**,那是在
用户玩到一半时把存档删掉。
- host/dispatch.rs:`AppCommand::Saves` 与 `AppCommand::Mods` 同款,先查
`CoreHost::in_flight(&id)` 再把 `running` 传下去
- host/saves.rs::dispatch 增 `running`:为真时三个写操作**不 spawn、不碰盘**,
直接回一条 `SavesFailureKind::GameRunning` 的结构化失败;读路径与「打开文件夹」不受影响
- dto:新增 `GameRunning` 类别(不折进 WriteFailed —— 那不是"写失败",是"我们主动没写")
- i18n:「游戏正在运行(先退出再操作)」中英成对 + 金表同步
- 用例:在飞时三条写命令盘上指纹不变/世界还在/备份落点没建,且回 GameRunning;
反向用例钉住闸门没有把写操作一并关死;UI 侧断言三种动词的主句都不出现「写盘失败」且不画重试
- 拆分(400 行):host/saves.rs → host/saves/write.rs;两处测试各拆出 write 子模块
- SavesState 模块文档补「生命周期」表:draft / pending / confirm 谁写谁清、何时必须清,
并把 confirm「取走即清」(连点两下不删两个)写成安全不变量
- 出图:ULL_SAVES_FIXTURE=running 一张(失败那句话的样子)
|
2026-11-11 13:29:56 +08:00 |
|
AskaEth
|
c921b9c185
|
feat(core,presenter,app-iced): 存档三个写操作(重命名 / 删除 / 备份)+ 行操作区(M247 SAVESOPS)
core::game::saves 新增 write 模块,三个入口的第一句都是 boundary::guard:
- rename_world:saves/<old> → saves/<new>,撞名/同名/非法名字各自具名拒绝
- delete_world:递归删(不跟随符号链接、层级上限 64),先过边界校验
- backup_world:流式 zip(限额预检 → 临时文件 → 原子改名),
<世界名>-YYYYMMDD-HHMMSS.zip,撞名顺延,绝不覆盖上一份
guard 三道判据(每次写前重做,不信任调用方):名字必须是单段裸名字;
saves/ 必须是运行目录的真实直属子目录;世界目录必须是 saves/ 下的真目录
(解析后比父级,不比字符串前缀)。落点目录要求绝对路径(相对路径会落到进程 CWD,
实测过一次)。
presenter:SavesCommand 增 RenameWorld/DeleteWorld/BackupWorld,host 三个后台入口
写成功后重新列一遍目录并把「回执」挂在快照上(SavesOped:改名两端 / 被删的名字 /
备份落点+字节数+跳过的链接数)。SavesFailureView 增 file 与 op,写失败八类一一对应。
SavesState 增 draft / pending / confirm 三样交互态(草稿是行内输入缓冲,
pending 与 ModsState::pending 同一条先例,confirm 是删除确认框在等谁)。
app-iced:世界行右侧重命名/备份/删除;行内输入框改名(现成模态队列没有「输入变了」
这一条消息,用输入模态等于重写一套);删除走现成 modal 的 Confirm,主按钮落点接在
app/update/dialog.rs。回执行画在卡片里(备份落点看不见就是静默失败)。
i18n:新增 25 条中英成对 key + 金表同步;删掉 M235 的「这一版只读」那条(写操作接上
之后它是假的)。出图夹具 ULL_SAVES_FIXTURE=rename|confirm|backed-up 三种形态。
|
2026-11-11 13:29:56 +08:00 |
|
AskaEth
|
f217d83680
|
feat(saves): 实例存档 / 截图的只读列表与打开文件夹(M235 STOREMVP)
用户诉求是 PCL 差距四项里的「存档截图 / 导入」,M230 审计确认三层全缺。塔裁决 U3
把这一版钉成「只读列表 + 打开文件夹」,不做缩略图墙(缩略图要引图片解码依赖,而
AGENTS §2 只允许 palette-extract 引 image 类依赖;截图/导入产物形态也没定型)。
core
- `game::saves`(新):只读列 `<run_dir>/saves`(世界目录)与 `<run_dir>/screenshots`
(图片文件)。只调 symlink_metadata / read_dir / metadata,不建目录、不写文件、不读
文件内容(`icon.png` 只判存在)。目录不存在 ⇒ 空列表不是错误;存在但不可用(符号
链接 / 不是目录 / 读不了)⇒ 具名错误。条目级异常逐条登记原因,不静默丢。
- `platform::opener`(新):`open_dir` 是**目录**打开器的唯一收敛点(explorer / open /
xdg-open),内部复用 `child::quiet`,cfg 分支只此一处。塔明确要求按 AGENTS §6 放
platform 而不是业务模块,并要一条可执行判据防退化
(`the_launcher_literals_live_here_only` 扫 `crates/core/src`:除本文件外不许出现
`"explorer"` / `"xdg-open"` 字面量)。
presenter
- `dto::saves`:SavesCommand(List / OpenFolder)、SavesListView、SavesFailureView
(结构 + OS 原文,不拼中文)、`SavesListView` 的计数助手。
- `host::saves`:走 `job::spawn`,UI 只收快照;运行目录仍是
`isolation::derive_game_dir` 的同一个答案(与启动 / mod 列表同源,**不写盘**)。
「打开文件夹」打开哪个目录由 host 定:`saves/` → `screenshots/` → 运行目录。
失败分三类(InstanceUnavailable / DirUnusable / OpenFailed),可重试。
- `state::saves`:快照整体替换、迟到结果丢弃、失败保留绑定(重试才有意义)。
- 接线:CoreEvent::Saves / AppCommand::Saves / HostTask::Saves。
app-iced
- `pages::instances::saves`:详情页 SAVES 卡片(MODS 之后、启动参数之前;**不套第二层
滚动条**,整列那一条是唯一入口)。世界行带 UTC 时间与「有图标」,截图行带大小与时间;
第一行固定画「这一版只读」(U3 边界让用户看得见)。读盘失败画一条红字 + 「重试」;
打开文件夹失败**不画**重试(那个动作的重试就是再点一次按钮)。
- 接线:Message::{ReloadSaves, OpenSavesFolder}、`sync_saves`(与 `sync_mods` 同一判据)、
Model::saves、`saves_shot` 出图夹具(ULL_SAVES_FIXTURE=1)。
i18n
- `InstancesSaves*` 20 条中英成对,catalog 与金表在**同一条锚点**后追加、逐字节一致。
证据
- core 只读判据:`game::saves::tests` 在真盘建世界/截图,调用前后各拍一次
(相对路径, 是否目录, 字节数, mtime)指纹并逐条比对;另有用例钉「目录缺失不建目录」。
- presenter:`host::saves::tests` 真盘端到端(custom 档位派生运行目录 → 快照)。
- GUI:`--software-renderer` 1180×760 浅/深各一张 + 1180×1280 两张「整块卡片可见」
(1180×760 下 SAVES 卡片位于折叠线附近,只能看到卡头;第二对用 ULL_WINDOW_SIZE
把窗口拉高,口径与 M98 的矩阵一致),落 `DevDocs/artifacts/M235/`。
没做的(U3 边界内,见 handoff):缩略图墙、导入、删除/重命名、`level.dat` 的
LevelName 解析(世界名暂时就是目录名)。
|
2026-11-11 06:00:27 +08:00 |
|
tower-worker
|
a0f61d8bb5
|
feat(mods): 本地 Mod 列表与启停(M224 MODTOGGLE)
三层一次做完:core 读写目录 → presenter DTO/host → 实例详情页 MODS 区。
r1 复审后 rebase 到 main 71144df(M223 已合入),并修掉四条文档疵。
core(crates/core/src/addon/mods/)
- suffix:`.disabled` / `.old` 的**唯一判据**(四态枚举 + 展示名 + 双向改名目标名),
收敛原先两份同构实现——`export/scan.rs::is_disabled_path` 与 `import/plan/paths.rs::suffix_variant`
改为委派/再导出,签名与行为不变。
- list:单根语义(入口是 derive_game_dir 派生出的运行目录)列 `<run>/mods/`,不按扩展名过滤,
符号链接/目录/怪名字逐条登记原因;`mods/` 本身是符号链接时拒(不跟随)。
- toggle:启停 = 在 `mods/` 里改名。五条守卫(裸文件名 / 目录可用 / 普通文件 / 不覆盖 / 不做
copy+delete 兜底)+ 幂等;`.disabled` 只插在 `.old` 之前。
presenter
- dto/mods:ModsCommand / ModListView / ModFailureView(不拼文案,只给结构 + OS 原文)。
- host/mods:后台线程列目录与启停,运行目录走与启动同一份 D20 派生、不写任何设置;
游戏在跑时 host 侧直接挡。
- state/mods:快照整体替换、迟到结果丢弃、在飞标记;`AppState::mods`。
app-iced(实例详情页)
- MODS 区(`pages/instances/mods.rs`):名字 + 大小 + `.old` 徽标 + Switch;运行中/在飞只读。
- 进入详情页即后台列一次(不走 3 s 观察窗,避免打红 M192 的「空闲不烧帧」守卫)。
- MODS 卡排在启动参数**之前**(详情列是滚动区,排在后面 1180×1000 下永远看不见)。
- i18n:19 条中英文案(`catalog/instances.rs` + 金表)。
rebase 冲突解法(三个文件,全是"两侧同段新增",都保留):
- `i18n/catalog/instances.rs` + `i18n/catalog/golden.rs`:M223 的 Adopt* 段在前、M224 的
InstancesMods* 段在后(= `Key::ALL` 顺序 = 金表顺序)。
- `presenter/src/state.rs`:`adopt` 与 `mods` 字段/初始化/apply_core 分支都留;`tiles()` 归
`state/tiles.rs`(本分支搬的),`apply_agent`/`agent_rail_visible` 归 `state/agent.rs`
(M223 搬的)——两处搬移不重叠,state.rs 里都不再出现。
r1 四条文档疵:
1. `pages/instances/mods.rs` 模块文档:挂载位置写反("启动参数卡之后"→实际之前),并补上为什么;
2. `state/mods.rs`:引用不存在的 `CoreEvent::ModsChanged/ModsFailed` → 改成 `CoreEvent::Mods`
+ 文字说明 Ok 落快照 / Err 落具名失败;
3. `app/state/mods_shot.rs`:文档说"目录串取真实派生结果"但代码留空 → 改成"故意留空";
4. `app/state/refresh.rs::note_mods_failure`:文档说"连点两次看见两次红字"与去重机制不符 →
改成按 `(实例, 文件, 大类)` 三元组去重(防刷屏),换文件/换实例/换大类仍会再弹。
顺带(r1 已确认的 main 红):`pages/download/options/view.rs:88-89` 两条
`clippy::doc_lazy_continuation` 只缩进修掉,文字未动。
|
2026-11-10 21:09:37 +08:00 |
|
AskaEth
|
ee67965b9b
|
fix(m157): r4 修复未收集的周快照用例 + 两处 clippy 红,并补整环回归(复审 p1-2)
P1-1 crates/core/src/launch/overrides/tests.rs:modded_weekly_snapshot_needs_the_root_version_for_the_gate 原先写在 backend_allowed_combines_capability_and_threshold 函数体内(unnameable_test_items,永不执行)。移到模块层;移动后首次真正执行暴露出用例自身的 EmptyJavaPath(AdapterOptions 默认 java 为空),补 JavaSelection 后绿。--list 现在 10 条 launch::overrides::tests::(含该名字)。
P1-2 clippy -D warnings 两处:cli/commands/instance_launch.rs needless_borrows_for_generic_args(去 &);presenter/mock_data.rs items_after_test_module(mock_launch 移到 mod tests 之前)。
P3-a 新增整环回归 app/tests/instances_save_loop.rs:真 Message → dispatch → 后端回错误 Toast → pump → refresh_view → sync_launch_form,断言 4g 草稿与脏标记都还在。
P3-b LaunchForm::matches 内存改按数值比(解析失败退文本),补 memory_is_compared_by_value_not_by_text(04096 / +4096 / 清空三档)。
P3-c 门槛文案不再在 catalog 硬编码 26.2:InstancesLaunchBackendGated 改用 {min} 占位符,页面从 LaunchFacts::min_version(← core GRAPHICS_BACKEND_MIN_VERSION)代入;金表同步;灰化态截图重拍。
|
2026-11-07 11:06:18 +08:00 |
|
AskaEth
|
e2021645d7
|
feat(launch): M157 实例级启动参数(五项回落 + graphicsBackend 三态)
core: 新增 game/launch_overrides(LaunchOverrides 五项 All-Option + 三级回落 + 文本补丁校验)与 launch/overrides(拼装落位:全局 java.extra_args 进 user.jvm、实例 jvmArgs 进 override_jvm、gameArgs 进 user.game、memory 进 -Xmx、backend 进 --graphicsBackend 并复用既有版本门槛告警);实例 schema 登记 launch.* 五键。
presenter: dto/LaunchArgsView+LaunchArgsPatch,主机侧读/写与门槛判定(backend_allowed),AppCommand::SetInstanceLaunchArgs。
cli: 新命令 instances launch-args(读/写/--clear),launch 装配链消费回落值。
app-iced: 实例详情页「启动参数」区(JVM/游戏参数、内存、Java、三态后端 chips + 灰化提示 + 保存/恢复),表单状态归 App、i18n 中英文案同步。
|
2026-11-07 10:36:35 +08:00 |
|
AskaEth
|
d0a8f68607
|
docs(m120): 页面模块的守门说明改成白名单口径
|
2026-11-05 13:36:45 +08:00 |
|
AskaEth
|
1a4e1fee12
|
feat(app-iced): M120 实例页与启动阶段标签跟着界面语言走
来源:M106 r1 复审点名——中文机器上首屏(实例页)仍是英中混排(页头 / New instance /
Import / ALL INSTANCES / VERSION / Present on disk / Running · pid / Launch failed)。
用户的原话是「我系统语言是中文 为什么打开软件是英文」。
改了什么
- i18n:catalog/instances.rs 从 6 条死 key 补到 34 条(页头 / 列表列头 / 详情动作 /
窄窗说明 / 元信息标签与值 / 隔离档位 / 运行状态 / 四个启动阶段)。族在装配链第 2 位,
新 key 追加在本族末尾,golden 对应位置插入(不是文件末尾追加)。
- 页面:新增 pages/instances/text.rs(Texts)——页面唯一的取词入口,实例页里不再有
任何可见英文字面量;detail / demo 也改从它取。
- 阶段标签:view/instances.rs 的 Running / Launch failed / 四阶段全部走目录;
**数字与分隔符不随语言变形**(运行中 · pid 1234 与 Running · pid 1234 只换前半句)。
- 顺手修掉两处「语言反向泄漏」:原版徽标此前直接画 presenter 的中文「原版」(英文界面
会漏中文),现在走 LoaderVanilla;隔离档位 isolated/shared 也从 core 的稳定 id 换成人话。
- 删掉 InstancesLastPlayed:M117 加的整句 key,从未接线,形状与「标签 + 值」的元信息卡
不符,由 InstancesMetaLastPlayed + InstancesNeverPlayed 取代。
守门(pages/instances/tests/i18n.rs + app/view/tests.rs)
- 中文态无 ASCII 英文单词(品牌 Java / 技术标识 pid 白名单);
- 每一条 Instances* 的两套译文必须不同(切语言时真的变);
- Running 的数字与 · pid 分隔符在两套语言里逐字保留;
- 页面源码里 29 条旧英文基线不许回来;每条 key 都必须被页面引用(死 key)。
出图:DevDocs/artifacts/m120/01~12(有实例 / 空态 / 运行中 × 浅深 × 中英)。
|
2026-11-05 13:36:44 +08:00 |
|