CI / fmt (rustfmt --check) (push) Canceled after 0s
CI / clippy (ubuntu-latest) (push) Canceled after 0s
CI / clippy (windows-latest) (push) Canceled after 0s
CI / test (ubuntu-latest) (push) Canceled after 0s
CI / test (windows-latest) (push) Canceled after 0s
CI / build release (ubuntu-latest) (push) Canceled after 0s
CI / build release (windows-latest) (push) Canceled after 0s
Guards / core 零 UI 守门 (push) Canceled after 0s
Guards / 文件行数 ≤400 守门 (push) Canceled after 0s
Guards / 依赖许可与来源(cargo-deny) (push) Canceled after 0s
Rust 原生单文件 Minecraft 启动器:CLI 完整可用(install/launch/accounts/java/diagnose/agent), MCP server 接入外部 Agent 工具,GUI 开发中。
65 lines
2.0 KiB
Rust
65 lines
2.0 KiB
Rust
//! 把会话事件流接到日志泵上:逐行落盘 + 自动窗口出现检测。
|
|
//!
|
|
//! 放在单独文件是为了让 [`crate::launch::session`] 保持“只写事件、只管索引”的单一职责,
|
|
//! 也避免单文件超过 400 行的硬约束。
|
|
|
|
use std::sync::Mutex;
|
|
|
|
use crate::launch::pump::{LineSink, LogLine};
|
|
use crate::launch::session::SessionWriter;
|
|
use crate::launch::window_detect::WindowDetector;
|
|
|
|
/// 会话日志 sink。
|
|
#[derive(Debug)]
|
|
pub struct SessionSink {
|
|
writer: Mutex<SessionWriter>,
|
|
detector: Mutex<WindowDetector>,
|
|
}
|
|
|
|
impl SessionSink {
|
|
/// 以进程启动时刻为窗口检测起点。
|
|
pub fn new(writer: SessionWriter) -> Self {
|
|
Self {
|
|
writer: Mutex::new(writer),
|
|
detector: Mutex::new(WindowDetector::new()),
|
|
}
|
|
}
|
|
|
|
/// 指定窗口检测计时起点(进程 spawn 时刻)。
|
|
pub fn with_start(writer: SessionWriter, started_at: std::time::Instant) -> Self {
|
|
Self {
|
|
writer: Mutex::new(writer),
|
|
detector: Mutex::new(WindowDetector::with_start(started_at)),
|
|
}
|
|
}
|
|
|
|
/// 借用写入器(退出分析、结束会话等需要可变访问的场合)。
|
|
pub fn with_writer<R>(&self, action: impl FnOnce(&mut SessionWriter) -> R) -> Option<R> {
|
|
self.writer.lock().ok().map(|mut guard| action(&mut guard))
|
|
}
|
|
|
|
/// 是否已检测到游戏窗口。
|
|
pub fn window_detected(&self) -> bool {
|
|
match self.writer.lock() {
|
|
Ok(writer) => writer.is_window_detected(),
|
|
Err(_) => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl LineSink for SessionSink {
|
|
fn on_line(&self, line: &LogLine) {
|
|
let detection = match self.detector.lock() {
|
|
Ok(mut detector) => detector.observe(&line.text),
|
|
Err(_) => None,
|
|
};
|
|
let Ok(mut writer) = self.writer.lock() else {
|
|
return;
|
|
};
|
|
if let Some(detection) = detection {
|
|
let _ = writer.window_detected(&detection);
|
|
}
|
|
let _ = writer.line(line);
|
|
}
|
|
}
|