2024-07-31 10:35:43 -05:00
|
|
|
import {useCallback, useState} from 'react';
|
2024-07-13 03:02:55 -05:00
|
|
|
|
2024-07-20 04:32:33 -05:00
|
|
|
import {usePacket} from '@/react/context/client.js';
|
2024-07-31 09:29:33 -05:00
|
|
|
import {useEcsTick} from '@/react/context/ecs.js';
|
2024-07-20 04:41:00 -05:00
|
|
|
import {parseLetters} from '@/util/dialogue.js';
|
2024-07-12 02:10:22 -05:00
|
|
|
|
2024-07-27 12:31:52 -05:00
|
|
|
import Damages from './damages.jsx';
|
2024-07-12 02:10:22 -05:00
|
|
|
import Entity from './entity.jsx';
|
|
|
|
|
2024-07-14 07:24:15 -05:00
|
|
|
export default function Entities({
|
|
|
|
camera,
|
|
|
|
scale,
|
|
|
|
setChatMessages,
|
|
|
|
setMonopolizers,
|
|
|
|
}) {
|
2024-07-12 02:10:22 -05:00
|
|
|
const [entities, setEntities] = useState({});
|
2024-07-14 02:38:59 -05:00
|
|
|
usePacket('EcsChange', async () => {
|
|
|
|
setEntities({});
|
2024-07-31 09:29:33 -05:00
|
|
|
});
|
|
|
|
const onEcsTick = useCallback((payload, ecs) => {
|
2024-07-13 16:33:23 -05:00
|
|
|
const deleting = {};
|
|
|
|
const updating = {};
|
2024-07-12 02:10:22 -05:00
|
|
|
for (const id in payload) {
|
|
|
|
if ('1' === id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const update = payload[id];
|
|
|
|
if (false === update) {
|
2024-07-13 16:33:23 -05:00
|
|
|
deleting[id] = true;
|
2024-07-12 02:10:22 -05:00
|
|
|
continue;
|
|
|
|
}
|
2024-07-13 16:33:23 -05:00
|
|
|
updating[id] = ecs.get(id);
|
2024-07-12 02:10:22 -05:00
|
|
|
const {dialogue} = update.Interlocutor || {};
|
|
|
|
if (dialogue) {
|
2024-07-13 16:33:23 -05:00
|
|
|
const {dialogues} = updating[id].Interlocutor;
|
2024-07-12 02:10:22 -05:00
|
|
|
for (const key in dialogue) {
|
2024-07-13 03:02:55 -05:00
|
|
|
dialogues[key] = dialogue[key];
|
2024-07-22 04:19:29 -05:00
|
|
|
if (!dialogues[key].offset) {
|
|
|
|
dialogues[key].offset = {x: 0, y: 0};
|
|
|
|
}
|
2024-07-22 03:55:37 -05:00
|
|
|
if ('track' === dialogues[key].origin) {
|
|
|
|
dialogues[key].origin = () => updating[id].Position;
|
|
|
|
}
|
2024-07-22 04:19:29 -05:00
|
|
|
if ('track' === dialogues[key].position) {
|
|
|
|
dialogues[key].position = () => updating[id].Position;
|
|
|
|
}
|
2024-07-13 03:02:55 -05:00
|
|
|
dialogues[key].letters = parseLetters(dialogues[key].body);
|
2024-07-14 21:44:33 -05:00
|
|
|
setChatMessages((chatMessages) => ({
|
|
|
|
[[id, key].join('-')]: dialogues[key].letters,
|
|
|
|
...chatMessages,
|
|
|
|
}));
|
2024-07-13 17:08:23 -05:00
|
|
|
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]);
|
|
|
|
}
|
2024-07-13 03:02:55 -05:00
|
|
|
dialogues[key].onClose = () => {
|
|
|
|
setEntities((entities) => ({
|
|
|
|
...entities,
|
|
|
|
[id]: ecs.rebuild(id),
|
|
|
|
}));
|
2024-07-13 17:08:23 -05:00
|
|
|
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];
|
2024-07-13 03:02:55 -05:00
|
|
|
};
|
2024-07-12 02:10:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-13 16:33:23 -05:00
|
|
|
setEntities((entities) => {
|
|
|
|
for (const id in deleting) {
|
|
|
|
delete entities[id];
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
...entities,
|
|
|
|
...updating,
|
|
|
|
};
|
|
|
|
});
|
2024-07-31 10:35:43 -05:00
|
|
|
}, [setChatMessages, setMonopolizers]);
|
2024-07-31 09:29:33 -05:00
|
|
|
useEcsTick(onEcsTick);
|
2024-07-12 02:10:22 -05:00
|
|
|
const renderables = [];
|
|
|
|
for (const id in entities) {
|
|
|
|
renderables.push(
|
|
|
|
<Entity
|
|
|
|
camera={camera}
|
|
|
|
entity={entities[id]}
|
|
|
|
key={id}
|
|
|
|
scale={scale}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return (
|
2024-07-30 14:05:27 -05:00
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
translate: `
|
|
|
|
calc(-1px * ${camera.x})
|
|
|
|
calc(-1px * ${camera.y})
|
|
|
|
`,
|
|
|
|
}}
|
|
|
|
>
|
2024-07-12 02:10:22 -05:00
|
|
|
{renderables}
|
2024-07-27 12:31:52 -05:00
|
|
|
<Damages
|
|
|
|
scale={scale}
|
|
|
|
/>
|
2024-07-30 14:05:27 -05:00
|
|
|
</div>
|
2024-07-12 02:10:22 -05:00
|
|
|
);
|
|
|
|
}
|