Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: encode Uuid correctly (fixes #454) #583

Merged
merged 5 commits into from
Feb 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions pumpkin-config/src/resource_pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,32 @@ use serde::{Deserialize, Serialize};
pub struct ResourcePackConfig {
pub enabled: bool,
/// The path to the resource pack.
pub url: String,
pub resource_pack_url: String,
/// The SHA1 hash (40) of the resource pack.
pub sha1: String,
pub resource_pack_sha1: String,
/// Custom prompt Text component, Leave blank for none
pub message: String,
pub prompt_message: String,
Comment on lines +8 to +12
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this, The Category is already named Resource so this is just duplicate naming

/// Will force the Player to accept the resource pack
pub force: bool,
}

impl ResourcePackConfig {
pub fn validate(&self) {
if !self.enabled {
return;
}

assert_eq!(
!self.url.is_empty(),
!self.sha1.is_empty(),
!self.resource_pack_url.is_empty(),
!self.resource_pack_sha1.is_empty(),
"Resource Pack path or Sha1 hash is missing"
);

let hash_len = self.resource_pack_sha1.len();
assert!(
self.sha1.len() <= 40,
"Resource pack sha1 hash is too long (max. 40)"
hash_len == 40,
"Resource pack sha1 hash is the wrong length (should be 40, is {})",
hash_len
)
}
}
3 changes: 3 additions & 0 deletions pumpkin-protocol/src/bytebuf/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ impl<B: BufMut> ser::Serializer for &mut Serializer<B> {
self.output.put_var_int(&variant_index.into());
Ok(())
}
fn is_human_readable(&self) -> bool {
false
}
}

impl<B: BufMut> ser::SerializeSeq for &mut Serializer<B> {
Expand Down
5 changes: 3 additions & 2 deletions pumpkin-protocol/src/client/config/add_resource_pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use pumpkin_data::packet::clientbound::CONFIG_RESOURCE_PACK_PUSH;
#[derive(Serialize)]
#[packet(CONFIG_RESOURCE_PACK_PUSH)]
pub struct CConfigAddResourcePack<'a> {
uuid: uuid::Uuid,
#[serde(with = "uuid::serde::compact")]
uuid: &'a uuid::Uuid,
url: &'a str,
hash: &'a str, // max 40
forced: bool,
Expand All @@ -17,7 +18,7 @@ pub struct CConfigAddResourcePack<'a> {

impl<'a> CConfigAddResourcePack<'a> {
pub fn new(
uuid: uuid::Uuid,
uuid: &'a uuid::Uuid,
url: &'a str,
hash: &'a str,
forced: bool,
Expand Down
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/server/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ mod client_information;
mod cookie_response;
mod known_packs;
mod plugin_message;
mod resource_pack_response;

pub use acknowledge_finish_config::*;
pub use client_information::*;
pub use cookie_response::*;
pub use known_packs::*;
pub use plugin_message::*;
pub use resource_pack_response::*;
41 changes: 41 additions & 0 deletions pumpkin-protocol/src/server/config/resource_pack_response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use pumpkin_data::packet::serverbound::CONFIG_RESOURCE_PACK;
use pumpkin_macros::packet;
use serde::Serialize;

use crate::VarInt;

pub enum ResourcePackResponseResult {
DownloadSuccess,
DownloadFail,
Downloaded,
Accepted,
Declined,
InvalidUrl,
ReloadFailed,
Discarded,
Unknown(i32),
}

#[derive(serde::Deserialize, Serialize)]
#[packet(CONFIG_RESOURCE_PACK)]
pub struct SConfigResourcePack {
#[serde(with = "uuid::serde::compact")]
pub uuid: uuid::Uuid,
result: VarInt,
}

impl SConfigResourcePack {
pub fn response_result(&self) -> ResourcePackResponseResult {
match self.result.0 {
0 => ResourcePackResponseResult::DownloadSuccess,
1 => ResourcePackResponseResult::Declined,
2 => ResourcePackResponseResult::DownloadFail,
3 => ResourcePackResponseResult::Accepted,
4 => ResourcePackResponseResult::Downloaded,
5 => ResourcePackResponseResult::InvalidUrl,
6 => ResourcePackResponseResult::ReloadFailed,
7 => ResourcePackResponseResult::Discarded,
x => ResourcePackResponseResult::Unknown(x),
}
}
}
8 changes: 6 additions & 2 deletions pumpkin/src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use pumpkin_protocol::{
packet_encoder::{PacketEncodeError, PacketEncoder},
server::{
config::{
SAcknowledgeFinishConfig, SClientInformationConfig, SConfigCookieResponse, SKnownPacks,
SPluginMessage,
SAcknowledgeFinishConfig, SClientInformationConfig, SConfigCookieResponse,
SConfigResourcePack, SKnownPacks, SPluginMessage,
},
handshake::SHandShake,
login::{
Expand Down Expand Up @@ -515,6 +515,10 @@ impl Client {
SConfigCookieResponse::PACKET_ID => {
self.handle_config_cookie_response(SConfigCookieResponse::read(bytebuf)?);
}
SConfigResourcePack::PACKET_ID => {
self.handle_resource_pack_response(SConfigResourcePack::read(bytebuf)?)
.await;
}
_ => {
log::error!(
"Failed to handle client packet id {} in Config State",
Expand Down
73 changes: 72 additions & 1 deletion pumpkin/src/net/packet/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ use crate::{
server::Server,
};
use core::str;
use pumpkin_config::ADVANCED_CONFIG;
use pumpkin_protocol::{
ConnectionState,
client::config::{CFinishConfig, CRegistryData},
codec::var_int::VarInt,
server::config::{
SClientInformationConfig, SConfigCookieResponse, SKnownPacks, SPluginMessage,
ResourcePackResponseResult, SClientInformationConfig, SConfigCookieResponse,
SConfigResourcePack, SKnownPacks, SPluginMessage,
},
};
use pumpkin_util::text::TextComponent;
Expand Down Expand Up @@ -67,6 +69,75 @@ impl Client {
}
}

pub async fn handle_resource_pack_response(&self, packet: SConfigResourcePack) {
let resource_config = &ADVANCED_CONFIG.resource_pack;
if resource_config.enabled {
let expected_uuid = uuid::Uuid::new_v3(
&uuid::Uuid::NAMESPACE_DNS,
resource_config.resource_pack_url.as_bytes(),
);

if packet.uuid == expected_uuid {
match packet.response_result() {
ResourcePackResponseResult::DownloadSuccess => {
log::trace!(
"Client {} successfully downloaded the resource pack",
self.id
);
}
ResourcePackResponseResult::DownloadFail => {
log::warn!(
"Client {} failed to downloaded the resource pack. Is it available on the internet?",
self.id
);
}
ResourcePackResponseResult::Downloaded => {
log::trace!("Client {} already has the resource pack", self.id);
}
ResourcePackResponseResult::Accepted => {
log::trace!("Client {} accepted the resource pack", self.id);

// Return here to wait for the next response update
return;
}
ResourcePackResponseResult::Declined => {
log::trace!("Client {} declined the resource pack", self.id);
}
ResourcePackResponseResult::InvalidUrl => {
log::warn!(
"Client {} reported that the resource pack url is invalid!",
self.id
);
}
ResourcePackResponseResult::ReloadFailed => {
log::trace!("Client {} failed to reload the resource pack", self.id);
}
ResourcePackResponseResult::Discarded => {
log::trace!("Client {} discarded the resource pack", self.id);
}
ResourcePackResponseResult::Unknown(result) => {
log::warn!(
"Client {} responded with a bad result: {}!",
self.id,
result
);
}
}
} else {
log::warn!(
"Client {} returned a response for a resource pack we did not set!",
self.id
);
}
} else {
log::warn!(
"Client {} returned a response for a resource pack that was not enabled!",
self.id
);
}
self.send_known_packs().await;
}

pub fn handle_config_cookie_response(&self, packet: SConfigCookieResponse) {
// TODO: allow plugins to access this
log::debug!(
Expand Down
45 changes: 27 additions & 18 deletions pumpkin/src/net/packet/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,23 +340,6 @@ impl Client {
self.connection_state.store(ConnectionState::Config);
self.send_packet(&server.get_branding()).await;

let resource_config = &ADVANCED_CONFIG.resource_pack;
if resource_config.enabled {
let resource_pack = CConfigAddResourcePack::new(
Uuid::new_v3(&uuid::Uuid::NAMESPACE_DNS, resource_config.url.as_bytes()),
&resource_config.url,
&resource_config.sha1,
resource_config.force,
if resource_config.message.is_empty() {
None
} else {
Some(TextComponent::text(&resource_config.message))
},
);

self.send_packet(&resource_pack).await;
}

if ADVANCED_CONFIG.server_links.enabled {
self.send_packet(&CConfigServerLinks::new(
&VarInt(LINKS.len() as i32),
Expand All @@ -373,13 +356,39 @@ impl Client {
]))
.await;

let resource_config = &ADVANCED_CONFIG.resource_pack;
if resource_config.enabled {
let uuid = Uuid::new_v3(
&uuid::Uuid::NAMESPACE_DNS,
resource_config.resource_pack_url.as_bytes(),
);
let resource_pack = CConfigAddResourcePack::new(
&uuid,
&resource_config.resource_pack_url,
&resource_config.resource_pack_sha1,
resource_config.force,
if resource_config.prompt_message.is_empty() {
None
} else {
Some(TextComponent::text(&resource_config.prompt_message))
},
);

self.send_packet(&resource_pack).await;
} else {
// This will be invoked by our resource pack handler in the case of the above branch
self.send_known_packs().await;
}
log::debug!("login acknowledged");
}

pub async fn send_known_packs(&self) {
// known data packs
self.send_packet(&CKnownPacks::new(&[KnownPack {
namespace: "minecraft",
id: "core",
version: "1.21",
}]))
.await;
log::debug!("login acknowledged");
}
}