Compare commits

...

2 Commits

Author SHA1 Message Date
min
f2b74a2597 fix(skin): ��������� ����� � ��������� ������� (#32)
All checks were successful
CI / Lint (push) Successful in 52s
CI / Build (push) Successful in 1m28s
CI / Secret scan (push) Successful in 20s
CI / PR size check (push) Has been skipped
CI / Deploy to S1 + S2 (push) Successful in 2m59s
2026-06-15 05:21:27 +00:00
min
3754ecf4a1 fix(skin): валидация скина в карточках игроков (legacy bacon → y-bot)
All checks were successful
CI / Lint (pull_request) Successful in 52s
CI / Build (pull_request) Successful in 1m28s
CI / Secret scan (pull_request) Successful in 20s
CI / PR size check (pull_request) Successful in 7s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
В меню «На сервере» аватарка бралась по player.skin. Если в БД legacy
skin_bacon-hair (которого нет) — показывался бекон. Теперь невалидный
скин (не в MIXAMO_SKINS) → аватар skin_y-bot, как и 3D-модель в игре.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-15 06:46:58 +03:00

View File

@ -1,6 +1,7 @@
import React, { useEffect, useState, useRef, useCallback } from 'react'; import React, { useEffect, useState, useRef, useCallback } from 'react';
import Icon from '../editor-shared/Icon'; import Icon from '../editor-shared/Icon';
import { STORYS_addres, USER_addres } from '../api/API'; import { STORYS_addres, USER_addres } from '../api/API';
import { MIXAMO_SKINS } from '../engine/PlayerController';
const getToken = () => { const getToken = () => {
try { try {
@ -608,19 +609,18 @@ function PlayerCard({ player, isMe, isFriend, isPending, onAddFriend }) {
let avatarUrl = null; let avatarUrl = null;
let isSkin = false; let isSkin = false;
if (player.skin && typeof player.skin === 'string') { if (player.skin && typeof player.skin === 'string') {
const isLegacy = LEGACY_SKINS.has(player.skin); // ВАЛИДАЦИЯ: legacy R15-скины (bacon-hair и пр.) больше не существуют.
if (!isLegacy && player.skin.startsWith('skin_')) { // Если скин НЕ в наборе валидных Mixamo (80 шт) показываем аватар
// Mixamo: PNG на rublox-site (на проде rublox.pro, // дефолтного skin_y-bot (как и в самой игре 3D-модель валидируется).
// локально localhost:3000) рядом с GLB. let skinId = player.skin;
const base = (typeof window !== 'undefined' if (!MIXAMO_SKINS.has(skinId) && !skinId.startsWith('customskin:')) {
&& window.location.hostname === 'localhost') skinId = 'skin_y-bot';
? 'http://localhost:3000'
: 'https://rublox.pro';
avatarUrl = `${base}/character-assets/skins/${player.skin}.png?v=20260614`;
} else {
// Legacy R15: путь по старому шаблону.
avatarUrl = `/kubikon-assets/characters/${player.skin}/avatar.png?v=2026_05_27`;
} }
const base = (typeof window !== 'undefined'
&& window.location.hostname === 'localhost')
? 'http://localhost:3000'
: 'https://rublox.pro';
avatarUrl = `${base}/character-assets/skins/${skinId}.png?v=20260614`;
isSkin = true; isSkin = true;
} else if (player.photo_thumb_b64) { } else if (player.photo_thumb_b64) {
avatarUrl = player.photo_thumb_b64.startsWith('data:') avatarUrl = player.photo_thumb_b64.startsWith('data:')