/
RaskolnickOFF
/
3D
Обзор
Документация
Войти
/
RaskolnickOFF
/
3D
Код
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
js/debug/WorldDebugOverlay.js
207 строк
9 KB
RaskolnickOFF
debug refactor part 2
15 июн 2026, 22:32
15 июн 2026, 22:32
f4de7c0
Код
Авторство
О чём код?
// js/debug/WorldDebugOverlay.js — дебаг-оверлей с зонами import LIB from 'LIB'; import { Components } from '../source/core/Components.js'; export class WorldDebugOverlay { constructor(timeInterval, SETTINGS, container) { this.settings = SETTINGS; if (!this.settings.debug.world) return; this.cfg = this.settings.UI.debug; this._interval = timeInterval; this.timer = 0; this.container = container; this._renderDOM(this.container); this._zonesCount = 0; } _renderDOM(container) { if (!this.settings.debug.world) return; // --- World --- const label = document.createElement('label'); const span = document.createElement('span'); span.textContent = this.cfg.worldCurrent; const row = LIB.dom.infoRow({ [this.cfg.worldEntitiesClass]: this.cfg.worldEntities, [this.cfg.worldZonesClass]: this.cfg.worldZones, [this.cfg.worldItemsClass]: this.cfg.worldItems }); label.append(span, row); // --- Zones --- const zonesLabel = document.createElement('label'); const zonesSpan = document.createElement('span'); zonesSpan.textContent = this.cfg.worldZonesActivity; const zonesRow = LIB.dom.infoRow({ [this.cfg.worldActiveClass]: this.cfg.worldActiveZones, [this.cfg.worldInactiveClass]: this.cfg.worldInactiveZones, [this.cfg.worldSleepClass]: this.cfg.worldSleepZones, }); zonesLabel.append(zonesSpan, zonesRow); // --- Enemies --- const enemiesLabel = document.createElement('label'); const enemiesSpan = document.createElement('span'); enemiesSpan.textContent = this.cfg.worldEnemies; const enemiesFirstRow = LIB.dom.infoRow({ [this.cfg.worldTotalClass]: this.cfg.worldEnemiesTotal, [this.cfg.worldIdleClass]: this.cfg.worldEnemiesIdle, [this.cfg.worldPatrolClass]: this.cfg.worldEnemiesPatrol }); const enemiesSecondRow = LIB.dom.infoRow({ [this.cfg.worldChaseClass]: this.cfg.worldEnemiesChase, [this.cfg.worldSearchClass]: this.cfg.worldEnemiesSearch, [this.cfg.worldReturnClass]: this.cfg.worldEnemiesReturn }); enemiesLabel.append(enemiesSpan, enemiesFirstRow, enemiesSecondRow); // --- Zones Detail --- const zonesDetailLabel = document.createElement('label'); const zonesDetailSpan = document.createElement('span'); zonesDetailSpan.textContent = this.cfg.worldZonesDetail; const zonesDetailList = document.createElement('ol'); zonesDetailLabel.append(zonesDetailSpan, zonesDetailList); container.append(label, zonesLabel, enemiesLabel, zonesDetailLabel); this._zoneDetailContainer = zonesDetailList; this._totalEl = enemiesFirstRow.querySelector( '.' + this.cfg.worldTotalClass); this._idleEl = enemiesFirstRow.querySelector( '.' + this.cfg.worldIdleClass); this._patrolEl = enemiesFirstRow.querySelector( '.' + this.cfg.worldPatrolClass); this._chaseEl = enemiesSecondRow.querySelector( '.' + this.cfg.worldChaseClass); this._searchEl = enemiesSecondRow.querySelector( '.' + this.cfg.worldSearchClass); this._returnEl = enemiesSecondRow.querySelector( '.' + this.cfg.worldReturnClass); this._entitiesEl = row.querySelector( '.' + this.cfg.worldEntitiesClass); this._itemsEl = row.querySelector( '.' + this.cfg.worldItemsClass); this._zonesEl = row.querySelector( '.' + this.cfg.worldZonesClass); this._zonesActiveEl = zonesRow.querySelector( '.' + this.cfg.worldActiveClass); this._zonesInactiveEl = zonesRow.querySelector( '.' + this.cfg.worldInactiveClass); this._zonesSleepingEl = zonesRow.querySelector( '.' + this.cfg.worldSleepClass); } update(engine, acc) { if (!this.settings.debug.world) return; this.timer += acc; if (this.timer < this._interval) return; this.timer -= this._interval; const zones = [...engine.with(Components.ZONE)]; this._zonesCount = zones.length; const allEntities = engine.with(Components.TRANSFORM); const items = [...allEntities].filter(e => !e.has(Components.PLAYER) && !e.has(Components.ENEMY) && !e.has(Components.PENDING_DESTROY) ); // --- World --- this._entitiesEl.textContent = [...allEntities].length; this._itemsEl.textContent = items.length; this._zonesEl.textContent = zones.length; // --- Zones --- const zoneStates = { active: 0, sleeping: 0, inactive: 0 }; for (const zone of zones) { const state = zone.get(Components.ZONE_STATE) || 'inactive'; zoneStates[state] = (zoneStates[state] || 0) + 1; } this._zonesActiveEl.textContent = zoneStates.active; this._zonesInactiveEl.textContent = zoneStates.inactive; this._zonesSleepingEl.textContent = zoneStates.sleeping; // --- Enemies --- const enemies = engine.with(Components.ENEMY); const stateCounts = { idle: 0, patrol: 0, chase: 0, search: 0, 'return': 0 }; for (const enemy of enemies) { const state = enemy.get(Components.AI_STATE) || 'idle'; stateCounts[state] = (stateCounts[state] || 0) + 1; } this._totalEl.textContent = [...enemies].length; this._idleEl.textContent = stateCounts.idle; this._patrolEl.textContent = stateCounts.patrol; this._chaseEl.textContent = stateCounts.chase; this._searchEl.textContent = stateCounts.search; this._returnEl.textContent = stateCounts['return']; // --- Zones Detail --- const zonesInfo = []; const enemiesByZone = new Map(); for (const enemy of enemies) { const zoneId = enemy.get(Components.ZONE_OWNED); if (zoneId !== undefined) { enemiesByZone.set(zoneId, (enemiesByZone.get(zoneId) || 0) + 1); } } for (const [zoneId, count] of enemiesByZone) { const zone = zones.find(z => z.get(Components.ZONE_ID) === zoneId); const state = zone ? zone.get(Components.ZONE_STATE) : '?'; zonesInfo.push({ zoneId, count, state }); } // Обновление списка зон this.updateZones( this._zonesCount, this._zoneDetailContainer, enemiesByZone.size, zonesInfo); } updateZones(zones, container, size, info) { if (!this.settings.debug.world || !zones || !container) return; // console.log(zones, container.children.length); if (!container.children.length) { for (let id = 0; id < zones + 1; id++) { const li = document.createElement('li'); if (id === 0) { li.textContent = this.cfg.worldPeaceful; li.id = this.cfg.worldZoneID + id; } else { li.textContent = `${this.cfg.worldZoneName} ${id} : `; const span = document.createElement('span'); span.id = this.cfg.worldZoneID + id; span.className = this.cfg.worldZoneClass; li.appendChild(span); } container.appendChild(li); } } const peaceful = container.querySelector( '#' + this.cfg.worldZoneID + 0); const list = container.querySelectorAll('.' + this.cfg.worldZoneClass); list.forEach(span => { if (!span.classList.contains('hidden')) { span.classList.add('hidden'); } }); if (size === 0) { if (peaceful.classList.contains('hidden')) { peaceful.classList.remove('hidden'); } } else { if (!peaceful.classList.contains('hidden')) { peaceful.classList.add('hidden'); } info.forEach(({ zoneId, count, state }) => { const el = container.querySelector( '#' + this.cfg.worldZoneID + zoneId); if (el) { el.classList.remove('hidden'); const stateText = state === 'active' ? this.cfg.worldEnemiesActive : ( state === 'sleep' ? this.cfg.worldEnemiesSleep : this.cfg.worldEnemiesNonActive ); el.textContent = ` ${this.cfg.worldEnemiesText} ${count} (${stateText}) `; } }); } } updateInterval(interval) { if (!this.settings.debug.world) return; if (interval !== this._interval) { this._interval = interval; } } }