import {useState} from 'react'; import {usePacket} from '@/react/context/client.js'; import {useEcs, useEcsTick} from '@/react/context/ecs.js'; import {parseLetters} from '@/util/dialogue.js'; import Entity from './entity.jsx'; export default function Entities({ camera, scale, setChatMessages, setMonopolizers, }) { const [ecs] = useEcs(); const [entities, setEntities] = useState({}); usePacket('EcsChange', async () => { setEntities({}); }, [setEntities]); useEcsTick((payload) => { if (!ecs) { return; } const deleting = {}; const updating = {}; for (const id in payload) { if ('1' === id) { continue; } const update = payload[id]; if (false === update) { deleting[id] = true; continue; } updating[id] = ecs.get(id); const {dialogue} = update.Interlocutor || {}; if (dialogue) { const {dialogues} = updating[id].Interlocutor; for (const key in dialogue) { dialogues[key] = dialogue[key]; dialogues[key].letters = parseLetters(dialogues[key].body); setChatMessages((chatMessages) => ({ [[id, key].join('-')]: dialogues[key].letters, ...chatMessages, })); const skipListeners = new Set(); dialogues[key].addSkipListener = (listener) => { skipListeners.add(listener); return () => { skipListeners.delete(listener); } } const monopolizer = { trigger: () => { for (const listener of skipListeners) { listener(); } }, }; if (dialogues[key].monopolizer) { setMonopolizers((monopolizers) => [...monopolizers, monopolizer]); } dialogues[key].onClose = () => { setEntities((entities) => ({ ...entities, [id]: ecs.rebuild(id), })); if (dialogues[key].monopolizer) { setMonopolizers((monopolizers) => { const index = monopolizers.indexOf(monopolizer); if (-1 === index) { return monopolizers; } monopolizers.splice(index, 1); return [...monopolizers]; }); } delete dialogues[key]; }; } } } setEntities((entities) => { for (const id in deleting) { delete entities[id]; } return { ...entities, ...updating, }; }); }, [ecs, setMonopolizers]); const renderables = []; for (const id in entities) { renderables.push( ); } return ( <> {renderables} ); }