From 503a7d2514efea959368c4ca784126ddd885a56c Mon Sep 17 00:00:00 2001 From: cha0s Date: Fri, 6 Sep 2024 21:13:52 -0500 Subject: [PATCH] perf: refs --- app/react/components/devtools.jsx | 8 ++-- app/react/components/devtools/tiles.jsx | 10 ++--- app/react/components/pixi/ecs.jsx | 6 +-- app/react/components/pixi/entities.jsx | 33 ++++++++-------- app/react/components/pixi/entity.js | 3 +- app/react/components/ui.jsx | 50 ++++++++++++------------ app/react/context/ecs.js | 8 ++-- app/routes/_main-menu.play.$.$/route.jsx | 15 ++++--- 8 files changed, 65 insertions(+), 68 deletions(-) diff --git a/app/react/components/devtools.jsx b/app/react/components/devtools.jsx index 42fc095..2d00ebf 100644 --- a/app/react/components/devtools.jsx +++ b/app/react/components/devtools.jsx @@ -14,14 +14,14 @@ export default function Devtools({ eventsChannel, }) { const client = useClient(); - const [mainEntity] = useMainEntity(); + const mainEntityRef = useMainEntity(); const [mainEntityJson, setMainEntityJson] = useState(''); const onEcsTick = useCallback((payload, ecs) => { - if (!mainEntity) { + if (!mainEntityRef.current) { return; } - setMainEntityJson(JSON.stringify(ecs.get(mainEntity), null, 2)); - }, [mainEntity]); + setMainEntityJson(JSON.stringify(ecs.get(mainEntityRef.current), null, 2)); + }, [mainEntityRef]); useEcsTick(onEcsTick); return (
diff --git a/app/react/components/devtools/tiles.jsx b/app/react/components/devtools/tiles.jsx index 57690d4..a2cf9f7 100644 --- a/app/react/components/devtools/tiles.jsx +++ b/app/react/components/devtools/tiles.jsx @@ -17,12 +17,12 @@ export default function Tiles({eventsChannel}) { const [layer, setLayer] = useState(0); const [brush, setBrush] = useState(0); const [stamp, setStamp] = useState([]); - const [ecs] = useEcs(); + const ecsRef = useEcs(); useEffect(() => { - if (!ecs) { + if (!ecsRef.current) { return; } - const master = ecs.get(1); + const master = ecsRef.current.get(1); if (!master) { return; } @@ -56,10 +56,10 @@ export default function Tiles({eventsChannel}) { eventsChannel.removeListener('click', onClick); }; }); - if (!ecs) { + if (!ecsRef.current) { return false; } - const master = ecs.get(1); + const master = ecsRef.current.get(1); if (!master) { return false; } diff --git a/app/react/components/pixi/ecs.jsx b/app/react/components/pixi/ecs.jsx index c64e768..815e8ff 100644 --- a/app/react/components/pixi/ecs.jsx +++ b/app/react/components/pixi/ecs.jsx @@ -11,14 +11,14 @@ import TileLayer from './tile-layer.jsx'; import Water from './water.jsx'; export default function Ecs({camera, monopolizers, particleWorker, scale}) { - const [mainEntity] = useMainEntity(); + const mainEntityRef = useMainEntity(); const [layers, setLayers] = useState([]); const [hour, setHour] = useState(10); const [projected, setProjected] = useState([]); const [position, setPosition] = useState({x: 0, y: 0}); const [water, setWater] = useState(); const onEcsTick = useCallback((payload, ecs) => { - const entity = ecs.get(mainEntity); + const entity = ecs.get(mainEntityRef.current); for (const id in payload) { const update = payload[id]; switch (id) { @@ -42,7 +42,7 @@ export default function Ecs({camera, monopolizers, particleWorker, scale}) { setPosition(Position.toJSON()); setProjected(Wielder.activeItem()?.project(Position.tile, Direction.quantize(4))); } - }, [mainEntity]); + }, [mainEntityRef]); useEcsTick(onEcsTick); return ( { + const updateEntities = useCallback((payload, ecs) => { for (const id in payload) { if ('1' === id) { continue; @@ -43,14 +43,15 @@ export default function Entities({monopolizers, particleWorker}) { 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].reset(ecs.get(id)); + entities.current[id].setDebug(false); + if (mainEntityRef.current === id) { entities.current[id].setMainEntity(); } } entities.current[id].update(payload[id], containerRef.current); } - }, [debug, ecs, mainEntity]) + }, [mainEntityRef]) useEffect(() => { if (0 === pool.current.length) { for (let i = 0; i < 1000; ++i) { @@ -69,25 +70,25 @@ export default function Entities({monopolizers, particleWorker}) { } entities.current = {}; }); - const onEcsTickEntities = useCallback((payload) => { - updateEntities(payload); - }, [updateEntities]); - useEcsTick(onEcsTickEntities); + useEcsTick(updateEntities); useEffect(() => { - if (!ecs || !particleWorker) { + if (!particleWorker) { return; } async function onMessage(diff) { + if (!ecsRef.current) { + return; + } latestTick.current = Promise.resolve(latestTick.current).then(async () => { - await ecs.apply(diff.data); - updateEntities(diff.data); + await ecsRef.current.apply(diff.data); + updateEntities(diff.data, ecsRef.current); }); } particleWorker.addEventListener('message', onMessage); return () => { particleWorker.removeEventListener('message', onMessage); }; - }, [ecs, particleWorker, updateEntities]); + }, [ecsRef, particleWorker, updateEntities]); const onEcsTickParticles = useCallback((payload) => { for (const id in payload) { const update = payload[id]; @@ -100,7 +101,7 @@ export default function Entities({monopolizers, particleWorker}) { }, [particleWorker]); useEcsTick(onEcsTickParticles); const onEcsTickInteractions = useCallback((payload, ecs) => { - const main = ecs.get(mainEntity); + const main = ecs.get(mainEntityRef.current); if (main) { if (willInteractWith.current !== main.Interacts.willInteractWith) { if (entities.current[willInteractWith.current]) { @@ -115,7 +116,7 @@ export default function Entities({monopolizers, particleWorker}) { : []; } } - }, [interactionFilters, mainEntity, monopolizers]); + }, [interactionFilters, mainEntityRef, monopolizers]); useEcsTick(onEcsTickInteractions); return ( { async function setEcsStuff() { const {default: Components} = await import('@/ecs/components/index.js'); @@ -174,7 +174,7 @@ function Ui({disconnected}) { event.preventDefault(); } if ('keyDown' === type) { - setDebug(!debug); + setDebug((debug) => !debug); } break; } @@ -302,7 +302,6 @@ function Ui({disconnected}) { }, [ chatIsOpen, client, - debug, devtoolsIsOpen, hotbarHideHandle, isInventoryOpen, @@ -313,22 +312,21 @@ function Ui({disconnected}) { ]); const onEcsChangePacket = useCallback(() => { refreshEcs(); - setMainEntity(undefined); + mainEntityRef.current = undefined; setMonopolizers([]); - }, [refreshEcs, setMainEntity]); + }, [refreshEcs, mainEntityRef]); usePacket('EcsChange', onEcsChangePacket); const onTickPacket = useCallback(async (payload, client) => { if (0 === Object.keys(payload.ecs).length) { return; } latestTick.current = Promise.resolve(latestTick.current).then(async () => { - await ecs.apply(payload.ecs); + await ecsRef.current.apply(payload.ecs); client.emitter.invoke(':Ecs', payload.ecs); }); - }, [ecs]); + }, [ecsRef]); usePacket('Tick', onTickPacket); const onEcsTick = useCallback((payload, ecs) => { - let localMainEntity = mainEntity; for (const id in payload) { const entity = ecs.get(id); const update = payload[id]; @@ -336,10 +334,10 @@ function Ui({disconnected}) { continue; } if (update.MainEntity) { - setMainEntity(localMainEntity = id); + mainEntityRef.current = id; } if (update.Inventory) { - if (localMainEntity === id) { + if (mainEntityRef.current === id) { setBufferSlot(entity.Inventory.item(0)); const newInventorySlots = emptySlots(); for (let i = 1; i < 41; ++i) { @@ -365,13 +363,13 @@ function Ui({disconnected}) { setExternalInventorySlots(); } } - if (localMainEntity === id) { + if (mainEntityRef.current === id) { if (update.Wielder && 'activeSlot' in update.Wielder) { setActiveSlot(update.Wielder.activeSlot); } } } - }, [hotbarHideHandle, mainEntity, setMainEntity]); + }, [hotbarHideHandle, mainEntityRef]); useEcsTick(onEcsTick); const onEcsTickParticles = useCallback((payload, ecs) => { if (!('1' in payload) || particleWorker) { @@ -415,15 +413,15 @@ function Ui({disconnected}) { }, []); useEcsTick(onEcsTickAabbs); const onEcsTickCamera = useCallback((payload, ecs) => { - if (mainEntity) { - const mainEntityEntity = ecs.get(mainEntity); + if (mainEntityRef.current) { + const mainEntityEntity = ecs.get(mainEntityRef.current); const x = Math.round((mainEntityEntity.Camera.x * scale) - RESOLUTION.x / 2); const y = Math.round((mainEntityEntity.Camera.y * scale) - RESOLUTION.y / 2); if (x !== camera.x || y !== camera.y) { setCamera({x, y}); } } - }, [camera, mainEntity, scale]); + }, [camera, mainEntityRef, scale]); useEcsTick(onEcsTickCamera); useEffect(() => { function onContextMenu(event) { @@ -435,15 +433,15 @@ function Ui({disconnected}) { }; }, []); const computePosition = useCallback(({clientX, clientY}) => { - if (!gameRef.current || !mainEntity) { + if (!gameRef.current || !mainEntityRef.current) { return; } const {top, left, width} = gameRef.current.getBoundingClientRect(); - const master = ecs.get(1); + const master = ecsRef.current.get(1); if (!master) { return; } - const {Camera} = ecs.get(mainEntity); + const {Camera} = ecsRef.current.get(mainEntityRef.current); const size = width / RESOLUTION.x; const camera = { x: ((Camera.x * scale) - (RESOLUTION.x / 2)), @@ -454,8 +452,8 @@ function Ui({disconnected}) { y: (((clientY - top) / size) + camera.y) / scale, }; }, [ - ecs, - mainEntity, + ecsRef, + mainEntityRef, scale, ]); return ( @@ -576,7 +574,7 @@ function Ui({disconnected}) { keepHotbarOpen(); client.send({ type: 'Action', - payload: {type: 'swapSlots', value: [0, mainEntity, i + 1]}, + payload: {type: 'swapSlots', value: [0, mainEntityRef.current, i + 1]}, }); }} slots={inventorySlots.slice(0, 10)} @@ -586,7 +584,7 @@ function Ui({disconnected}) { onActivate={(i) => { client.send({ type: 'Action', - payload: {type: 'swapSlots', value: [0, mainEntity, i + 11]}, + payload: {type: 'swapSlots', value: [0, mainEntityRef.current, i + 11]}, }); }} slots={inventorySlots.slice(10, 20)} diff --git a/app/react/context/ecs.js b/app/react/context/ecs.js index 11481c2..fe1dc02 100644 --- a/app/react/context/ecs.js +++ b/app/react/context/ecs.js @@ -11,12 +11,12 @@ export function useEcs() { } export function useEcsTick(fn) { - const [ecs] = useEcs(); + const ecsRef = useEcs(); const memo = useCallback((payload) => { - if (!ecs) { + if (!ecsRef.current) { return; } - fn(payload, ecs); - }, [ecs, fn]); + fn(payload, ecsRef.current); + }, [ecsRef, fn]); usePacket(':Ecs', memo); } \ No newline at end of file diff --git a/app/routes/_main-menu.play.$.$/route.jsx b/app/routes/_main-menu.play.$.$/route.jsx index 9fa1ad9..b1d146d 100644 --- a/app/routes/_main-menu.play.$.$/route.jsx +++ b/app/routes/_main-menu.play.$.$/route.jsx @@ -1,5 +1,5 @@ import {json} from "@remix-run/node"; -import {useCallback, useEffect, useState} from 'react'; +import {useCallback, useEffect, useRef, useState} from 'react'; import {useOutletContext, useParams} from 'react-router-dom'; import Ui from '@/react/components/ui.jsx'; @@ -22,10 +22,9 @@ export default function PlaySpecific() { const Client = useOutletContext(); const assetsTuple = useState({}); const [client, setClient] = useState(); - const mainEntityTuple = useState(); - const setMainEntity = mainEntityTuple[1]; + const mainEntityRef = useRef(); const debugTuple = useState(false); - const ecsTuple = useState(); + const ecsRef = useRef(); const [disconnected, setDisconnected] = useState(false); const params = useParams(); const [type, url] = params['*'].split('/'); @@ -109,7 +108,7 @@ export default function PlaySpecific() { if (!client || !disconnected) { return; } - setMainEntity(undefined); + mainEntityRef.current = undefined; async function reconnect() { await client.connect(url); } @@ -118,7 +117,7 @@ export default function PlaySpecific() { return () => { clearInterval(handle); }; - }, [client, disconnected, setMainEntity, url]); + }, [client, disconnected, mainEntityRef, url]); // useEffect(() => { // let source = true; // async function play() { @@ -144,8 +143,8 @@ export default function PlaySpecific() { // }, []) return ( - - + +