2024-07-01 18:12:53 -05:00
|
|
|
import {AdjustmentFilter} from '@pixi/filter-adjustment';
|
|
|
|
import {GlowFilter} from '@pixi/filter-glow';
|
2024-06-27 13:57:18 -05:00
|
|
|
import {Container} from '@pixi/react';
|
2024-07-31 13:01:33 -05:00
|
|
|
import {useCallback, useEffect, useRef, useState} from 'react';
|
2024-07-01 18:12:53 -05:00
|
|
|
|
2024-07-20 04:32:33 -05:00
|
|
|
import {usePacket} from '@/react/context/client.js';
|
2024-07-31 21:07:17 -05:00
|
|
|
import {useDebug} from '@/react/context/debug.js';
|
2024-07-20 04:32:33 -05:00
|
|
|
import {useEcs, useEcsTick} from '@/react/context/ecs.js';
|
|
|
|
import {useMainEntity} from '@/react/context/main-entity.js';
|
|
|
|
import {useRadians} from '@/react/context/radians.js';
|
2024-06-27 13:57:18 -05:00
|
|
|
|
2024-07-31 21:07:17 -05:00
|
|
|
import Entity from './entity.js';
|
2024-06-18 07:24:20 -05:00
|
|
|
|
2024-07-30 12:31:40 -05:00
|
|
|
export default function Entities({monopolizers, particleWorker}) {
|
2024-07-31 21:07:17 -05:00
|
|
|
const [debug] = useDebug();
|
2024-07-01 18:12:53 -05:00
|
|
|
const [ecs] = useEcs();
|
2024-07-31 21:07:17 -05:00
|
|
|
const containerRef = useRef();
|
2024-08-01 13:23:10 -05:00
|
|
|
const latestTick = useRef();
|
2024-07-31 13:01:33 -05:00
|
|
|
const entities = useRef({});
|
2024-07-31 21:07:17 -05:00
|
|
|
const pool = useRef([]);
|
2024-07-01 18:12:53 -05:00
|
|
|
const [mainEntity] = useMainEntity();
|
2024-07-14 21:07:46 -05:00
|
|
|
const radians = useRadians();
|
2024-07-31 21:07:17 -05:00
|
|
|
const willInteractWith = useRef(0);
|
2024-07-14 21:07:46 -05:00
|
|
|
const [interactionFilters] = useState([
|
|
|
|
new AdjustmentFilter(),
|
|
|
|
new GlowFilter({color: 0x0}),
|
|
|
|
]);
|
2024-07-31 21:07:17 -05:00
|
|
|
const pulse = (Math.cos(radians / 4) + 1) * 0.5;
|
|
|
|
interactionFilters[0].brightness = (pulse * 0.75) + 1;
|
|
|
|
interactionFilters[1].outerStrength = pulse * 0.5;
|
|
|
|
const updateEntities = useCallback((payload) => {
|
|
|
|
for (const id in payload) {
|
2024-08-05 02:23:41 -05:00
|
|
|
if ('1' === id) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-07-31 21:07:17 -05:00
|
|
|
if (!payload[id]) {
|
|
|
|
entities.current[id].removeFromContainer();
|
|
|
|
pool.current.push(entities.current[id]);
|
|
|
|
delete entities.current[id];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!entities.current[id]) {
|
2024-08-05 02:23:41 -05:00
|
|
|
entities.current[id] = pool.current.length > 0
|
|
|
|
? pool.current.pop()
|
|
|
|
: new Entity();
|
|
|
|
entities.current[id].reset(ecs.get(id), debug);
|
|
|
|
if (mainEntity === id) {
|
|
|
|
entities.current[id].setMainEntity();
|
|
|
|
}
|
2024-07-31 21:07:17 -05:00
|
|
|
}
|
2024-08-05 03:06:31 -05:00
|
|
|
entities.current[id].update(payload[id], containerRef.current);
|
2024-07-31 21:07:17 -05:00
|
|
|
}
|
|
|
|
}, [debug, ecs, mainEntity])
|
2024-08-05 02:23:41 -05:00
|
|
|
useEffect(() => {
|
|
|
|
if (0 === pool.current.length) {
|
|
|
|
for (let i = 0; i < 1000; ++i) {
|
|
|
|
pool.current.push(new Entity());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, []);
|
2024-07-31 21:07:17 -05:00
|
|
|
useEffect(() => {
|
|
|
|
for (const key in entities.current) {
|
|
|
|
entities.current[key].setDebug(debug);
|
|
|
|
}
|
|
|
|
}, [debug]);
|
|
|
|
usePacket('EcsChange', async () => {
|
|
|
|
for (const id in entities.current) {
|
|
|
|
entities.current[id].removeFromContainer();
|
|
|
|
}
|
|
|
|
entities.current = {};
|
|
|
|
});
|
|
|
|
const onEcsTickEntities = useCallback((payload) => {
|
|
|
|
updateEntities(payload);
|
|
|
|
}, [updateEntities]);
|
|
|
|
useEcsTick(onEcsTickEntities);
|
2024-07-30 09:56:53 -05:00
|
|
|
useEffect(() => {
|
|
|
|
if (!ecs || !particleWorker) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
async function onMessage(diff) {
|
2024-08-01 13:23:10 -05:00
|
|
|
latestTick.current = Promise.resolve(latestTick.current).then(async () => {
|
|
|
|
await ecs.apply(diff.data);
|
|
|
|
updateEntities(diff.data);
|
|
|
|
});
|
2024-07-30 09:56:53 -05:00
|
|
|
}
|
|
|
|
particleWorker.addEventListener('message', onMessage);
|
|
|
|
return () => {
|
|
|
|
particleWorker.removeEventListener('message', onMessage);
|
|
|
|
};
|
2024-07-31 21:07:17 -05:00
|
|
|
}, [ecs, particleWorker, updateEntities]);
|
2024-07-31 09:29:33 -05:00
|
|
|
const onEcsTickParticles = useCallback((payload) => {
|
|
|
|
for (const id in payload) {
|
|
|
|
const update = payload[id];
|
|
|
|
if (update.Emitter?.emit) {
|
|
|
|
for (const id in update.Emitter.emit) {
|
|
|
|
particleWorker?.postMessage(update.Emitter.emit[id]);
|
|
|
|
}
|
|
|
|
}
|
2024-07-11 03:09:28 -05:00
|
|
|
}
|
2024-07-31 09:29:33 -05:00
|
|
|
}, [particleWorker]);
|
|
|
|
useEcsTick(onEcsTickParticles);
|
|
|
|
const onEcsTickInteractions = useCallback((payload, ecs) => {
|
2024-07-11 03:09:28 -05:00
|
|
|
const main = ecs.get(mainEntity);
|
|
|
|
if (main) {
|
2024-07-31 21:07:17 -05:00
|
|
|
if (willInteractWith.current !== main.Interacts.willInteractWith) {
|
|
|
|
if (entities.current[willInteractWith.current]) {
|
|
|
|
entities.current[willInteractWith.current].diffuse.filters = [];
|
|
|
|
}
|
|
|
|
willInteractWith.current = main.Interacts.willInteractWith;
|
|
|
|
}
|
|
|
|
const interacting = entities.current[main.Interacts.willInteractWith];
|
|
|
|
if (interacting) {
|
|
|
|
interacting.diffuse.filters = 0 === monopolizers.length
|
|
|
|
? interactionFilters
|
|
|
|
: [];
|
|
|
|
}
|
2024-07-11 03:09:28 -05:00
|
|
|
}
|
2024-07-31 21:07:17 -05:00
|
|
|
}, [interactionFilters, mainEntity, monopolizers]);
|
2024-07-31 09:29:33 -05:00
|
|
|
useEcsTick(onEcsTickInteractions);
|
2024-06-27 13:57:18 -05:00
|
|
|
return (
|
|
|
|
<Container
|
2024-07-31 21:07:17 -05:00
|
|
|
ref={containerRef}
|
2024-06-27 13:57:18 -05:00
|
|
|
sortableChildren
|
2024-07-31 21:07:17 -05:00
|
|
|
/>
|
2024-06-27 13:57:18 -05:00
|
|
|
);
|
2024-06-11 18:42:48 -05:00
|
|
|
}
|