Compare commits

...

2 Commits

Author SHA1 Message Date
min
4913da49ff Merge pull request 'fix(skin): ��������� ����� � Play-������ ��������� (bacon > y-bot)' (#44) from fix/studio-skin-validation-2026-06-15 into main
All checks were successful
CI / Lint (push) Successful in 1m13s
CI / Build (push) Successful in 2m1s
CI / Secret scan (push) Successful in 24s
CI / PR size check (push) Has been skipped
CI / Deploy to S1 + S2 (push) Successful in 3m28s
2026-06-15 08:52:07 +00:00
min
e6cfcad2c0 fix(skin): валидация скина в Play-режиме редактора (legacy bacon → y-bot)
All checks were successful
CI / Lint (pull_request) Successful in 1m4s
CI / Build (pull_request) Successful in 1m57s
CI / Secret scan (pull_request) Successful in 23s
CI / PR size check (pull_request) Successful in 8s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
KubikonEditor подмешивал skin_folder из БД в hash без проверки.
Для ~22 legacy-юзеров БД отдаёт skin_bacon-hair (модель удалена) →
в Play-режиме студии играл бекон. Теперь невалидный скин (не в
MIXAMO_SKINS и не customskin:) подменяется на skin_y-bot, как в
плеере (KubikonPlayer/GameMenu) и кабинете. Дефолты bacon → y-bot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 11:47:10 +03:00
2 changed files with 15 additions and 5 deletions

View File

@ -4,6 +4,7 @@ import { jwtDecode } from 'jwt-decode';
import { useAuth, redirectToLogin } from '../auth/AuthContext.jsx';
import { useSanctions } from '../auth/SanctionsContext.jsx';
import { BabylonScene } from './engine/BabylonScene';
import { MIXAMO_SKINS } from './engine/PlayerController';
import { StudioCollab } from './engine/StudioCollab';
import { CollabOverlay } from './engine/CollabOverlay';
import { BLOCK_TYPES, BLOCK_CATEGORIES, blockPreview, registerCustomBlockType } from './engine/BlockTypes';
@ -938,7 +939,7 @@ const KubikonEditor = () => {
// === Game settings inline в TopRibbon (вкладка Тест) ===
// Дефолт R15-скин bacon-hair (классический Roblox-вид).
const [playerModelType, setPlayerModelTypeUI] = useState('skin_bacon-hair');
const [playerModelType, setPlayerModelTypeUI] = useState('skin_y-bot');
const [envPreset, setEnvPresetUI] = useState('day');
const [dayDurationMin, setDayDurationMinUI] = useState(5);
const [nightDurationMin, setNightDurationMinUI] = useState(3);
@ -964,7 +965,7 @@ const KubikonEditor = () => {
genre: 'other',
thumbnail: '',
is_public: false,
player_model_type: 'skin_bacon-hair',
player_model_type: 'skin_y-bot',
});
const projectNameRef = useRef(projectName);
useEffect(() => { projectNameRef.current = projectName; metaRef.current.title = projectName; }, [projectName]);
@ -1782,7 +1783,7 @@ const KubikonEditor = () => {
sceneRef.current.history?.initialize();
// Синхронизируем UI-state TopRibbon из загруженной сцены
try {
setPlayerModelTypeUI(sceneRef.current.getPlayerModelType?.() || 'skin_bacon-hair');
setPlayerModelTypeUI(sceneRef.current.getPlayerModelType?.() || 'skin_y-bot');
const env = sceneRef.current.getEnvironmentState?.();
if (env?.preset) setEnvPresetUI(env.preset);
if (env?.dayDurationMin) setDayDurationMinUI(env.dayDurationMin);
@ -2093,7 +2094,16 @@ const KubikonEditor = () => {
const uid = getCurrentUserId();
if (uid) {
const r = await Kubikon3DApi.getEquippedSkin(uid);
const sf = r?.data?.skin_folder;
let sf = r?.data?.skin_folder;
// ВАЛИДАЦИЯ: legacy R15-скины (bacon-hair и пр.) больше
// не существуют. Если БД отдала невалидный подменяем
// на skin_y-bot (как в плеере и кабинете).
if (sf && typeof sf === 'string'
&& !MIXAMO_SKINS.has(sf)
&& !sf.startsWith('customskin:')) {
console.log('[KubikonEditor] skin', sf, 'не валиден → skin_y-bot');
sf = 'skin_y-bot';
}
if (sf && typeof sf === 'string') {
// Подмешиваем в hash так чтобы не сломать ticket=...
const cur = window.location.hash || '';

View File

@ -32,7 +32,7 @@ import { MixamoAnimator, loadMixamoAnimations } from './MixamoAnimator';
// Список всех Mixamo-скинов. Должен совпадать со списком в плеере и
// каталоге сайта (rublox-site/src/data/skinsCatalog.js).
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',