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 中英文案同步。
This commit is contained in:
1 parent
d68523b02a
commit
e2021645d7
56 files changed
+3776
-607
No files matched your search
@@ -25,6 +25,7 @@ use crate::dto::{
|
||||
InstanceRuntime,
|
||||
InstanceSummary,
|
||||
JavaPageView,
|
||||
LaunchArgsPatch,
|
||||
LoaderKind,
|
||||
LogLine,
|
||||
LogOutcome,
|
||||
@@ -177,6 +178,15 @@ pub enum AppCommand {
|
||||
/// `isolated` / `shared`
|
||||
mode: String,
|
||||
},
|
||||
/// 写实例启动参数(M157 的「启动参数」区:JVM/游戏参数、内存、Java、图形后端)
|
||||
///
|
||||
/// 补丁语义:`None` = 这一项不改;`Some("")` = 清空回「跟随全局」。
|
||||
SetInstanceLaunchArgs {
|
||||
/// 实例 id
|
||||
id: InstanceId,
|
||||
/// 五项补丁
|
||||
patch: LaunchArgsPatch,
|
||||
},
|
||||
/// 刷新日志会话列表
|
||||
RefreshLogSessions,
|
||||
/// 打开某个会话(拉取日志行 + 触发诊断)
|
||||
@@ -237,6 +247,14 @@ impl AppCommand {
|
||||
mode: mode.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 构造「写实例启动参数」指令(详情页「启动参数」区)。
|
||||
pub fn set_launch_args(id: &str, patch: LaunchArgsPatch) -> Self {
|
||||
Self::SetInstanceLaunchArgs {
|
||||
id: id.to_string(),
|
||||
patch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 后端通道:core/agent host 实现它;[`crate::mock::MockBackend`] 验证通道语义。
|
||||
|
||||
@@ -6,6 +6,8 @@ use std::path::PathBuf;
|
||||
|
||||
use unlucky_core::game::LoaderKind as CoreLoaderKind;
|
||||
|
||||
use super::LaunchArgsView;
|
||||
|
||||
/// 实例标识:core::game 生成的稳定 id,app 视为不透明字符串。
|
||||
pub type InstanceId = String;
|
||||
|
||||
@@ -235,6 +237,8 @@ pub struct InstanceSummary {
|
||||
pub version_id: String,
|
||||
/// 版本本体是否在盘上(缺载荷时磁贴亮黄条)
|
||||
pub version_present: bool,
|
||||
/// 启动参数(M157:实例配置页「启动参数」区的数据;含三级回落后的生效值与版本门槛)
|
||||
pub launch: LaunchArgsView,
|
||||
}
|
||||
|
||||
/// 新建实例向导提交给 host 的请求(已通过向导校验)。
|
||||
@@ -375,6 +379,7 @@ mod tests {
|
||||
isolation: "isolated".to_string(),
|
||||
version_id: "1.20.4".to_string(),
|
||||
version_present: true,
|
||||
launch: LaunchArgsView::default(),
|
||||
};
|
||||
let text = serde_json::to_string(&instance).expect("序列化");
|
||||
let back: InstanceSummary = serde_json::from_str(&text).expect("反序列化");
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
//! 实例启动参数 DTO(M157):实例配置页「启动参数」区的唯一数据源 + 写回补丁。
|
||||
//!
|
||||
//! 口径三条:
|
||||
//! 1. **实例层与生效值分开给**:`jvm_args` 等是实例文件里的原文(空 = 跟随全局),
|
||||
//! `*_effective` 是三级回落(实例 → 全局 → 默认)之后真正会下发的值。UI 要把两件事同时
|
||||
//! 画出来(「留空 = 跟随全局 {global}」这种提示与「生效值」是两回事);
|
||||
//! 2. **图形后端的可选值与门槛由 host 算好**:`graphics_backend_options` 来自 core 的词表
|
||||
//! ([`LaunchArgsView::graphics_backend_options`]),`graphics_backend_allowed` 来自 core 的
|
||||
//! 版本门槛判定——UI 不复制任何一条判据(任务书:判定用 core capability);
|
||||
//! 3. **本模块不含 core 类型**(D42:dto 只放扁平 IPC 类型)。
|
||||
//!
|
||||
//! 补丁的「不改 / 清空」二分:`None` = 这一项不动;`Some("")` = 清空(回到跟随)。
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// 实例启动参数的**读取**视图(详情页「启动参数」区)。
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
pub struct LaunchArgsView {
|
||||
/// 实例 id。
|
||||
pub instance_id: String,
|
||||
/// 实例层 JVM 参数原文(空 = 只用全局 `java.extra_args`)。
|
||||
pub jvm_args: String,
|
||||
/// 实例层游戏参数原文(空 = 不追加)。
|
||||
pub game_args: String,
|
||||
/// 实例层最大堆(`None` = 跟随全局)。
|
||||
pub memory_mb: Option<u32>,
|
||||
/// 生效最大堆(三级回落 + 出厂默认,恒有值)。
|
||||
pub memory_effective_mb: u32,
|
||||
/// 实例层 Java 可执行文件原文(空 = 跟随全局 / 自动挑)。
|
||||
pub java_path: String,
|
||||
/// 生效 Java 可执行文件(空 = 自动挑;展示用,不代表已探测)。
|
||||
pub java_effective: String,
|
||||
/// 实例层图形后端(`default` / `opengl` / `vulkan`)。
|
||||
pub graphics_backend: String,
|
||||
/// 生效图形后端(三级回落之后)。
|
||||
pub graphics_backend_effective: String,
|
||||
/// 该实例版本能不能用 `--graphicsBackend`(core 的版本门槛判定;`false` ⇒ UI 灰化 + 提示)。
|
||||
pub graphics_backend_allowed: bool,
|
||||
/// 判定所依据的游戏版本(提示文案「需 MC 26.2+」旁边给出实际版本)。
|
||||
pub mc_version: String,
|
||||
/// 门槛的最低版本(core 的 `GRAPHICS_BACKEND_MIN_VERSION`;文案与测试共用一份来源)。
|
||||
pub graphics_backend_min_version: String,
|
||||
/// 图形后端三态的词表(顺序即下拉顺序;来自 core,不让 UI 手抄)。
|
||||
pub graphics_backend_options: Vec<String>,
|
||||
}
|
||||
|
||||
impl LaunchArgsView {
|
||||
/// 三态下拉的 id → 是不是当前生效值(UI 高亮用;未知值原样比较)。
|
||||
#[must_use]
|
||||
pub fn is_effective_backend(&self, id: &str) -> bool {
|
||||
self.graphics_backend_effective == id
|
||||
}
|
||||
}
|
||||
|
||||
/// 实例启动参数的**写回**补丁(GUI 表单与 CLI 共用)。
|
||||
///
|
||||
/// 每个字段:`None` = 不改;`Some("")` = 清空(回到跟随下一层)。
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
pub struct LaunchArgsPatch {
|
||||
/// 实例层 JVM 参数(文本,空白分隔)。
|
||||
pub jvm_args: Option<String>,
|
||||
/// 实例层游戏参数(文本)。
|
||||
pub game_args: Option<String>,
|
||||
/// 实例层最大堆(文本形态,host 解析;空 = 跟随全局)。
|
||||
pub memory_mb: Option<String>,
|
||||
/// 实例层 Java 可执行文件。
|
||||
pub java_path: Option<String>,
|
||||
/// 实例层图形后端(`default` / `opengl` / `vulkan`)。
|
||||
pub graphics_backend: Option<String>,
|
||||
}
|
||||
|
||||
impl LaunchArgsPatch {
|
||||
/// 是否什么都不改(UI 没动过表单时的短路)。
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.jvm_args.is_none()
|
||||
&& self.game_args.is_none()
|
||||
&& self.memory_mb.is_none()
|
||||
&& self.java_path.is_none()
|
||||
&& self.graphics_backend.is_none()
|
||||
}
|
||||
|
||||
/// 只改图形后端(下拉切换的最小补丁)。
|
||||
#[must_use]
|
||||
pub fn backend(id: &str) -> Self {
|
||||
Self {
|
||||
graphics_backend: Some(id.to_string()),
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn empty_patch_touches_nothing() {
|
||||
assert!(LaunchArgsPatch::default().is_empty());
|
||||
assert!(!LaunchArgsPatch::backend("vulkan").is_empty());
|
||||
// `Some("")` 是「清空」而不是「不改」——两者不能折叠成一个判据。
|
||||
let clear = LaunchArgsPatch {
|
||||
jvm_args: Some(String::new()),
|
||||
..LaunchArgsPatch::default()
|
||||
};
|
||||
assert!(!clear.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_round_trips_as_ipc() {
|
||||
let view = LaunchArgsView {
|
||||
instance_id: "inst-1".to_string(),
|
||||
jvm_args: "-XX:+UseG1GC".to_string(),
|
||||
game_args: String::new(),
|
||||
memory_mb: Some(4096),
|
||||
memory_effective_mb: 4096,
|
||||
java_path: String::new(),
|
||||
java_effective: "C:/jdk21/bin/java.exe".to_string(),
|
||||
graphics_backend: "vulkan".to_string(),
|
||||
graphics_backend_effective: "vulkan".to_string(),
|
||||
graphics_backend_allowed: true,
|
||||
mc_version: "26.2-snapshot-2".to_string(),
|
||||
graphics_backend_min_version: "26.2-snapshot-2".to_string(),
|
||||
graphics_backend_options: vec![
|
||||
"default".to_string(),
|
||||
"opengl".to_string(),
|
||||
"vulkan".to_string(),
|
||||
],
|
||||
};
|
||||
let text = serde_json::to_string(&view).expect("序列化");
|
||||
let back: LaunchArgsView = serde_json::from_str(&text).expect("反序列化");
|
||||
assert_eq!(back, view);
|
||||
assert!(back.is_effective_backend("vulkan"));
|
||||
assert!(!back.is_effective_backend("opengl"));
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ mod events;
|
||||
mod install;
|
||||
mod instances;
|
||||
mod java;
|
||||
// M157: 实例启动参数(启动参数区的读取视图 + 写回补丁)
|
||||
mod launch_args;
|
||||
mod logs;
|
||||
mod notices;
|
||||
// M113: import/export —— 整合包导入/导出的 DTO(M111/M112 管线的 IPC 面)
|
||||
@@ -45,6 +47,7 @@ pub use instances::{
|
||||
LoaderKind, Progress,
|
||||
};
|
||||
pub use java::{JavaChainOutcome, JavaChainStep, JavaPageView, JavaRuntimeView, JavaVendorView};
|
||||
pub use launch_args::{LaunchArgsPatch, LaunchArgsView};
|
||||
pub use logs::{Diagnosis, DiagnosisReport, LogLevel, LogLine, LogOutcome, LogSession, SessionId};
|
||||
pub use notices::{NoticeLevel, NoticeView};
|
||||
// M113: import/export
|
||||
|
||||
Reference in new issue
Block a user