/
RaskolnickOFF
/
3D
Обзор
Документация
Войти
/
RaskolnickOFF
/
3D
Код
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
js/source/core/Components.js
264 строки
14 KB
RaskolnickOFF
fixes
19 июн 2026, 19:05
19 июн 2026, 19:05
84fe909
Код
Авторство
О чём код?
// js/source/core/Components.js /** * Константы — имена компонентов ECS. * * Группы: * CORE — позиция, трансформ, скорость * IDENTITY — маркеры типа сущности (player, enemy, tree, item, zone) * RENDER — THREE.js визуал * COMBAT — здоровье, бой, неуязвимость * SURVIVAL — голод, стамина * AI_STATE — FSM врагов * AI_PERCEP — восприятие (зрение, слух, запах) * AI_MEMORY — память врагов (известная позиция, таймеры) * AI_PATROL — патрулирование * AI_IDLE — бездействие, осмотр * AI_COMBAT — боевые таймеры * ZONE — зоны мира * CAMERA — камера (offsets) * LIFECYCLE — удаление сущностей */ // ============================================================================ // CORE — позиция, движение, трансформ // ============================================================================ export const Components = { TRANSFORM: 'transform', // {x, y, z, rotY} POSITION: 'position', // {x, y, z} (legacy/alias) VELOCITY: 'velocity', // {x, y, z} — текущая скорость DESIRED_VELOCITY: 'desiredVelocity', // {x, z} — желаемая (AI) DESIRED_ROTATION: 'desiredRotation', // rotY — желаемый поворот (AI) NOISE: 'noise', // 0|3|8 — уровень шума игрока // ============================================================================ // IDENTITY — маркеры типа сущности // ============================================================================ PLAYER: 'player', // true — сущность-игрок CURRENT_TILE: 'current_tile', // {tx, tz} — тайл игрока ENEMY: 'enemy', // true — сущность-враг ENEMY_TYPE: 'enemyType', // string — тип врага (из spawnTable) TREE: 'tree', // true — сущность-дерево TREE_TYPE: 'treeType', // string — тип дерева ("pine", "oak", ...) ITEM_TYPE: 'itemType', // string — тип предмета (лут) BERRY_BUSH: 'berryBush', BERRY_BUSH_TYPE: 'berryBushType', // ============================================================================ // RENDER — визуал // ============================================================================ MESH: 'mesh', // THREE.Object3D // ============================================================================ // COMBAT — здоровье, бой, защита // ============================================================================ HEALTH: 'health', // number — текущее HP INVULNERABLE: 'invulnerable', // boolean — временная неуязвимость // ============================================================================ // SURVIVAL — голод, выносливость // ============================================================================ HUNGER: 'hunger', // number — текущий голод STAMINA: 'stamina', // number — текущая стамина THIRST: 'thirst', // number — текущая жажда // ============================================================================ // AI: STATE — конечный автомат врагов // ============================================================================ AI_STATE: 'aiState', // 'idle'|'patrol'|'chase'|'combat'|'search'|'return' // ============================================================================ // AI: PERCEPTION — сенсоры (зрение, слух, запах) // ============================================================================ CAN_SEE: 'canSee', // boolean — игрок в зоне видимости CAN_HEAR: 'canHear', // boolean — игрок слышен CAN_SMELL: 'canSmell', // boolean — игрок в радиусе запаха KNOWN_POSITION: 'knownPosition', // {x, z} — текущая известная позиция игрока // ============================================================================ // AI: MEMORY — память о цели, поиск, возврат // ============================================================================ LAST_KNOWN: 'lastKnown', // {x, z} — последняя известная позиция MEMORY_TIMER: 'memoryTimer', // number — время удержания цели в памяти SEARCH_TIMER: 'searchTimer', // number — время поиска после потери SEARCH_DIRECTION: 'searchDirection', // {x, z} — направление поиска ORIGIN_POSITION: 'originPosition', // {x, y, z} — точка дома/спавна CURRENT_ANGLE: 'currentAngle', // number — текущий угол поворота // ============================================================================ // AI: PATROL — патрулирование // ============================================================================ PATROL_DIRECTION: 'patrolDirection', // {x, z} — направление патруля PATROL_TIMER: 'patrolTimer', // number — оставшееся время патруля PAUSE_TIMER: 'pauseTimer', // number — пауза при патруле // ============================================================================ // AI: IDLE — бездействие, осмотр // ============================================================================ IDLE_TIMER: 'idleTimer', // number — время до перехода в patrol LOOK_TIMER: 'lookTimer', // number — интервал осмотра LOOK_TARGET_ANGLE: 'lookTargetAngle', // number — целевой угол поворота головы // ============================================================================ // AI: COMBAT — бой // ============================================================================ COMBAT_SLOT: 'combatSlot', // number — слот в бою (?) COMBAT_TIMER: 'combatTimer', // number — кулдаун атаки // ============================================================================ // ZONE — зоны мира // ============================================================================ ZONE: 'zone', // true — сущность-зона ZONE_ID: 'zoneId', // number — уникальный ID зоны ZONE_BOUNDS: 'zoneBounds', // {minX, maxX, minZ, maxZ} ZONE_BIOME: 'zoneBiome', // 'forest'|'swamp'|'snow' ZONE_STATE: 'zoneState', // 'inactive'|'active'|'sleeping' ZONE_SPAWN_TABLE: 'zoneSpawnTable', // {enemies:[...], loot:[...], trees:[...]} ZONE_OWNED: 'zoneOwned', // number — ID зоны-владельца // ============================================================================ // CAMERA — смещения камеры // ============================================================================ CAMERA_ANGLE: 'cameraAngle', // number CAMERA_OFFSET_X: 'cameraOffsetX', // number CAMERA_OFFSET_Z: 'cameraOffsetZ', // number // ============================================================================ // LIFECYCLE — удаление // ============================================================================ PENDING_DESTROY: 'pendingDestroy', // boolean — помечен на удаление }; // ============================================================================ // ComponentMeta — persistent/transient для Save/Load (F1) // ============================================================================ export const ComponentsMeta = { // --- CORE --- [Components.TRANSFORM]: { persistent: true }, [Components.POSITION]: { persistent: false }, [Components.VELOCITY]: { persistent: false }, [Components.DESIRED_VELOCITY]: { persistent: false }, [Components.DESIRED_ROTATION]: { persistent: false }, [Components.NOISE]: { persistent: false }, // --- IDENTITY --- [Components.PLAYER]: { persistent: true }, [Components.ENEMY]: { persistent: true }, [Components.ENEMY_TYPE]: { persistent: true }, [Components.TREE]: { persistent: true }, [Components.TREE_TYPE]: { persistent: true }, [Components.ITEM_TYPE]: { persistent: true }, [Components.BERRY_BUSH]: { persistent: true }, [Components.BERRY_BUSH_TYPE]: { persistent: true }, // --- RENDER --- [Components.MESH]: { persistent: false }, // --- COMBAT --- [Components.HEALTH]: { persistent: true }, [Components.INVULNERABLE]: { persistent: true }, // --- SURVIVAL --- [Components.HUNGER]: { persistent: true }, [Components.STAMINA]: { persistent: true }, [Components.THIRST]: { persistent: true }, // --- AI: STATE --- [Components.AI_STATE]: { persistent: true }, // --- AI: PERCEPTION --- [Components.CAN_SEE]: { persistent: false }, [Components.CAN_HEAR]: { persistent: false }, [Components.CAN_SMELL]: { persistent: false }, [Components.KNOWN_POSITION]: { persistent: false }, // --- AI: MEMORY --- [Components.LAST_KNOWN]: { persistent: false }, [Components.MEMORY_TIMER]: { persistent: true }, [Components.SEARCH_TIMER]: { persistent: true }, [Components.SEARCH_DIRECTION]: { persistent: true }, [Components.ORIGIN_POSITION]: { persistent: true }, [Components.CURRENT_ANGLE]: { persistent: false }, // --- AI: PATROL --- [Components.PATROL_DIRECTION]: { persistent: true }, [Components.PATROL_TIMER]: { persistent: true }, [Components.PAUSE_TIMER]: { persistent: true }, // --- AI: IDLE --- [Components.IDLE_TIMER]: { persistent: true }, [Components.LOOK_TIMER]: { persistent: true }, [Components.LOOK_TARGET_ANGLE]: { persistent: false }, // --- AI: COMBAT --- [Components.COMBAT_SLOT]: { persistent: false }, [Components.COMBAT_TIMER]: { persistent: true }, // --- ZONE --- [Components.ZONE]: { persistent: true }, [Components.ZONE_ID]: { persistent: true }, [Components.ZONE_BOUNDS]: { persistent: true }, [Components.ZONE_BIOME]: { persistent: true }, [Components.ZONE_STATE]: { persistent: true }, [Components.ZONE_SPAWN_TABLE]: { persistent: true }, [Components.ZONE_OWNED]: { persistent: true }, // --- CAMERA --- [Components.CAMERA_ANGLE]: { persistent: false }, [Components.CAMERA_OFFSET_X]: { persistent: false }, [Components.CAMERA_OFFSET_Z]: { persistent: false }, // --- LIFECYCLE --- [Components.PENDING_DESTROY]: { persistent: false }, }; // ============================================================================ // Утилита // ============================================================================ /** * Проверяет, является ли компонент persistent (подлежит сохранению). * @param {string} componentType * @returns {boolean} */ export function isPersistent(componentType) { return ComponentsMeta[componentType]?.persistent === true; } // УЛУЧШЕНИЯ ДЛЯ ТЕСТИРОВАНИЯ: // 1. getAllPersistent() — вернуть список всех persistent компонентов. // Удобно для SaveSystem: componentFilter = getAllPersistent() // Сейчас это захардкожено или собирается вручную. // export function getAllPersistent() { // return Object.keys(ComponentMeta).filter(key => ComponentMeta[key].persistent); // } // 2. getByGroup(group) — вернуть компоненты по группе. // Сейчас группы в комментариях, но кодом не проверяются. // Можно добавить структуру: // export const ComponentGroup = { // CORE: ['transform', 'position', 'velocity', 'desiredVelocity', 'desiredRotation', 'noise'], // IDENTITY: ['player', 'enemy', 'enemyType', 'tree', 'treeType', 'itemType', 'berryBush', 'berryBushType'], // AI_STATE: ['aiState'], // // ... // }; // export function getByGroup(group) { // return ComponentGroup[group] || []; // } // 3. validate(entity) — проверить, что у сущности нет конфликтующих компонентов. // Например, не может быть одновременно PLAYER и ENEMY. // Пока не нужно, но когда систем станет 30+, поможет ловить баги конфигурации. // export function validate(entity) { // if (entity.has(Component.PLAYER) && entity.has(Component.ENEMY)) { // console.error('Entity has both PLAYER and ENEMY components', entity.id); // } // } // 4. ComponentMeta — поле dependencies. // Какие компоненты обязательны для этого. // Например: AI_STATE требует ENEMY. При добавлении AI_STATE можно проверять. // [Component.AI_STATE]: { persistent: true, requires: [Component.ENEMY] }, // Пока избыточно, но если будут баги с отсутствующими компонентами — добавить.