diff --git a/Cargo.lock b/Cargo.lock index 16fd6b7fa..fc8c6e1c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,9 +636,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crossfire" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e1ff29ef3add47897a4dab381889ccf8dedcedec4e2c8feed37efcf22a6392b" +checksum = "cf9c756fd351d7bc1f95698a33a90ce39c8f7458335cc7e95132d3d36124902a" dependencies = [ "crossbeam-utils", "futures-core", @@ -2386,7 +2386,7 @@ dependencies = [ [[package]] name = "rand" version = "0.10.0-rc.8" -source = "git+https://github.com/rust-random/rand#47455a0b004d5992d2a3d23ecf244f1edea27f40" +source = "git+https://github.com/rust-random/rand#a4c9a8e565fa310de423e3ba89593b647b721e8c" dependencies = [ "chacha20", "getrandom 0.4.0-rc.1", diff --git a/Cargo.toml b/Cargo.toml index 5f1b844be..8cdfdf932 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,7 +115,7 @@ console-subscriber = { version = "0.5.0", default-features = false } crc-fast = "1.10.0" criterion = { version = "0.8", default-features = false } crossbeam-utils = "0.8.21" -crossfire = { version= "3.0.2", features = ["compat"]} +crossfire = { version= "3.0.3", features = ["compat"]} dashmap = "6.1" ecdsa = "0.16.9" enum_dispatch = "0.3.13" diff --git a/pumpkin-util/src/text/color.rs b/pumpkin-util/src/text/color.rs index 0382acc8a..aad2df19b 100644 --- a/pumpkin-util/src/text/color.rs +++ b/pumpkin-util/src/text/color.rs @@ -92,6 +92,41 @@ impl Color { Self::Rgb(color) => text.truecolor(color.red, color.green, color.blue), } } + + #[must_use] + pub const fn from_legacy_code(code: char) -> Option { + let named = match code.to_ascii_lowercase() { + '0' => NamedColor::Black, + '1' => NamedColor::DarkBlue, + '2' => NamedColor::DarkGreen, + '3' => NamedColor::DarkAqua, + '4' => NamedColor::DarkRed, + '5' => NamedColor::DarkPurple, + '6' => NamedColor::Gold, + '7' => NamedColor::Gray, + '8' => NamedColor::DarkGray, + '9' => NamedColor::Blue, + 'a' => NamedColor::Green, + 'b' => NamedColor::Aqua, + 'c' => NamedColor::Red, + 'd' => NamedColor::LightPurple, + 'e' => NamedColor::Yellow, + 'f' => NamedColor::White, + _ => return None, + }; + Some(Self::Named(named)) + } + + #[must_use] + pub fn from_hex_str(hex: &str) -> Option { + if hex.len() != 6 { + return None; + } + let r = u8::from_str_radix(&hex[0..2], 16).ok()?; + let g = u8::from_str_radix(&hex[2..4], 16).ok()?; + let b = u8::from_str_radix(&hex[4..6], 16).ok()?; + Some(Self::Rgb(RGBColor::new(r, g, b))) + } } #[derive(Debug, Deserialize, Clone, Copy, Eq, Hash, PartialEq)] diff --git a/pumpkin-util/src/text/mod.rs b/pumpkin-util/src/text/mod.rs index 7996e7d4e..92939a50d 100644 --- a/pumpkin-util/src/text/mod.rs +++ b/pumpkin-util/src/text/mod.rs @@ -284,6 +284,109 @@ impl TextComponent { }) } + #[must_use] + pub fn from_legacy_string(input: &str) -> Self { + let mut root = Self::text(""); + let parts: Vec<&str> = input.split('ยง').collect(); + + if !parts[0].is_empty() { + root = root.add_child(Self::text(parts[0].to_string())); + } + + let mut current_color: Option = None; + let mut bold = false; + let mut italic = false; + let mut underlined = false; + let mut strikethrough = false; + let mut obfuscated = false; + + let mut i = 1; + while i < parts.len() { + let part = parts[i]; + if part.is_empty() { + i += 1; + continue; + } + + let mut chars = part.chars(); + let code = chars.next().unwrap_or(' ').to_ascii_lowercase(); + let remainder = &part[1..]; + + match code { + 'x' if i + 6 < parts.len() => { + let mut hex = String::new(); + for j in 1..=6 { + if let Some(c) = parts[i + j].chars().next() { + hex.push(c); + } + } + current_color = Color::from_hex_str(&hex); + + i += 6; + + let last_part = parts[i]; + if last_part.len() > 1 { + let mut child = Self::text(last_part[1..].to_string()); + if let Some(c) = current_color { + child = child.color(c); + } + root = root.add_child(child); + } + i += 1; + continue; + } + '0'..='9' | 'a'..='f' => { + current_color = Color::from_legacy_code(code); + bold = false; + italic = false; + underlined = false; + strikethrough = false; + obfuscated = false; + } + 'l' => bold = true, + 'o' => italic = true, + 'n' => underlined = true, + 'm' => strikethrough = true, + 'k' => obfuscated = true, + 'r' => { + current_color = None; + bold = false; + italic = false; + underlined = false; + strikethrough = false; + obfuscated = false; + } + _ => {} + } + + if !remainder.is_empty() { + let mut child = Self::text(remainder.to_string()); + if let Some(c) = current_color { + child = child.color(c); + } + if bold { + child = child.bold(); + } + if italic { + child = child.italic(); + } + if underlined { + child = child.underlined(); + } + if strikethrough { + child = child.strikethrough(); + } + if obfuscated { + child = child.obfuscated(); + } + root = root.add_child(child); + } + i += 1; + } + + root + } + #[must_use] pub fn add_child(mut self, child: Self) -> Self { self.0.extra.push(child.0); diff --git a/pumpkin-world/src/chunk_system.rs b/pumpkin-world/src/chunk_system.rs index 9faf69277..ecbeab030 100644 --- a/pumpkin-world/src/chunk_system.rs +++ b/pumpkin-world/src/chunk_system.rs @@ -983,7 +983,7 @@ impl GenerationCache for Cache { // debug_assert!(dx >= 0 && dz >= 0); if !(dx < self.size && dz < self.size && dx >= 0 && dz >= 0) { // breakpoint here - log::error!( + log::debug!( "illegal get_block_state {pos:?} cache pos ({}, {}) size {}", self.x, self.z, @@ -1011,7 +1011,7 @@ impl GenerationCache for Cache { // debug_assert!(dx >= 0 && dz >= 0); if !(dx < self.size && dz < self.size && dx >= 0 && dz >= 0) { // breakpoint here - log::error!( + log::debug!( "illegal set_block_state {pos:?} cache pos ({}, {}) size {}", self.x, self.z, diff --git a/pumpkin/src/lib.rs b/pumpkin/src/lib.rs index e4021b799..d3cff2b27 100644 --- a/pumpkin/src/lib.rs +++ b/pumpkin/src/lib.rs @@ -178,8 +178,6 @@ impl PumpkinServer { let rcon = server.advanced_config.networking.rcon.clone(); - let mut ticker = Ticker::new(); - if server.advanced_config.commands.use_console && let Some((wrapper, _)) = LOGGER_IMPL.wait() { @@ -267,7 +265,7 @@ impl PumpkinServer { { let ticker_server = server.clone(); server.spawn_task(async move { - ticker.run(&ticker_server).await; + Ticker::run(&ticker_server).await; }); }; diff --git a/pumpkin/src/server/ticker.rs b/pumpkin/src/server/ticker.rs index 04460ac91..c2d82e059 100644 --- a/pumpkin/src/server/ticker.rs +++ b/pumpkin/src/server/ticker.rs @@ -5,26 +5,12 @@ use std::{ }; use tokio::time::sleep; -pub struct Ticker { - last_tick: Instant, -} - -impl Default for Ticker { - fn default() -> Self { - Self::new() - } -} +pub struct Ticker; impl Ticker { - #[must_use] - pub fn new() -> Self { - Self { - last_tick: Instant::now(), - } - } - /// IMPORTANT: Run this in a new thread/tokio task. - pub async fn run(&mut self, server: &Arc) { + pub async fn run(server: &Arc) { + let mut last_tick = Instant::now(); while !SHOULD_STOP.load(Ordering::Relaxed) { let tick_start_time = Instant::now(); let manager = &server.tick_rate_manager; @@ -54,7 +40,7 @@ impl Ticker { // Sleep logic remains the same let now = Instant::now(); - let elapsed = now.duration_since(self.last_tick); + let elapsed = now.duration_since(last_tick); let tick_interval = if manager.is_sprinting() { Duration::ZERO @@ -68,7 +54,7 @@ impl Ticker { sleep(sleep_time).await; } - self.last_tick = Instant::now(); + last_tick = Instant::now(); } log::debug!("Ticker stopped"); }