diff --git a/src/KubikonPlayer/KubikonPlayer.jsx b/src/KubikonPlayer/KubikonPlayer.jsx index 77c6647..c49fd70 100644 --- a/src/KubikonPlayer/KubikonPlayer.jsx +++ b/src/KubikonPlayer/KubikonPlayer.jsx @@ -4,6 +4,7 @@ import { jwtDecode } from 'jwt-decode'; import { Client } from 'colyseus.js'; import * as Kubikon3DApi from '../api/Kubikon3DService'; import { BabylonScene } from '../engine/BabylonScene'; +import { MIXAMO_SKINS } from '../engine/PlayerController'; import { attachConsoleHook, devlogReset } from '../engine/devlog'; import { MultiplayerSync } from '../engine/MultiplayerSync'; import { REALTIME_WS } from '../api/API'; @@ -669,6 +670,16 @@ const KubikonPlayer = () => { } } catch (e) {} } + // ВАЛИДАЦИЯ: если скин не из валидного набора Mixamo-скинов + // (legacy bacon-hair/sigma-labubu/cop и пр. — их больше нет, + // или бэкенд вернул дефолтный bacon) — fallback на skin_y-bot. + // Это защита: персонаж не должен пытаться загрузить несуществующий + // скин. См. БД rublox_equipped_skin (22+ юзеров с bacon-hair). + if (mySkin && !MIXAMO_SKINS.has(mySkin) + && !mySkin.startsWith('customskin:')) { + console.log('[KubikonPlayer] skin', mySkin, 'не валиден → skin_y-bot'); + mySkin = 'skin_y-bot'; + } skinFolderRef.current = mySkin; try { scene.setPlayerModelType?.(mySkin); } catch (e) {} diff --git a/src/engine/PlayerController.js b/src/engine/PlayerController.js index 9b11d78..038a565 100644 --- a/src/engine/PlayerController.js +++ b/src/engine/PlayerController.js @@ -38,7 +38,7 @@ import { AccessoryManager } from './AccessoryManager'; * 2026-06-11: эти 80 ID перенесены сюда из data/skinsCatalog.js фронта * чтобы плеер их распознавал и грузил по правильному пути. * Дефолтные: skin_x-bot (male), skin_y-bot (female/null). */ -const MIXAMO_SKINS = new Set([ +export const MIXAMO_SKINS = new Set([ 'skin_aj', 'skin_akai', 'skin_arissa', 'skin_big-vegas', 'skin_castle-guard-1', 'skin_castle-guard-2', 'skin_ch01', 'skin_ch02', 'skin_ch03', 'skin_ch04', 'skin_ch07', 'skin_ch08',