/
RaskolnickOFF
/
3D
Обзор
Документация
Войти
/
RaskolnickOFF
/
3D
Код
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
js/source/core/Engine.js
165 строк
6 KB
RaskolnickOFF
debug refactor part 2
15 июн 2026, 22:32
15 июн 2026, 22:32
f4de7c0
Код
Авторство
О чём код?
// js/source/core/Engine.js import { Entity } from './Entity.js'; export class Engine { constructor(pipeline) { this.entities = new Map(); this._nextId = 0; this.pipeline = pipeline; } createEntity() { const id = this._nextId++; const entity = new Entity(id); this.entities.set(id, entity); return entity; } getEntity(id) { return this.entities.get(id); } removeEntity(id) { this.entities.delete(id); } forEach(fn) { for (const entity of this.entities.values()) { fn(entity); } } with(componentName) { const result = []; for (const entity of this.entities.values()) { if (entity.has(componentName)) { result.push(entity); } } return result; } update(dt) { this.pipeline.execute('PRE_UPDATE', this); this.pipeline.execute('UPDATE', this, dt); this.pipeline.execute('POST_UPDATE', this, dt); this.pipeline.execute('RENDER', this); } get count() { return this.entities.size; } /** * Очищает все сущности из движка. * Используется при загрузке сохранения или сбросе мира. * Сбрасывает _nextId для чистого состояния после загрузки. */ clear() { this.entities.clear(); this._nextId = 0; } /** * Сериализует все сущности, применяя фильтр к компонентам. * @param {Function} componentFilter - Функция (componentName) => boolean, определяющая, сохранять ли компонент. * @returns {Array<Object>} Массив объектов { id, components: { [name]: value } } */ serializeAll(componentFilter) { const serializedEntities = []; for (const entity of this.entities.values()) { const componentsData = {}; let hasPersistentComponents = false; for (const [compName, compValue] of entity.components.entries()) { if (componentFilter(compName)) { componentsData[compName] = compValue; hasPersistentComponents = true; } } if (hasPersistentComponents) { serializedEntities.push({ id: entity.id, components: componentsData }); } } return serializedEntities; } /** * Десериализует и создает сущности из данных. * ВАЖНО: не сохраняет оригинальные ID — использует новый _nextId. * Вызывающие должны обновить ссылки (камера, слоты) через события. * @param {Array<Object>} entitiesData - Массив объектов { id, components } * @returns {Map<number, Entity>} Карта созданных сущностей (newId -> Entity) */ deserializeAndSpawn(entitiesData) { const spawnedEntities = new Map(); for (const data of entitiesData) { const entity = this.createEntity(); for (const [compName, compValue] of Object.entries(data.components)) { entity.add(compName, compValue); } spawnedEntities.set(entity.id, entity); } return spawnedEntities; } // УЛУЧШЕНИЯ ДЛЯ ТЕСТИРОВАНИЯ: // 1. count — геттер количества сущностей. Для отладки: engine.count → 42 // get count() { // return this.entities.size; // } // 2. withMultiple(...componentNames) — сущности, имеющие ВСЕ указанные компоненты. // Сейчас with() ищет по одному. Часто нужно несколько: // engine.withMultiple(Component.POSITION, Component.HEALTH) // withMultiple(...componentNames) { // const result = []; // for (const entity of this.entities.values()) { // if (componentNames.every(c => entity.has(c))) { // result.push(entity); // } // } // return result; // } // 3. first(componentName) — первая сущность с компонентом. // Для синглтонов (игрок, камера) вместо with(...)[0]: // engine.first(Component.PLAYER) → entity || null // first(componentName) { // for (const entity of this.entities.values()) { // if (entity.has(componentName)) { // return entity; // } // } // return null; // } // 4. update(dt) — аргументы для RENDER фазы. // Сейчас в RENDER передаётся только this. Возможно, системам рендера // нужен renderContext, а не engine. Тогда сигнатуру update стоит поменять: // update(dt, renderContext) { // this.pipeline.execute('PRE_UPDATE', this, dt); // this.pipeline.execute('UPDATE', this, dt); // this.pipeline.execute('POST_UPDATE', this, dt); // this.pipeline.execute('RENDER', renderContext, dt); // } // Зависит от того, как системы рендера получают доступ к сцене/камере. // 5. deserializeAndSpawn — копировать или не копировать компоненты. // Сейчас передаётся compValue как есть. Если это объект (position: {x, y, z}), // мутации в игре могут изменить объект, на который ссылаются данные сохранения // (если они вдруг сохранены где-то снаружи). Обычно не проблема, // но если будут баги с сохранениями — начать отсюда. }