Parse vanilla to LogMeta

This commit is contained in:
2025-12-05 00:10:47 +01:00
parent 98d5e59413
commit 5f57bd8668
5 changed files with 146 additions and 19 deletions

View File

@@ -11,11 +11,13 @@ license = "MIT"
publish = false
[features]
default = ["core", "events"]
default = ["core", "events", "mc-vanilla"]
# Core runtime requirements for the currently implemented functionality.
core = ["dep:thiserror", "dep:tokio", "dep:tokio-stream", "dep:tokio-util"]
# Placeholder for upcoming event-driven functionality.
events = []
mc-vanilla = []
# Add new feature groups here; attach their optional dependencies to the relevant feature list.
[dependencies]

View File

@@ -1,5 +1,5 @@
pub mod stream;
pub mod version;
pub use stream::{StreamLine, StreamSource};
pub use stream::{LogMeta, StreamLine, StreamSource};
pub use version::{MinecraftType, MinecraftVersion, Snapshot, Version};

View File

@@ -1,5 +1,8 @@
use std::fmt::{self, Display};
#[cfg(feature = "mc-vanilla")]
use crate::error::ParserError;
/// Identifies which process stream produced a line of output.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StreamSource {
@@ -22,6 +25,101 @@ pub struct InstanceEvent {}
#[cfg(feature = "events")]
pub enum Events {}
#[cfg(feature = "mc-vanilla")]
pub struct LogMeta {
time: String,
thread: String,
level: LogLevel,
msg: String,
}
#[cfg(feature = "mc-vanilla")]
pub enum LogLevel {
Info,
Warn,
Error,
Other,
}
#[cfg(feature = "mc-vanilla")]
impl LogMeta {
pub fn new<S: Into<String>>(line: S) -> Result<Option<Self>, ParserError> {
let line: String = line.into();
let line = line.trim();
if !line.starts_with('[') {
return Ok(None);
}
let time_end = match line.find(']') {
Some(i) => i,
None => return Ok(None),
};
let time = line[1..time_end].to_string();
let meta_start = match line[time_end + 1..].find('[') {
Some(j) => time_end + 1 + j,
None => return Ok(None),
};
let msg_sep = match line[meta_start..].find("]: ") {
Some(k) => meta_start + k,
None => return Ok(None),
};
let meta = &line[(meta_start + 1)..msg_sep]; // inside the brackets
let msg = line[(msg_sep + 3)..].to_string(); // after "]: "
let mut thread_level = meta.splitn(2, '/');
let thread = thread_level
.next()
.ok_or(ParserError::ParserError)?
.to_string();
let level_str = thread_level
.next()
.ok_or(ParserError::ParserError)?
.trim_end_matches(']'); // just in case
let level = match level_str {
"INFO" => LogLevel::Info,
"WARN" => LogLevel::Warn,
"ERROR" => LogLevel::Error,
_ => LogLevel::Other,
};
Ok(Some(LogMeta {
time,
thread,
level,
msg,
}))
}
}
#[cfg(feature = "mc-vanilla")]
impl Display for LogMeta {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let line = format!(
"Time: {}\nThread: {}\nLevel: {}\nMessage: {}",
self.time, self.thread, self.level, self.msg
);
write!(f, "{}", line)
}
}
#[cfg(feature = "mc-vanilla")]
impl Display for LogLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
LogLevel::Info => write!(f, "INFO"),
LogLevel::Warn => write!(f, "WARN"),
LogLevel::Error => write!(f, "ERROR"),
LogLevel::Other => write!(f, "OTHER"),
}
}
}
impl StreamLine {
pub fn new<S: Into<String>>(line: S, source: StreamSource) -> Self {
Self {
@@ -43,6 +141,10 @@ impl StreamLine {
source: StreamSource::Stderr,
}
}
pub fn msg(&self) -> String {
self.line.clone()
}
}
impl Display for StreamLine {

View File

@@ -92,3 +92,10 @@ pub enum ServerError {
#[error("Failed to write to stdin")]
StdinWriteFailed,
}
#[cfg(feature = "events")]
#[derive(Debug, Clone, Error)]
pub enum ParserError {
#[error("ParserError")]
ParserError,
}

View File

@@ -74,7 +74,7 @@ impl InstanceHandle {
root_dir: root,
jar_path: path,
mc_version: parsed_version,
mc_type: mc_type,
mc_type,
};
let status = InstanceStatus::Stopped;
@@ -248,14 +248,18 @@ impl InstanceHandle {
Ok(())
}
#[cfg(feature = "events")]
#[cfg(all(feature = "events", any(feature = "mc-vanilla")))]
fn setup_parser(&mut self) -> Result<(), ServerError> {
let stdout_stream = self
.subscribe(StreamSource::Stdout)
.map_err(|_| ServerError::NoStdoutPipe)?;
let shutdown = self.shutdown.clone();
let event_tx = self.events_tx.clone();
// TODO: Stream events!!!!
let _event_tx = self.events_tx.clone();
#[cfg(feature = "mc-vanilla")]
if self.data.mc_type == MinecraftType::Vanilla {
use crate::config::LogMeta;
tokio::spawn(async move {
let mut rx = stdout_stream;
@@ -266,7 +270,18 @@ impl InstanceHandle {
}
line = rx.next() => {
match line {
Some(Ok(_)) => {
Some(Ok(val)) => {
let msg = val.msg();
let meta = LogMeta::new(msg);
match meta {
Ok(val) => {
if val.is_some() {
println!("{}", val.unwrap());
}
}
Err(_) => (),
}
},
_ => (),
}
@@ -274,6 +289,7 @@ impl InstanceHandle {
}
}
});
}
Ok(())
}