player/src/engine/DecoModels.js
МИН 87444ee2c8 Initial public release: Rublox Player v1.0
Open-source web player for Rublox games, dual-licensed under
AGPL-3.0 + Commercial.

Highlights:
- Babylon.js 7 + React 18 + Vite 5 stack
- Self-contained engine (~46k lines): BlockManager, ModelManager,
  PlayerController, ScriptSandboxWorker, MultiplayerSync, 30+ GD
  gamemodes
- Configurable backend via VITE_API_BASE and friends — works against
  staging (dev-api.rublox.pro) out of the box
- Standalone mode (VITE_STANDALONE=true) loads a bundled sample game
  for first-run without any backend
- Full docs: README, ARCHITECTURE, CONTRIBUTING, SECURITY, CHANGELOG
- Lint + format scaffolding (ESLint + Prettier + EditorConfig)
- Legal: LICENSE (AGPL-3.0), LICENSE-COMMERCIAL.md, CLA.md, COPYRIGHT.md
- Issue templates: bug_report, feature_request, security_disclosure

Removed before public release:
- frontend_deploy.py (contained production SSH credentials)
- ~27 admin endpoints (kept in private repo)
- Hard-coded internal URLs and IPs
- All previous git history (clean repo init)
2026-05-27 23:04:04 +03:00

387 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* DecoModels — воксельные модели декораций (цветы, грибы, кустики травы).
*
* Каждая модель — массив мини-вокселей размером DECO_VOXEL_SIZE метров.
* Координаты voxel'ов в локальной системе модели (0..N в каждом измерении).
*
* Цвет хранится как [r, g, b] в 0..1 (Babylon.Color3).
*
* Применение: DecoManager берёт модель + позицию в мире + поворот, добавляет
* voxel'и как thin-instances одной геометрии (один куб 0.05м).
*/
/** Размер одного deco-voxel'а в мире (метров). */
export const DECO_VOXEL_SIZE = 0.05;
// ============================================================================
// Палитра цветов для декораций
// Каждый цвет — Color3-совместимый массив [r, g, b] в [0..1].
// ============================================================================
export const DECO_PALETTE = {
// Стебли и листва
stemGreen: [0.20, 0.50, 0.15],
stemLight: [0.40, 0.65, 0.20],
leafDark: [0.15, 0.40, 0.12],
leafGrass: [0.35, 0.70, 0.25],
// Палитра травы — 4 оттенка зелёного для разнообразия
grass1: [0.32, 0.62, 0.20], // основной
grass2: [0.22, 0.52, 0.15], // тёмный
grass3: [0.45, 0.72, 0.25], // светлый
grass4: [0.38, 0.65, 0.18], // желтоватый
grassYellow: [0.55, 0.65, 0.20], // сухой
grassRed: [0.40, 0.45, 0.15], // увядший
// Цветы — лепестки
petalRed: [0.85, 0.20, 0.20],
petalPink: [1.00, 0.55, 0.70],
petalYellow: [1.00, 0.85, 0.20],
petalWhite: [0.95, 0.95, 0.90],
petalBlue: [0.30, 0.50, 0.85],
petalPurple: [0.65, 0.30, 0.80],
petalOrange: [1.00, 0.55, 0.15],
// Центры цветов (тычинки)
centerYellow: [0.95, 0.75, 0.10],
centerOrange: [0.90, 0.55, 0.10],
centerBlack: [0.15, 0.10, 0.05],
// Грибы
capRed: [0.80, 0.15, 0.15],
capWhite: [0.95, 0.95, 0.90],
capBrown: [0.55, 0.35, 0.20],
capDots: [0.95, 0.95, 0.90],
mushroomStem: [0.92, 0.88, 0.75],
};
// ============================================================================
// Воксельные модели декораций
//
// Формат: voxels[] = [{ x, y, z, c }]
// - x, y, z — целые координаты в локальной системе модели (0..)
// - c — ключ из DECO_PALETTE
// - y = 0 — основание (касается земли)
//
// При размере 0.05м, модель 10 voxel = 0.5м реального мира.
// ============================================================================
/**
* Ромашка — стебель 5 voxel + шапка 3×3 белых лепестка с жёлтым центром.
* Высота ~10 voxel = 50см.
*/
export const FLOWER_DAISY = {
name: 'daisy',
voxels: [
// Стебель — 5 voxel вверх по центру (x=2, z=2 в 5x5 модели)
{ x: 2, y: 0, z: 2, c: 'stemGreen' },
{ x: 2, y: 1, z: 2, c: 'stemGreen' },
{ x: 2, y: 2, z: 2, c: 'stemGreen' },
{ x: 2, y: 3, z: 2, c: 'stemGreen' },
{ x: 2, y: 4, z: 2, c: 'stemLight' },
// Лист сбоку на высоте 2
{ x: 3, y: 2, z: 2, c: 'leafGrass' },
// Шапка на Y=5: лепестки 3×3 крест
{ x: 1, y: 5, z: 2, c: 'petalWhite' },
{ x: 3, y: 5, z: 2, c: 'petalWhite' },
{ x: 2, y: 5, z: 1, c: 'petalWhite' },
{ x: 2, y: 5, z: 3, c: 'petalWhite' },
// Центр — жёлтый
{ x: 2, y: 5, z: 2, c: 'centerYellow' },
// Верхушка
{ x: 2, y: 6, z: 2, c: 'centerYellow' },
],
};
/**
* Василёк — синий объёмный цветок-шар.
* Лепестки расходятся в стороны и вверх — как настоящий бутон.
*/
export const FLOWER_CORNFLOWER = {
name: 'cornflower',
voxels: [
// Стебель 5 voxel
{ x: 2, y: 0, z: 2, c: 'stemGreen' },
{ x: 2, y: 1, z: 2, c: 'stemGreen' },
{ x: 2, y: 2, z: 2, c: 'stemGreen' },
{ x: 2, y: 3, z: 2, c: 'stemGreen' },
// Лист сбоку
{ x: 3, y: 2, z: 2, c: 'leafGrass' },
// Объёмный бутон на Y=4..6
// Нижний слой (Y=4) — 4 «нижних» лепестка крестом
{ x: 1, y: 4, z: 2, c: 'petalBlue' },
{ x: 3, y: 4, z: 2, c: 'petalBlue' },
{ x: 2, y: 4, z: 1, c: 'petalBlue' },
{ x: 2, y: 4, z: 3, c: 'petalBlue' },
// Средний слой (Y=5) — заполненный 3×3 квадрат
{ x: 1, y: 5, z: 1, c: 'petalBlue' },
{ x: 2, y: 5, z: 1, c: 'petalBlue' },
{ x: 3, y: 5, z: 1, c: 'petalBlue' },
{ x: 1, y: 5, z: 2, c: 'petalBlue' },
{ x: 2, y: 5, z: 2, c: 'centerYellow' }, // центр (тычинки)
{ x: 3, y: 5, z: 2, c: 'petalBlue' },
{ x: 1, y: 5, z: 3, c: 'petalBlue' },
{ x: 2, y: 5, z: 3, c: 'petalBlue' },
{ x: 3, y: 5, z: 3, c: 'petalBlue' },
// Верхний слой (Y=6) — пирамидка крестом
{ x: 2, y: 6, z: 1, c: 'petalBlue' },
{ x: 1, y: 6, z: 2, c: 'petalBlue' },
{ x: 2, y: 6, z: 2, c: 'petalBlue' },
{ x: 3, y: 6, z: 2, c: 'petalBlue' },
{ x: 2, y: 6, z: 3, c: 'petalBlue' },
],
};
/**
* Красный мак — крупные красные лепестки.
*/
export const FLOWER_POPPY = {
name: 'poppy',
voxels: [
{ x: 2, y: 0, z: 2, c: 'stemGreen' },
{ x: 2, y: 1, z: 2, c: 'stemGreen' },
{ x: 2, y: 2, z: 2, c: 'stemGreen' },
{ x: 2, y: 3, z: 2, c: 'stemGreen' },
// Большой бутон 3×3
{ x: 1, y: 4, z: 1, c: 'petalRed' },
{ x: 2, y: 4, z: 1, c: 'petalRed' },
{ x: 3, y: 4, z: 1, c: 'petalRed' },
{ x: 1, y: 4, z: 2, c: 'petalRed' },
{ x: 2, y: 4, z: 2, c: 'centerBlack' },
{ x: 3, y: 4, z: 2, c: 'petalRed' },
{ x: 1, y: 4, z: 3, c: 'petalRed' },
{ x: 2, y: 4, z: 3, c: 'petalRed' },
{ x: 3, y: 4, z: 3, c: 'petalRed' },
],
};
/**
* Жёлтый одуванчик — объёмный пушистый шар (как реальный цветок).
*/
export const FLOWER_DANDELION = {
name: 'dandelion',
voxels: [
// Стебель
{ x: 2, y: 0, z: 2, c: 'stemGreen' },
{ x: 2, y: 1, z: 2, c: 'stemGreen' },
{ x: 2, y: 2, z: 2, c: 'stemGreen' },
{ x: 2, y: 3, z: 2, c: 'stemGreen' },
// Лист
{ x: 1, y: 1, z: 2, c: 'leafGrass' },
// Объёмный пушистый бутон на Y=4..6
// Нижний слой Y=4 — нижние лепестки крест
{ x: 1, y: 4, z: 2, c: 'petalYellow' },
{ x: 3, y: 4, z: 2, c: 'petalYellow' },
{ x: 2, y: 4, z: 1, c: 'petalYellow' },
{ x: 2, y: 4, z: 3, c: 'petalYellow' },
// Средний слой Y=5 — 3×3 квадрат
{ x: 1, y: 5, z: 1, c: 'petalYellow' },
{ x: 2, y: 5, z: 1, c: 'petalYellow' },
{ x: 3, y: 5, z: 1, c: 'petalYellow' },
{ x: 1, y: 5, z: 2, c: 'petalYellow' },
{ x: 2, y: 5, z: 2, c: 'centerOrange' },
{ x: 3, y: 5, z: 2, c: 'petalYellow' },
{ x: 1, y: 5, z: 3, c: 'petalYellow' },
{ x: 2, y: 5, z: 3, c: 'petalYellow' },
{ x: 3, y: 5, z: 3, c: 'petalYellow' },
// Верхний слой Y=6 — пирамидка
{ x: 2, y: 6, z: 1, c: 'petalYellow' },
{ x: 1, y: 6, z: 2, c: 'petalYellow' },
{ x: 2, y: 6, z: 2, c: 'petalYellow' },
{ x: 3, y: 6, z: 2, c: 'petalYellow' },
{ x: 2, y: 6, z: 3, c: 'petalYellow' },
// Верхушка
{ x: 2, y: 7, z: 2, c: 'petalYellow' },
],
};
/**
* Мухомор — красная шляпка с белыми точками + белая ножка.
*/
export const MUSHROOM_FLY = {
name: 'fly_mushroom',
voxels: [
// Белая ножка 3 voxel
{ x: 2, y: 0, z: 2, c: 'mushroomStem' },
{ x: 2, y: 1, z: 2, c: 'mushroomStem' },
{ x: 2, y: 2, z: 2, c: 'mushroomStem' },
// Красная шляпка 3×3
{ x: 1, y: 3, z: 1, c: 'capRed' },
{ x: 2, y: 3, z: 1, c: 'capDots' }, // белая точка
{ x: 3, y: 3, z: 1, c: 'capRed' },
{ x: 1, y: 3, z: 2, c: 'capDots' }, // белая точка
{ x: 2, y: 3, z: 2, c: 'capRed' },
{ x: 3, y: 3, z: 2, c: 'capDots' }, // белая точка
{ x: 1, y: 3, z: 3, c: 'capRed' },
{ x: 2, y: 3, z: 3, c: 'capRed' },
{ x: 3, y: 3, z: 3, c: 'capDots' }, // белая точка
// Верхушка шляпки
{ x: 2, y: 4, z: 2, c: 'capRed' },
],
};
/**
* Коричневый гриб — простая шляпка.
*/
export const MUSHROOM_BROWN = {
name: 'brown_mushroom',
voxels: [
{ x: 2, y: 0, z: 2, c: 'mushroomStem' },
{ x: 2, y: 1, z: 2, c: 'mushroomStem' },
// Шляпка
{ x: 1, y: 2, z: 1, c: 'capBrown' },
{ x: 2, y: 2, z: 1, c: 'capBrown' },
{ x: 3, y: 2, z: 1, c: 'capBrown' },
{ x: 1, y: 2, z: 2, c: 'capBrown' },
{ x: 2, y: 2, z: 2, c: 'capBrown' },
{ x: 3, y: 2, z: 2, c: 'capBrown' },
{ x: 1, y: 2, z: 3, c: 'capBrown' },
{ x: 2, y: 2, z: 3, c: 'capBrown' },
{ x: 3, y: 2, z: 3, c: 'capBrown' },
],
};
/**
* Трава — 7 РАЗНЫХ моделей. WorldGenerator выбирает случайно при размещении,
* + случайный scale и rotation. Это даёт хаотичный, естественный вид:
*
* grass_short — короткие отростки (2-3 voxel'а высотой, маленький пучок)
* grass_tuft — обычный пучок (5-7 voxel'ов крестом)
* grass_tall — высокая трава (5+ voxel'ов вверх стеблем)
* grass_wide — широкий пучок (расходится в стороны)
* grass_clump — кустистый клумб
* grass_blade — отдельная травинка с листом
* grass_dry — сухая, желтоватая
*
* Все используют разные оттенки grass1..4 + редкий grassYellow для разнообразия.
*/
/** Короткие отростки — самая мелкая трава, чаще всего. */
export const GRASS_SHORT = {
name: 'grass_short',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grass1' },
{ x: 2, y: 1, z: 2, c: 'grass1' },
{ x: 1, y: 0, z: 2, c: 'grass3' },
{ x: 3, y: 0, z: 2, c: 'grass2' },
],
};
/** Обычный пучок — крестом, средняя высота. */
export const GRASS_TUFT = {
name: 'grass_tuft',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grass1' },
{ x: 2, y: 1, z: 2, c: 'grass1' },
{ x: 1, y: 1, z: 2, c: 'grass2' },
{ x: 3, y: 1, z: 2, c: 'grass3' },
{ x: 2, y: 2, z: 2, c: 'grass2' },
],
};
/** Высокая трава — столбик 4 voxel + 1 ветка. */
export const GRASS_TALL = {
name: 'grass_tall',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grass2' },
{ x: 2, y: 1, z: 2, c: 'grass1' },
{ x: 2, y: 2, z: 2, c: 'grass3' },
{ x: 2, y: 3, z: 2, c: 'grass4' },
{ x: 3, y: 2, z: 2, c: 'grass3' },
],
};
/** Широкий пучок — расходится в стороны, низкий. */
export const GRASS_WIDE = {
name: 'grass_wide',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grass2' },
{ x: 1, y: 0, z: 2, c: 'grass1' },
{ x: 3, y: 0, z: 2, c: 'grass1' },
{ x: 2, y: 0, z: 1, c: 'grass1' },
{ x: 2, y: 0, z: 3, c: 'grass1' },
{ x: 2, y: 1, z: 2, c: 'grass3' },
],
};
/** Кустистый клумб — компактный куст. */
export const GRASS_CLUMP = {
name: 'grass_clump',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grass2' },
{ x: 1, y: 0, z: 2, c: 'grass2' },
{ x: 3, y: 0, z: 2, c: 'grass2' },
{ x: 2, y: 0, z: 1, c: 'grass2' },
{ x: 2, y: 0, z: 3, c: 'grass2' },
{ x: 2, y: 1, z: 2, c: 'grass1' },
{ x: 2, y: 2, z: 2, c: 'grass3' },
],
};
/** Отдельная травинка с листом — тонкая. */
export const GRASS_BLADE = {
name: 'grass_blade',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grass2' },
{ x: 2, y: 1, z: 2, c: 'grass1' },
{ x: 2, y: 2, z: 2, c: 'grass3' },
],
};
/** Сухая трава — желтовато-зелёная, низкая. */
export const GRASS_DRY = {
name: 'grass_dry',
voxels: [
{ x: 2, y: 0, z: 2, c: 'grassYellow' },
{ x: 1, y: 0, z: 2, c: 'grassYellow' },
{ x: 3, y: 0, z: 2, c: 'grassRed' },
{ x: 2, y: 1, z: 2, c: 'grassYellow' },
],
};
/**
* Все доступные модели — упорядоченный список.
*/
export const DECO_MODELS = {
daisy: FLOWER_DAISY,
cornflower: FLOWER_CORNFLOWER,
poppy: FLOWER_POPPY,
dandelion: FLOWER_DANDELION,
fly_mushroom: MUSHROOM_FLY,
brown_mushroom: MUSHROOM_BROWN,
// 7 разных моделей травы — генератор выбирает случайно
grass_short: GRASS_SHORT,
grass_tuft: GRASS_TUFT,
grass_tall: GRASS_TALL,
grass_wide: GRASS_WIDE,
grass_clump: GRASS_CLUMP,
grass_blade: GRASS_BLADE,
grass_dry: GRASS_DRY,
};
/**
* Пул моделей травы для генератора — с весами для частоты появления.
* Чем больше повторений, тем чаще встречается.
*/
export const GRASS_MODELS_POOL = [
// Самые дешёвые модели (3-4 voxel) — основная масса травы
'grass_short', 'grass_short', 'grass_short', 'grass_short', 'grass_short', 'grass_short', // ×6
'grass_blade', 'grass_blade', 'grass_blade', 'grass_blade', // ×4
// Средние (5-6 voxel) — для разнообразия
'grass_tuft', 'grass_tuft', // ×2
'grass_wide', // ×1
'grass_tall', // ×1
'grass_clump', // ×1
'grass_dry', // ×1
];
/**
* Группы декораций по биому. Используется при процедурном размещении.
*/
export const DECO_BY_BIOME = {
grass: ['daisy', 'cornflower', 'poppy', 'dandelion', 'grass_tuft', 'grass_tuft', 'grass_tuft'],
forest: ['daisy', 'fly_mushroom', 'brown_mushroom', 'grass_tuft', 'grass_tuft'],
plain: ['dandelion', 'cornflower', 'grass_tuft', 'grass_tuft'],
desert: [], // в пустыне декораций нет
snow: [],
mountain: [],
};