From a0f23a2bcaf96127fdbd64371479d373fe2e126a Mon Sep 17 00:00:00 2001 From: Jerozgen Date: Sun, 26 Oct 2025 16:53:56 +0300 Subject: [PATCH] Fix normalized skins uploading to Mojang (#4646) * Fix normalized skins uploading to Mojang * Run app-frontend > fix --- .../src/components/ui/skin/EditSkinModal.vue | 13 +++++----- apps/app-frontend/src/helpers/skins.ts | 5 ++++ apps/app-frontend/src/pages/Skins.vue | 24 ++++++++++--------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue index 1ac359d7..56d418ce 100644 --- a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue +++ b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue @@ -130,6 +130,7 @@ import { remove_custom_skin, type Skin, type SkinModel, + type SkinTextureUrl, unequip_skin, } from '@/helpers/skins.ts' @@ -142,7 +143,7 @@ const currentSkin = ref(null) const shouldRestoreModal = ref(false) const isSaving = ref(false) -const uploadedTextureUrl = ref(null) +const uploadedTextureUrl = ref(null) const previewSkin = ref('') const variant = ref('CLASSIC') @@ -188,7 +189,7 @@ function getSortedCapeExcluding(excludeId: string): Cape | undefined { async function loadPreviewSkin() { if (uploadedTextureUrl.value) { - previewSkin.value = uploadedTextureUrl.value + previewSkin.value = uploadedTextureUrl.value.normalized } else if (currentSkin.value) { try { previewSkin.value = await get_normalized_skin_texture(currentSkin.value) @@ -253,11 +254,11 @@ async function show(e: MouseEvent, skin?: Skin) { modal.value?.show(e) } -async function showNew(e: MouseEvent, skinTextureUrl: string) { +async function showNew(e: MouseEvent, skinTextureUrl: SkinTextureUrl) { mode.value = 'new' currentSkin.value = null uploadedTextureUrl.value = skinTextureUrl - variant.value = await determineModelType(skinTextureUrl) + variant.value = await determineModelType(skinTextureUrl.original) selectedCape.value = undefined visibleCapeList.value = [] initVisibleCapeList() @@ -267,7 +268,7 @@ async function showNew(e: MouseEvent, skinTextureUrl: string) { modal.value?.show(e) } -async function restoreWithNewTexture(skinTextureUrl: string) { +async function restoreWithNewTexture(skinTextureUrl: SkinTextureUrl) { uploadedTextureUrl.value = skinTextureUrl await loadPreviewSkin() @@ -361,7 +362,7 @@ async function save() { let textureUrl: string if (uploadedTextureUrl.value) { - textureUrl = uploadedTextureUrl.value + textureUrl = uploadedTextureUrl.value.original } else { textureUrl = currentSkin.value!.texture } diff --git a/apps/app-frontend/src/helpers/skins.ts b/apps/app-frontend/src/helpers/skins.ts index 75dea749..87f7286c 100644 --- a/apps/app-frontend/src/helpers/skins.ts +++ b/apps/app-frontend/src/helpers/skins.ts @@ -22,6 +22,11 @@ export interface Skin { is_equipped: boolean } +export interface SkinTextureUrl { + original: string + normalized: string +} + export const DEFAULT_MODEL_SORTING = ['Steve', 'Alex'] as string[] export const DEFAULT_MODELS: Record = { diff --git a/apps/app-frontend/src/pages/Skins.vue b/apps/app-frontend/src/pages/Skins.vue index cab38f2f..d2bca13f 100644 --- a/apps/app-frontend/src/pages/Skins.vue +++ b/apps/app-frontend/src/pages/Skins.vue @@ -31,7 +31,7 @@ import { get_default_user, login as login_flow, users } from '@/helpers/auth' import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts' import { generateSkinPreviews, skinBlobUrlMap } from '@/helpers/rendering/batch-skin-renderer.ts' import { get as getSettings } from '@/helpers/settings.ts' -import type { Cape, Skin } from '@/helpers/skins.ts' +import type { Cape, Skin, SkinTextureUrl } from '@/helpers/skins.ts' import { equip_skin, filterDefaultSkins, @@ -245,16 +245,18 @@ function openUploadSkinModal(e: MouseEvent) { function onSkinFileUploaded(buffer: ArrayBuffer) { const fakeEvent = new MouseEvent('click') - normalize_skin_texture(`data:image/png;base64,` + arrayBufferToBase64(buffer)).then( - (skinTextureNormalized: Uint8Array) => { - const skinTexUrl = `data:image/png;base64,` + arrayBufferToBase64(skinTextureNormalized) - if (editSkinModal.value && editSkinModal.value.shouldRestoreModal) { - editSkinModal.value.restoreWithNewTexture(skinTexUrl) - } else { - editSkinModal.value?.showNew(fakeEvent, skinTexUrl) - } - }, - ) + const originalSkinTexUrl = `data:image/png;base64,` + arrayBufferToBase64(buffer) + normalize_skin_texture(originalSkinTexUrl).then((skinTextureNormalized: Uint8Array) => { + const skinTexUrl: SkinTextureUrl = { + original: originalSkinTexUrl, + normalized: `data:image/png;base64,` + arrayBufferToBase64(skinTextureNormalized), + } + if (editSkinModal.value && editSkinModal.value.shouldRestoreModal) { + editSkinModal.value.restoreWithNewTexture(skinTexUrl) + } else { + editSkinModal.value?.showNew(fakeEvent, skinTexUrl) + } + }) } function onUploadCanceled() {