Skip to content

Commit cf1d948

Browse files
authored
fix: desync on flush (#6223)
1 parent fe8fa4b commit cf1d948

1 file changed

Lines changed: 69 additions & 2 deletions

File tree

packages/app-lib/src/api/minecraft_skins.rs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ pub async fn get_available_skins() -> crate::Result<Vec<Skin>> {
361361
);
362362
let mut found_equipped_skin = false;
363363
let mut available_skins = Vec::new();
364+
let mut custom_skins = Vec::new();
364365
let mut saved_default_skins = Vec::new();
365366

366367
for mut custom_skin in CustomMinecraftSkin::get_all(profile.id, &state.pool)
@@ -426,7 +427,7 @@ pub async fn get_available_skins() -> crate::Result<Vec<Skin>> {
426427
None => custom_skin.texture_blob(&state.pool).await?,
427428
};
428429

429-
available_skins.push(Skin {
430+
custom_skins.push(Skin {
430431
name: None,
431432
section: None,
432433
variant: custom_skin.variant,
@@ -444,6 +445,9 @@ pub async fn get_available_skins() -> crate::Result<Vec<Skin>> {
444445
});
445446
}
446447

448+
custom_skins.sort_by(|a, b| a.texture.as_str().cmp(b.texture.as_str()));
449+
available_skins.extend(custom_skins);
450+
447451
for default_skin in assets::DEFAULT_SKINS.iter() {
448452
let is_equipped = !found_equipped_skin
449453
&& default_skin.texture_key == current_skin_texture_key
@@ -676,9 +680,17 @@ async fn equip_skin_now(
676680

677681
preserve_current_profile_skin(&state, &profile).await?;
678682

683+
let texture_blob = png_util::url_to_data_stream(&skin.texture)
684+
.await?
685+
.try_fold(Vec::new(), |mut texture, chunk| async move {
686+
texture.extend_from_slice(&chunk);
687+
Ok(texture)
688+
})
689+
.await?;
690+
679691
let profile = mojang_api::MinecraftSkinOperation::equip(
680692
selected_credentials,
681-
png_util::url_to_data_stream(&skin.texture).await?,
693+
stream::iter([Ok::<_, String>(Bytes::from(texture_blob.clone()))]),
682694
skin.variant,
683695
)
684696
.await?;
@@ -693,6 +705,13 @@ async fn equip_skin_now(
693705
})?,
694706
};
695707

708+
if let Err(error) =
709+
persist_equipped_skin(&state, &profile, skin, &texture_blob).await
710+
{
711+
refresh_profile_cache(selected_credentials).await;
712+
return Err(error);
713+
}
714+
696715
if let Err(error) =
697716
sync_cape(selected_credentials, &profile, skin.cape_id).await
698717
{
@@ -703,6 +722,54 @@ async fn equip_skin_now(
703722
Ok(())
704723
}
705724

725+
async fn persist_equipped_skin(
726+
state: &State,
727+
profile: &MinecraftProfile,
728+
skin: &Skin,
729+
texture_blob: &[u8],
730+
) -> crate::Result<()> {
731+
let equipped_skin = profile.current_skin()?;
732+
let equipped_skin_texture_key = equipped_skin.texture_key();
733+
let equipped_skin_variant = equipped_skin.variant;
734+
let texture_key_changed =
735+
skin.texture_key.as_ref() != equipped_skin_texture_key.as_ref();
736+
737+
if skin.cape_id.is_none()
738+
&& is_bundled_skin(&equipped_skin_texture_key, equipped_skin_variant)
739+
{
740+
CustomMinecraftSkin {
741+
texture_key: equipped_skin_texture_key.to_string(),
742+
variant: equipped_skin_variant,
743+
cape_id: None,
744+
}
745+
.remove(profile.id, &state.pool)
746+
.await?;
747+
} else if texture_key_changed || !matches!(&skin.source, SkinSource::Custom)
748+
{
749+
CustomMinecraftSkin::add(
750+
profile.id,
751+
&equipped_skin_texture_key,
752+
texture_blob,
753+
equipped_skin_variant,
754+
skin.cape_id,
755+
&state.pool,
756+
)
757+
.await?;
758+
}
759+
760+
if texture_key_changed {
761+
CustomMinecraftSkin {
762+
texture_key: skin.texture_key.to_string(),
763+
variant: skin.variant,
764+
cape_id: skin.cape_id,
765+
}
766+
.remove(profile.id, &state.pool)
767+
.await?;
768+
}
769+
770+
Ok(())
771+
}
772+
706773
/// Removes a custom skin from the app database.
707774
///
708775
/// The player will continue to be equipped with the same skin and cape as before, even if

0 commit comments

Comments
 (0)