diff --git a/nmsr-aas/src/model/request/cache.rs b/nmsr-aas/src/model/request/cache.rs index f5d3488..b86c6fc 100644 --- a/nmsr-aas/src/model/request/cache.rs +++ b/nmsr-aas/src/model/request/cache.rs @@ -266,7 +266,8 @@ impl CacheHandler Some(u.to_string()), - RenderRequestEntry::TextureHash(hash) => Some(hash.clone()), + RenderRequestEntry::TextureHash(hash) + | RenderRequestEntry::DefaultSkinTextureHash(hash) => Some(hash.clone()), RenderRequestEntry::MojangPlayerName(_) | RenderRequestEntry::PlayerSkin(_, _) => None, }) } diff --git a/nmsr-aas/src/model/request/entry.rs b/nmsr-aas/src/model/request/entry.rs index d3bfa3c..8e84d6f 100644 --- a/nmsr-aas/src/model/request/entry.rs +++ b/nmsr-aas/src/model/request/entry.rs @@ -17,6 +17,7 @@ pub enum RenderRequestEntry { MojangOfflinePlayerUuid(Uuid), GeyserPlayerUuid(Uuid), TextureHash(String), + DefaultSkinTextureHash(String), PlayerSkin(#[debug(skip)] Vec, #[debug(skip)] Option>), } @@ -27,7 +28,9 @@ impl RenderRequestEntry { pub(crate) fn default_skin_hash(skin: DefaultSkin, is_slim: bool) -> RenderRequestEntry { // TODO: Move to CoW - Self::TextureHash(DefaultSkinResolver::resolve_default_skin(skin, is_slim).to_string()) + Self::DefaultSkinTextureHash( + DefaultSkinResolver::resolve_default_skin(skin, is_slim).to_string(), + ) } } @@ -98,7 +101,8 @@ impl TryFrom for String { RenderRequestEntry::MojangPlayerUuid(uuid) | RenderRequestEntry::MojangOfflinePlayerUuid(uuid) | RenderRequestEntry::GeyserPlayerUuid(uuid) => Ok(uuid.to_string()), - RenderRequestEntry::TextureHash(hash) => Ok(hash), + RenderRequestEntry::TextureHash(hash) + | RenderRequestEntry::DefaultSkinTextureHash(hash) => Ok(hash), RenderRequestEntry::PlayerSkin(_, _) => Err(RenderRequestError::InvalidPlayerRequest( "Unable to convert PlayerSkin to String".to_string(), )), diff --git a/nmsr-aas/src/model/resolver/mod.rs b/nmsr-aas/src/model/resolver/mod.rs index 96f0610..af0b6ec 100644 --- a/nmsr-aas/src/model/resolver/mod.rs +++ b/nmsr-aas/src/model/resolver/mod.rs @@ -319,6 +319,15 @@ impl RenderRequestResolver { cape_texture = None; model = None; } + RenderRequestEntry::DefaultSkinTextureHash(skin_hash) => { + // Handle default skin textures. These have to go straight to Mojang, whether or not the user changed the config. + skin_texture = Some( + self.fetch_texture_from_mojang(skin_hash, None, MojangTextureRequestType::DefaultSkin) + .await?, + ); + cape_texture = None; + model = None; + } RenderRequestEntry::PlayerSkin(skin_bytes, cape_bytes) => { skin_texture = Some(MojangTexture::new_unnamed(skin_bytes.clone())); cape_texture = cape_bytes.to_owned().map(|b| MojangTexture::new_unnamed(b)); @@ -414,9 +423,9 @@ impl RenderRequestResolver { RenderRequestEntry::GeyserPlayerUuid(u) | RenderRequestEntry::MojangOfflinePlayerUuid(u) | RenderRequestEntry::MojangPlayerUuid(u) => Some(*u), - RenderRequestEntry::TextureHash(_) | RenderRequestEntry::PlayerSkin(_, _) => { - None - } + RenderRequestEntry::TextureHash(_) + | RenderRequestEntry::DefaultSkinTextureHash(_) + | RenderRequestEntry::PlayerSkin(_, _) => None, RenderRequestEntry::MojangPlayerName(_) => Some(Uuid::new_v4()), }; @@ -453,7 +462,7 @@ impl RenderRequestResolver { resolved } - pub async fn resolve_raw(&self, request: &RenderRequest) -> Result { + async fn resolve_raw(&self, request: &RenderRequest) -> Result { // First, we need to resolve the skin and cape textures. let resolved_textures = self .resolve_entry_textures(&request.entry) diff --git a/nmsr-aas/src/model/resolver/mojang/client.rs b/nmsr-aas/src/model/resolver/mojang/client.rs index c02ab11..6404bee 100644 --- a/nmsr-aas/src/model/resolver/mojang/client.rs +++ b/nmsr-aas/src/model/resolver/mojang/client.rs @@ -1,6 +1,8 @@ use super::model::GameProfile; use crate::{ - config::MojankConfiguration, + config::{ + MojankConfiguration, DEFAULT_TEXTURES_SERVER, DEFAULT_TEXTURES_SERVER_SKIN_URL_TEMPLATE, + }, error::{MojangRequestError, MojangRequestResult}, model::resolver::mojang::model::UsernameToUuidResponse, utils::http_client::NmsrHttpClient, @@ -24,6 +26,7 @@ pub enum MojangClientKind { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum MojangTextureRequestType { + DefaultSkin, Skin, Cape, } @@ -150,12 +153,24 @@ impl MojangClient { fn build_request_url(&self, req_type: MojangTextureRequestType, texture_id: &str) -> String { let mojank = self.mojank_config(); - let url = match req_type { - MojangTextureRequestType::Skin => &mojank.textures_server_skin_url_template, - MojangTextureRequestType::Cape => &mojank.textures_server_cape_url_template, + let req_type_default_skin = (req_type, mojank.default_skins_use_official_textures_server); + + let url = match req_type_default_skin { + (MojangTextureRequestType::DefaultSkin, true) => { + DEFAULT_TEXTURES_SERVER_SKIN_URL_TEMPLATE + } + (MojangTextureRequestType::Skin, _) | (MojangTextureRequestType::DefaultSkin, _) => { + &mojank.textures_server_skin_url_template + } + (MojangTextureRequestType::Cape, _) => &mojank.textures_server_cape_url_template, }; - url.replace("{textures_server}", &mojank.textures_server) + let target_server = match req_type_default_skin { + (MojangTextureRequestType::DefaultSkin, true) => DEFAULT_TEXTURES_SERVER, + _ => &mojank.textures_server, + }; + + url.replace("{textures_server}", target_server) .replace("{texture_id}", texture_id) } } diff --git a/nmsr-aas/src/utils/config.rs b/nmsr-aas/src/utils/config.rs index 271ccf1..ff0212c 100644 --- a/nmsr-aas/src/utils/config.rs +++ b/nmsr-aas/src/utils/config.rs @@ -106,6 +106,10 @@ pub struct MojankConfiguration { /// By enabling this, the UUIDs will be sent to the Mojang API without dashes. pub use_dashless_uuids: bool, + /// Whether to redirect default skin requests to the official Mojang textures server. + /// Change this value if you want default skins to be fetched from the configured textures server. + pub default_skins_use_official_textures_server: bool, + /// The template to use for resolving player skin textures. pub textures_server_skin_url_template: String, @@ -113,11 +117,14 @@ pub struct MojankConfiguration { pub textures_server_cape_url_template: String, } +pub const DEFAULT_TEXTURES_SERVER_SKIN_URL_TEMPLATE: &str = "{textures_server}/texture/{texture_id}"; +pub const DEFAULT_TEXTURES_SERVER: &str = "https://textures.minecraft.net"; + impl Default for MojankConfiguration { fn default() -> Self { Self { session_server: "https://sessionserver.mojang.com/".to_string(), - textures_server: "https://textures.minecraft.net".to_string(), + textures_server: DEFAULT_TEXTURES_SERVER.to_string(), mojang_api_server: "https://api.mojang.com/".to_string(), geysermc_api_server: "https://api.geysermc.org/".to_string(), @@ -126,11 +133,12 @@ impl Default for MojankConfiguration { session_server_timeout: 5 * 60 /* 5 minutes */, use_default_skins_when_missing: true, + default_skins_use_official_textures_server: true, allow_offline_mode_uuids: false, use_dashless_uuids: false, - textures_server_skin_url_template: "{textures_server}/texture/{texture_id}".to_string(), - textures_server_cape_url_template: "{textures_server}/texture/{texture_id}".to_string(), + textures_server_skin_url_template: DEFAULT_TEXTURES_SERVER_SKIN_URL_TEMPLATE.to_string(), + textures_server_cape_url_template: DEFAULT_TEXTURES_SERVER_SKIN_URL_TEMPLATE.to_string(), } } }