feat(debug): 支持 JSON UI 热重载

新增可选的 auto_hot_reload_ui 配置,追踪资源包 UI JSON 的新增、修改、删除和重命名,并在游戏回到前台时发送原生 Ctrl+R。

统一 Python 与 JSON UI 的批处理和拖尾防抖逻辑,同时补充路径分类、事件动作与快捷键消息测试。
This commit is contained in:
2026-07-21 20:44:13 +08:00
parent 86a39dace7
commit 3afc122404
6 changed files with 701 additions and 195 deletions

View File

@@ -4,7 +4,7 @@ use crate::error::{CliError, Result};
use super::{
config::{DebugConfig, ResolvedModDir},
hotreload::HotReloadTask,
hotreload::{HotReloadOptions, HotReloadTask},
ipc::DebugIpcServer,
log::{self, LineBuffer},
};
@@ -52,9 +52,13 @@ pub fn launch_game(
let command = build_command(config, config_arg);
let mut command_w = wide_null(OsStr::new(&command));
let env_block = ipc
.as_ref()
.map(|server| build_environment_block(server.port()));
let env_block = if ipc.is_some() || config.auto_hot_reload_ui {
Some(build_environment_block(
ipc.as_ref().map(|server| server.port()),
))
} else {
None
};
let mut security = SECURITY_ATTRIBUTES {
nLength: std::mem::size_of::<SECURITY_ATTRIBUTES>() as u32,
@@ -116,12 +120,15 @@ pub fn launch_game(
let stderr_thread =
thread::spawn(move || read_pipe(err_read, stderr_filter, log::process_stderr_line));
let mut hotreload = if config.auto_hot_reload_mods {
ipc.clone()
.and_then(|server| HotReloadTask::start(pid, mod_dirs, server))
} else {
None
};
let mut hotreload = HotReloadTask::start(
pid,
mod_dirs,
ipc.clone(),
HotReloadOptions {
python: config.auto_hot_reload_mods,
json_ui: config.auto_hot_reload_ui,
},
);
unsafe { WaitForSingleObject(process_info.hProcess, INFINITE) };
@@ -223,14 +230,21 @@ where
}
#[cfg(windows)]
fn build_environment_block(ipc_port: u16) -> Vec<u16> {
fn build_environment_block(ipc_port: Option<u16>) -> Vec<u16> {
let mut pairs: Vec<(Vec<u16>, Vec<u16>)> = std::env::vars_os()
.filter(|(key, _)| {
let key = key.to_string_lossy();
!key.eq_ignore_ascii_case("MCDEV_DEBUG_IPC_PORT")
})
.map(|(key, value)| (key.encode_wide().collect(), value.encode_wide().collect()))
.collect();
pairs.push((
OsStr::new("MCDEV_DEBUG_IPC_PORT").encode_wide().collect(),
OsStr::new(&ipc_port.to_string()).encode_wide().collect(),
));
if let Some(port) = ipc_port {
pairs.push((
OsStr::new("MCDEV_DEBUG_IPC_PORT").encode_wide().collect(),
OsStr::new(&port.to_string()).encode_wide().collect(),
));
}
pairs.sort_by(|a, b| a.0.cmp(&b.0));
let mut block = Vec::new();