From 5d10c0d8a892d303d47f931327bf5455a2a86472 Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Wed, 5 Aug 2026 21:10:50 +0200 Subject: [PATCH] chore: use translations for ags --- Cargo.lock | 22 +- Cargo.toml | 2 +- pumpkin-util/src/text/mod.rs | 80 ++++ pumpkin-util/src/version.rs | 10 +- .../noise/router/multi_noise_sampler.rs | 14 +- .../noise/router/proto_noise_router.rs | 3 + .../noise/router/surface_height_sampler.rs | 14 +- pumpkin-world/src/lib.rs | 4 +- pumpkin/src/command/args/bounded_num.rs | 64 +++- pumpkin/src/command/args/sound.rs | 8 +- .../src/command/args/summonable_entities.rs | 6 +- pumpkin/src/command/commands/pumpkin.rs | 342 +++++++++++------- pumpkin/src/main.rs | 18 +- .../loader/wasm/wasm_host/wit/v0_1/player.rs | 2 +- 14 files changed, 401 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b13aa469d..98a039a46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2612,7 +2612,7 @@ dependencies = [ [[package]] name = "pumpkin" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "arc-swap", "base64 0.23.1", @@ -2675,7 +2675,7 @@ dependencies = [ [[package]] name = "pumpkin-api-macros" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "proc-macro-error2", "proc-macro2", @@ -2685,7 +2685,7 @@ dependencies = [ [[package]] name = "pumpkin-codecs" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "serde_json", "tracing", @@ -2693,7 +2693,7 @@ dependencies = [ [[package]] name = "pumpkin-config" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "pumpkin-util", "serde", @@ -2704,7 +2704,7 @@ dependencies = [ [[package]] name = "pumpkin-data" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "crc-fast", "criterion", @@ -2717,7 +2717,7 @@ dependencies = [ [[package]] name = "pumpkin-inventory" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "pumpkin-data", "pumpkin-protocol", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "pumpkin-macros" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "heck", "proc-macro-error2", @@ -2742,7 +2742,7 @@ dependencies = [ [[package]] name = "pumpkin-nbt" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "bytes", "cesu8", @@ -2768,7 +2768,7 @@ dependencies = [ [[package]] name = "pumpkin-protocol" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "aes", "async-compression", @@ -2792,7 +2792,7 @@ dependencies = [ [[package]] name = "pumpkin-util" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "base64 0.23.1", "bytes", @@ -2820,7 +2820,7 @@ dependencies = [ [[package]] name = "pumpkin-world" -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" dependencies = [ "arc-swap", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 9df9e40e4..7460b71cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,7 +77,7 @@ module_name_repetitions = "allow" struct_excessive_bools = "allow" [workspace.package] -version = "0.1.0-dev+26.2" +version = "0.1.0-dev+26.2-26.40" edition = "2024" rust-version = "1.95" license = "GPL-3.0" diff --git a/pumpkin-util/src/text/mod.rs b/pumpkin-util/src/text/mod.rs index 5eb8784f3..83e12df69 100644 --- a/pumpkin-util/src/text/mod.rs +++ b/pumpkin-util/src/text/mod.rs @@ -97,6 +97,7 @@ pub struct TextComponentBase { impl TextComponentBase { /// Converts this component to an NBT compound tag. + #[expect(clippy::too_many_lines)] #[must_use] pub fn to_nbt_compound(&self) -> pumpkin_nbt::NbtCompound { let mut compound = pumpkin_nbt::NbtCompound::new(); @@ -189,6 +190,83 @@ impl TextComponentBase { compound.put_byte("obfuscated", i8::from(obfuscated)); } + if let Some(ref click) = self.style.click_event { + let mut click_tag = pumpkin_nbt::NbtCompound::new(); + match click { + ClickEvent::OpenUrl { url } => { + click_tag.put_string("action", "open_url".to_string()); + click_tag.put_string("url", url.to_string()); + } + ClickEvent::OpenFile { path } => { + click_tag.put_string("action", "open_file".to_string()); + click_tag.put_string("path", path.to_string()); + } + ClickEvent::RunCommand { command } => { + click_tag.put_string("action", "run_command".to_string()); + click_tag.put_string("command", command.to_string()); + } + ClickEvent::SuggestCommand { command } => { + click_tag.put_string("action", "suggest_command".to_string()); + click_tag.put_string("command", command.to_string()); + } + ClickEvent::ChangePage { page } => { + click_tag.put_string("action", "change_page".to_string()); + click_tag.put_int("page", *page as i32); + } + ClickEvent::CopyToClipboard { value } => { + click_tag.put_string("action", "copy_to_clipboard".to_string()); + click_tag.put_string("value", value.to_string()); + } + } + compound.put_compound("click_event", click_tag); + } + + if let Some(ref hover) = self.style.hover_event { + let mut hover_tag = pumpkin_nbt::NbtCompound::new(); + match hover { + HoverEvent::ShowText { value } => { + hover_tag.put_string("action", "show_text".to_string()); + if value.len() == 1 { + hover_tag.put_compound("value", value[0].to_nbt_compound()); + } else { + let list = value + .iter() + .map(|e| pumpkin_nbt::tag::NbtTag::Compound(e.to_nbt_compound())) + .collect(); + hover_tag.put_list("value", list); + } + } + HoverEvent::ShowItem { id, count } => { + hover_tag.put_string("action", "show_item".to_string()); + let mut item_tag = pumpkin_nbt::NbtCompound::new(); + item_tag.put_string("id", id.to_string()); + if let Some(cnt) = count { + item_tag.put_int("count", *cnt); + } + hover_tag.put_compound("item", item_tag); + } + HoverEvent::ShowEntity { id, uuid, name } => { + hover_tag.put_string("action", "show_entity".to_string()); + let mut entity_tag = pumpkin_nbt::NbtCompound::new(); + entity_tag.put_string("id", id.to_string()); + entity_tag.put_string("uuid", uuid.to_string()); + if let Some(n) = name { + if n.len() == 1 { + entity_tag.put_compound("name", n[0].to_nbt_compound()); + } else { + let list = n + .iter() + .map(|e| pumpkin_nbt::tag::NbtTag::Compound(e.to_nbt_compound())) + .collect(); + entity_tag.put_list("name", list); + } + } + hover_tag.put_compound("entity", entity_tag); + } + } + compound.put_compound("hover_event", hover_tag); + } + if !self.extra.is_empty() { let list = self .extra @@ -893,6 +971,8 @@ impl TextComponent { self.0.content = Box::new(TextContent::Text { text: "".into() }); self.0.extra = colored_extra; + self.0.style.click_event = None; + self.0.style.hover_event = None; self } diff --git a/pumpkin-util/src/version.rs b/pumpkin-util/src/version.rs index 897dc5714..2431c3336 100644 --- a/pumpkin-util/src/version.rs +++ b/pumpkin-util/src/version.rs @@ -271,8 +271,8 @@ impl std::fmt::Display for JavaMinecraftVersion { pub enum BedrockMinecraftVersion { /// 1.21: Tricky Trials. V_1_21, - /// 1.26.30 - V_1_26_30, + /// 1.26.40 + V_1_26_40, /// Fallback for unrecognized protocol versions. Unknown, } @@ -285,7 +285,7 @@ impl BedrockMinecraftVersion { pub const fn protocol_version(&self) -> i32 { match self { Self::V_1_21 => 671, - Self::V_1_26_30 => 1001, + Self::V_1_26_40 => 2168, Self::Unknown => -1, } } @@ -297,7 +297,7 @@ impl BedrockMinecraftVersion { pub const fn from_protocol(protocol: u32) -> Self { match protocol { 671 => Self::V_1_21, - 1001 => Self::V_1_26_30, + 2168 => Self::V_1_26_40, _ => Self::Unknown, } } @@ -307,7 +307,7 @@ impl std::fmt::Display for BedrockMinecraftVersion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::V_1_21 => write!(f, "1.21"), - Self::V_1_26_30 => write!(f, "1.26.30"), + Self::V_1_26_40 => write!(f, "1.26.40"), Self::Unknown => write!(f, "unknown"), } } diff --git a/pumpkin-world/src/generation/noise/router/multi_noise_sampler.rs b/pumpkin-world/src/generation/noise/router/multi_noise_sampler.rs index 482b61409..a16b164f2 100644 --- a/pumpkin-world/src/generation/noise/router/multi_noise_sampler.rs +++ b/pumpkin-world/src/generation/noise/router/multi_noise_sampler.rs @@ -13,7 +13,9 @@ use super::{ }, chunk_noise_router::ChunkNoiseFunctionComponent, density_function::{NoiseFunctionComponentRange, PassThrough}, - proto_noise_router::{ProtoMultiNoiseRouter, ProtoNoiseFunctionComponent}, + proto_noise_router::{ + BEARDIFIER_ZERO_CONSTANT, ProtoMultiNoiseRouter, ProtoNoiseFunctionComponent, + }, }; pub struct MultiNoiseSamplerBuilderOptions { @@ -136,13 +138,9 @@ impl<'a> MultiNoiseSampler<'a> { ProtoNoiseFunctionComponent::PassThrough(pass_through) => { ChunkNoiseFunctionComponent::PassThrough(pass_through.clone()) } - ProtoNoiseFunctionComponent::Beardifier(_) => ChunkNoiseFunctionComponent::Independent( - Box::leak(Box::new( - crate::generation::noise::router::proto_noise_router::IndependentProtoNoiseFunctionComponent::Constant( - crate::generation::noise::router::density_function::math::Constant::new(0.0), - ), - )), - ), + ProtoNoiseFunctionComponent::Beardifier(_) => { + ChunkNoiseFunctionComponent::Independent(&BEARDIFIER_ZERO_CONSTANT) + } ProtoNoiseFunctionComponent::Wrapper(wrapper) => { //NOTE: Due to our previous invariant with the proto-function, it is guaranteed // that the wrapped function is already on the stack diff --git a/pumpkin-world/src/generation/noise/router/proto_noise_router.rs b/pumpkin-world/src/generation/noise/router/proto_noise_router.rs index a77972f10..ebd0d520c 100644 --- a/pumpkin-world/src/generation/noise/router/proto_noise_router.rs +++ b/pumpkin-world/src/generation/noise/router/proto_noise_router.rs @@ -29,6 +29,9 @@ use super::{ }; use pumpkin_util::math::vector3::Vector3; +pub static BEARDIFIER_ZERO_CONSTANT: IndependentProtoNoiseFunctionComponent = + IndependentProtoNoiseFunctionComponent::Constant(Constant::new(0.0)); + pub enum IndependentProtoNoiseFunctionComponent { Constant(Constant), EndIsland(EndIsland), diff --git a/pumpkin-world/src/generation/noise/router/surface_height_sampler.rs b/pumpkin-world/src/generation/noise/router/surface_height_sampler.rs index f4f42752b..2ec373cfe 100644 --- a/pumpkin-world/src/generation/noise/router/surface_height_sampler.rs +++ b/pumpkin-world/src/generation/noise/router/surface_height_sampler.rs @@ -11,7 +11,9 @@ use super::{ }, chunk_noise_router::ChunkNoiseFunctionComponent, density_function::{NoiseFunctionComponentRange, PassThrough}, - proto_noise_router::{ProtoNoiseFunctionComponent, ProtoSurfaceEstimator}, + proto_noise_router::{ + BEARDIFIER_ZERO_CONSTANT, ProtoNoiseFunctionComponent, ProtoSurfaceEstimator, + }, }; pub struct SurfaceHeightSamplerBuilderOptions { @@ -140,13 +142,9 @@ impl<'a> SurfaceHeightEstimateSampler<'a> { ProtoNoiseFunctionComponent::PassThrough(pass_through) => { ChunkNoiseFunctionComponent::PassThrough(pass_through.clone()) } - ProtoNoiseFunctionComponent::Beardifier(_) => ChunkNoiseFunctionComponent::Independent( - Box::leak(Box::new( - crate::generation::noise::router::proto_noise_router::IndependentProtoNoiseFunctionComponent::Constant( - crate::generation::noise::router::density_function::math::Constant::new(0.0), - ), - )), - ), + ProtoNoiseFunctionComponent::Beardifier(_) => { + ChunkNoiseFunctionComponent::Independent(&BEARDIFIER_ZERO_CONSTANT) + } ProtoNoiseFunctionComponent::Wrapper(wrapper) => { //NOTE: Due to our previous invariant with the proto-function, it is guaranteed // that the wrapped function is already on the stack diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index c719d3ca1..ff3f294f9 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -22,8 +22,8 @@ pub mod world; pub mod world_info; pub const CURRENT_MC_VERSION: &str = "26.2"; -pub const CURRENT_BEDROCK_MC_VERSION: &str = "1.26.30"; -pub const CURRENT_BEDROCK_MC_PROTOCOL: u32 = 1001; +pub const CURRENT_BEDROCK_MC_VERSION: &str = "1.26.40"; +pub const CURRENT_BEDROCK_MC_PROTOCOL: u32 = 2168; #[macro_export] macro_rules! global_path { diff --git a/pumpkin/src/command/args/bounded_num.rs b/pumpkin/src/command/args/bounded_num.rs index 91360bb1c..5b4e1ae99 100644 --- a/pumpkin/src/command/args/bounded_num.rs +++ b/pumpkin/src/command/args/bounded_num.rs @@ -87,18 +87,54 @@ pub enum NotInBounds { impl From for CommandError { fn from(value: NotInBounds) -> Self { match value { - NotInBounds::LowerBound(val, min) => Self::CommandFailed(TextComponent::text(format!( - "{} must not be less than {}, found {}", - val.qualifier(), - min, - val - ))), - NotInBounds::UpperBound(val, max) => Self::CommandFailed(TextComponent::text(format!( - "{} must not be more than {}, found {}", - val.qualifier(), - max, - val - ))), + NotInBounds::LowerBound(val, min) => { + let (key, min_text, val_text) = match val { + Number::F64(_) | Number::F32(_) => ( + pumpkin_data::translation::java::ARGUMENT_DOUBLE_LOW, + min.to_string(), + val.to_string(), + ), + Number::I32(_) => ( + pumpkin_data::translation::java::ARGUMENT_INTEGER_LOW, + min.to_string(), + val.to_string(), + ), + Number::I64(_) => ( + pumpkin_data::translation::java::ARGUMENT_LONG_LOW, + min.to_string(), + val.to_string(), + ), + }; + Self::CommandFailed(TextComponent::translate_cross( + key, + key, + [TextComponent::text(min_text), TextComponent::text(val_text)], + )) + } + NotInBounds::UpperBound(val, max) => { + let (key, max_text, val_text) = match val { + Number::F64(_) | Number::F32(_) => ( + pumpkin_data::translation::java::ARGUMENT_DOUBLE_BIG, + max.to_string(), + val.to_string(), + ), + Number::I32(_) => ( + pumpkin_data::translation::java::ARGUMENT_INTEGER_BIG, + max.to_string(), + val.to_string(), + ), + Number::I64(_) => ( + pumpkin_data::translation::java::ARGUMENT_LONG_BIG, + max.to_string(), + val.to_string(), + ), + }; + Self::CommandFailed(TextComponent::translate_cross( + key, + key, + [TextComponent::text(max_text), TextComponent::text(val_text)], + )) + } } } } @@ -124,8 +160,8 @@ impl Number { impl Display for Number { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - Self::F64(v) => write!(f, "{v:.2}"), - Self::F32(v) => write!(f, "{v:.2}"), + Self::F64(v) => write!(f, "{v}"), + Self::F32(v) => write!(f, "{v}"), Self::I32(v) => write!(f, "{v}"), Self::I64(v) => write!(f, "{v}"), } diff --git a/pumpkin/src/command/args/sound.rs b/pumpkin/src/command/args/sound.rs index ff957a617..e392ce591 100644 --- a/pumpkin/src/command/args/sound.rs +++ b/pumpkin/src/command/args/sound.rs @@ -54,9 +54,11 @@ impl<'a> FindArg<'a> for SoundArgumentConsumer { Some(Arg::Block(name)) => { Sound::from_name(name.strip_prefix("minecraft:").unwrap_or(name)).map_or_else( || { - Err(CommandError::CommandFailed(TextComponent::text(format!( - "Sound {name} does not exist." - )))) + Err(CommandError::CommandFailed(TextComponent::translate_cross( + pumpkin_data::translation::java::ARGUMENT_ID_INVALID, + pumpkin_data::translation::java::ARGUMENT_ID_INVALID, + [], + ))) }, Result::Ok, ) diff --git a/pumpkin/src/command/args/summonable_entities.rs b/pumpkin/src/command/args/summonable_entities.rs index bd0b9103c..90013ddea 100644 --- a/pumpkin/src/command/args/summonable_entities.rs +++ b/pumpkin/src/command/args/summonable_entities.rs @@ -54,8 +54,10 @@ impl<'a> FindArg<'a> for SummonableEntitiesArgumentConsumer { Some(Arg::Block(name)) => { EntityType::from_name(name.strip_prefix("minecraft:").unwrap_or(name)).map_or_else( || { - Err(CommandError::CommandFailed(TextComponent::text( - "Can't find Entity", + Err(CommandError::CommandFailed(TextComponent::translate_cross( + pumpkin_data::translation::java::ARGUMENT_ENTITY_INVALID, + pumpkin_data::translation::java::ARGUMENT_ENTITY_INVALID, + [], ))) }, Result::Ok, diff --git a/pumpkin/src/command/commands/pumpkin.rs b/pumpkin/src/command/commands/pumpkin.rs index ab6a1a014..e0e55ba43 100644 --- a/pumpkin/src/command/commands/pumpkin.rs +++ b/pumpkin/src/command/commands/pumpkin.rs @@ -66,6 +66,113 @@ fn extract_next_url(header: &str) -> Option { }) } +#[derive(Deserialize)] +struct Donator { + name: String, + tier: String, + tier_slug: String, +} + +#[derive(Deserialize)] +struct DonatorResponse { + current: Vec, + #[allow(dead_code)] + past: Vec, +} + +fn tier_priority(tier_slug: &str, tier_name: &str) -> u32 { + let s = format!("{tier_slug} {tier_name}").to_lowercase(); + + if s.contains("corporate platinum") || s.contains("corp platinum") { + 1 + } else if s.contains("corporate gold") || s.contains("corp gold") { + 2 + } else if s.contains("corporate silver") || s.contains("corp silver") { + 3 + } else if s.contains("corporate bronze") || s.contains("corp bronze") { + 4 + } else if s.contains("diamond") { + 5 + } else if s.contains("titanium") { + 6 + } else if s.contains("platinum") { + 7 + } else if s.contains("gold") { + 8 + } else if s.contains("silver") { + 9 + } else if s.contains("bronze") { + 10 + } else { + 11 + } +} + +fn tier_color(tier_slug: &str, tier_name: &str) -> NamedColor { + let s = format!("{tier_slug} {tier_name}").to_lowercase(); + + if s.contains("diamond") { + NamedColor::Aqua + } else if s.contains("titanium") { + NamedColor::DarkAqua + } else if s.contains("platinum") { + NamedColor::LightPurple + } else if s.contains("gold") { + NamedColor::Gold + } else if s.contains("silver") { + NamedColor::Gray + } else if s.contains("bronze") { + NamedColor::DarkRed + } else { + NamedColor::White + } +} + +fn fetch_donators_hover() -> TextComponent { + let url = "https://market.pumpkinmc.org/api/v1/rest/donators"; + let response = ureq::get(url).header("User-Agent", "Pumpkin-MC").call(); + + let mut donators_text = TextComponent::text("Click to open Donate\n\nDonators:\n"); + + if let Ok(mut res) = response + && let Ok(data) = res.body_mut().read_json::() + { + let mut current = data.current; + current.sort_by(|a, b| { + let prio_a = tier_priority(&a.tier_slug, &a.tier); + let prio_b = tier_priority(&b.tier_slug, &b.tier); + prio_a + .cmp(&prio_b) + .then_with(|| a.tier.cmp(&b.tier)) + .then_with(|| a.name.cmp(&b.name)) + }); + + if current.is_empty() { + donators_text = donators_text.add_child(TextComponent::text("No active donators")); + } else { + let mut current_tier = String::new(); + for donator in current { + if donator.tier != current_tier { + current_tier.clone_from(&donator.tier); + let color = tier_color(&donator.tier_slug, &donator.tier); + donators_text = donators_text.add_child( + TextComponent::text(format!("\n{current_tier}:\n")) + .color_named(color) + .bold(), + ); + } + let color = tier_color(&donator.tier_slug, &donator.tier); + donators_text = donators_text.add_child( + TextComponent::text(format!(" • {}\n", donator.name)).color_named(color), + ); + } + } + return donators_text; + } + + donators_text.add_child(TextComponent::text("Unable to load donators")) +} + #[expect(clippy::too_many_lines)] impl CommandExecutor for Executor { fn execute<'a>( @@ -94,14 +201,15 @@ impl CommandExecutor for Executor { profile, contributors.len() ); - sender - .send_message( - TextComponent::custom( - "pumpkin", - "commands.pumpkin.version", - locale, - vec![TextComponent::text(version_string.clone())], - ) + let mut msg = TextComponent::text(""); + + let version_translation = get_translation_text( + "pumpkin:commands.pumpkin.version", + locale, + vec![TextComponent::text(version_string.clone()).0], + ); + msg = msg.add_child( + TextComponent::text(version_translation.clone()) .hover_event(HoverEvent::show_text( TextComponent::text(format!("Commit: {GIT_HASH_FULL}\n\nContributors:\n")) .add_child( @@ -111,131 +219,101 @@ impl CommandExecutor for Executor { ), )) .click_event(ClickEvent::CopyToClipboard { - value: Cow::from( - get_translation_text( - "pumpkin:commands.pumpkin.version", - locale, - vec![TextComponent::text(version_string).0], - ) - .replace('\n', ""), - ), + value: Cow::from(version_translation.replace('\n', "")), }) - .color_named(NamedColor::Green) - .add_child( - TextComponent::custom( - "pumpkin", - "commands.pumpkin.description", - locale, - vec![], - ) - .click_event(ClickEvent::CopyToClipboard { - value: Cow::from( - get_translation_text( - "pumpkin:commands.pumpkin.description", - locale, - vec![], - ) - .replace('\n', ""), - ), - }) - .hover_event(HoverEvent::show_text(TextComponent::custom( - "pumpkin", - "commands.pumpkin.description.hover", - locale, - vec![], - ))) - .color_named(NamedColor::White), - ) - .add_child( - TextComponent::custom( - "pumpkin", - "commands.pumpkin.minecraft_version", - locale, - vec![ - TextComponent::text(CURRENT_MC_VERSION.to_string()), - TextComponent::text( - CURRENT_MC_VERSION.protocol_version().to_string(), - ), - ], - ) - .click_event(ClickEvent::CopyToClipboard { - value: Cow::from( - get_translation_text( - "pumpkin:commands.pumpkin.minecraft_version", - locale, - vec![ - TextComponent::text(CURRENT_MC_VERSION.to_string()).0, - TextComponent::text( - CURRENT_MC_VERSION.protocol_version().to_string(), - ) - .0, - ], - ) - .replace('\n', ""), - ), - }) - .hover_event(HoverEvent::show_text(TextComponent::custom( - "pumpkin", - "commands.pumpkin.minecraft_version.hover", - locale, - vec![], - ))) - .color_named(NamedColor::Gold), - ) - // https://pumpkinmc.org/ - .add_child( - TextComponent::custom("pumpkin", "commands.pumpkin.github", locale, vec![]) - .click_event(ClickEvent::OpenUrl { - url: Cow::from("https://github.com/Pumpkin-MC/Pumpkin"), - }) - .hover_event(HoverEvent::show_text(TextComponent::custom( - "pumpkin", - "commands.pumpkin.github.hover", - locale, - vec![], - ))) - .color_named(NamedColor::Blue) - .bold() - .underlined(), - ) - // Spacing - .add_child(TextComponent::text(" ")) - .add_child( - TextComponent::text("[Donate]") - .click_event(ClickEvent::OpenUrl { - url: Cow::from("https://pumpkinmc.org/donate/"), - }) - .hover_event(HoverEvent::show_text(TextComponent::text( - "Click to open Donate", - ))) - .rainbow() - .bold() - .underlined(), - ) - // Spacing - .add_child(TextComponent::text(" ")) - .add_child( - TextComponent::custom( - "pumpkin", - "commands.pumpkin.website", - locale, - vec![], - ) - .click_event(ClickEvent::OpenUrl { - url: Cow::from("https://pumpkinmc.org/"), - }) - .hover_event(HoverEvent::show_text(TextComponent::custom( - "pumpkin", - "commands.pumpkin.website.hover", - locale, - vec![], - ))) - .color_named(NamedColor::Blue) - .bold() - .underlined(), - ), - ) - .await; + .color_named(NamedColor::Green), + ); + + let desc_translation = + get_translation_text("pumpkin:commands.pumpkin.description", locale, vec![]); + let desc_hover_translation = + get_translation_text("pumpkin:commands.pumpkin.description.hover", locale, vec![]); + msg = msg.add_child( + TextComponent::text(desc_translation.clone()) + .click_event(ClickEvent::CopyToClipboard { + value: Cow::from(desc_translation.replace('\n', "")), + }) + .hover_event(HoverEvent::show_text(TextComponent::text( + desc_hover_translation, + ))) + .color_named(NamedColor::White), + ); + + let mc_version_translation = get_translation_text( + "pumpkin:commands.pumpkin.minecraft_version", + locale, + vec![ + TextComponent::text(CURRENT_MC_VERSION.to_string()).0, + TextComponent::text(CURRENT_MC_VERSION.protocol_version().to_string()).0, + ], + ); + let mc_version_hover_translation = get_translation_text( + "pumpkin:commands.pumpkin.minecraft_version.hover", + locale, + vec![], + ); + msg = msg.add_child( + TextComponent::text(mc_version_translation.clone()) + .click_event(ClickEvent::CopyToClipboard { + value: Cow::from(mc_version_translation.replace('\n', "")), + }) + .hover_event(HoverEvent::show_text(TextComponent::text( + mc_version_hover_translation, + ))) + .color_named(NamedColor::Gold), + ); + + let github_translation = + get_translation_text("pumpkin:commands.pumpkin.github", locale, vec![]); + let github_hover_translation = + get_translation_text("pumpkin:commands.pumpkin.github.hover", locale, vec![]); + msg = msg.add_child( + TextComponent::text(github_translation) + .click_event(ClickEvent::OpenUrl { + url: Cow::from("https://github.com/Pumpkin-MC/Pumpkin"), + }) + .hover_event(HoverEvent::show_text(TextComponent::text( + github_hover_translation, + ))) + .color_named(NamedColor::Blue) + .bold() + .underlined(), + ); + + msg = msg.add_child(TextComponent::text(" ")); + + let donators_hover = fetch_donators_hover(); + msg = msg.add_child( + TextComponent::text("[Donate]") + .click_event(ClickEvent::OpenUrl { + url: Cow::from("https://pumpkinmc.org/donate/"), + }) + .hover_event(HoverEvent::show_text(donators_hover)) + .rainbow() + .bold() + .underlined(), + ); + + msg = msg.add_child(TextComponent::text(" ")); + + let website_translation = + get_translation_text("pumpkin:commands.pumpkin.website", locale, vec![]); + let website_hover_translation = + get_translation_text("pumpkin:commands.pumpkin.website.hover", locale, vec![]); + msg = msg.add_child( + TextComponent::text(website_translation) + .click_event(ClickEvent::OpenUrl { + url: Cow::from("https://pumpkinmc.org/"), + }) + .hover_event(HoverEvent::show_text(TextComponent::text( + website_hover_translation, + ))) + .color_named(NamedColor::Blue) + .bold() + .underlined(), + ); + + sender.send_message(msg).await; // It makes total sense to return the number of // contributors as the i32 result for this command. diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 5b72dfd1e..992335540 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -5,6 +5,7 @@ compile_error!("Compiling for WASI targets is not supported!"); use pumpkin_data::packet::CURRENT_MC_VERSION; +use pumpkin_world::{CURRENT_BEDROCK_MC_PROTOCOL, CURRENT_BEDROCK_MC_VERSION}; use std::{ backtrace::{Backtrace, BacktraceStatus}, io::{self}, @@ -66,7 +67,7 @@ async fn main() { info!( "{}", TextComponent::text(format!( - "Starting {} {} Minecraft (Protocol {})", + "Starting {} {} Java Minecraft (Protocol {}) | {} Bedrock (Protocol {})", TextComponent::text("Pumpkin") .color_named(NamedColor::Gold) .to_pretty_console(), @@ -74,6 +75,12 @@ async fn main() { .color_named(NamedColor::Green) .to_pretty_console(), TextComponent::text(CURRENT_MC_VERSION.protocol_version().to_string()) + .color_named(NamedColor::DarkBlue) + .to_pretty_console(), + TextComponent::text(CURRENT_BEDROCK_MC_VERSION) + .color_named(NamedColor::Gold) + .to_pretty_console(), + TextComponent::text(CURRENT_BEDROCK_MC_PROTOCOL.to_string()) .color_named(NamedColor::DarkBlue) .to_pretty_console() )) @@ -184,6 +191,15 @@ fn print_support_links_and_warning() { .color_named(NamedColor::Aqua) .to_pretty_console() ); + info!( + "Consider {} to {}", + TextComponent::text("Donating") + .color_named(NamedColor::DarkPurple) + .to_pretty_console(), + TextComponent::text("https://pumpkinmc.org/donate/") + .color_named(NamedColor::Gold) + .to_pretty_console() + ); } fn handle_interrupt() { diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/player.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/player.rs index c41c332fd..7a0eae57c 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/player.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/player.rs @@ -111,7 +111,7 @@ const fn to_wasm_bedrock_version( ) -> pumpkin::plugin::player::BedrockMinecraftVersion { match version { BedrockMinecraftVersion::V_1_21 => pumpkin::plugin::player::BedrockMinecraftVersion::V121, - BedrockMinecraftVersion::V_1_26_30 => { + BedrockMinecraftVersion::V_1_26_40 => { pumpkin::plugin::player::BedrockMinecraftVersion::V12630 } BedrockMinecraftVersion::Unknown => {