perf: updates

This commit is contained in:
cha0s 2024-09-22 02:16:32 -05:00
parent 5492ec32bd
commit 73b7a9e0a5
6 changed files with 63 additions and 50 deletions

View File

@ -2,6 +2,7 @@ import {useCallback, useState} from 'react';
import {usePacket} from '@/react/context/client.js'; import {usePacket} from '@/react/context/client.js';
import {useEcsTick} from '@/react/context/ecs.js'; import {useEcsTick} from '@/react/context/ecs.js';
import {RESOLUTION} from '@/util/constants.js';
import {parseLetters} from '@/util/dialogue.js'; import {parseLetters} from '@/util/dialogue.js';
import Damages from './damages.jsx'; import Damages from './damages.jsx';
@ -14,6 +15,10 @@ export default function Entities({
setChatMessages, setChatMessages,
}) { }) {
const [entities, setEntities] = useState({}); const [entities, setEntities] = useState({});
const translatedCamera = {
x: Math.round((camera.x * scale) - RESOLUTION.x / 2),
y: Math.round((camera.y * scale) - RESOLUTION.y / 2),
};
usePacket('EcsChange', async () => { usePacket('EcsChange', async () => {
setEntities({}); setEntities({});
}); });
@ -98,7 +103,7 @@ export default function Entities({
for (const id in entities) { for (const id in entities) {
renderables.push( renderables.push(
<Entity <Entity
camera={camera} camera={translatedCamera}
entity={entities[id]} entity={entities[id]}
key={id} key={id}
scale={scale} scale={scale}
@ -109,8 +114,8 @@ export default function Entities({
<div <div
style={{ style={{
translate: ` translate: `
calc(-1px * ${camera.x}) calc(-1px * ${translatedCamera.x})
calc(-1px * ${camera.y}) calc(-1px * ${translatedCamera.y})
`, `,
}} }}
> >

View File

@ -10,7 +10,7 @@ import TargetingGrid from './targeting-grid.jsx';
import TileLayer from './tile-layer.jsx'; import TileLayer from './tile-layer.jsx';
import Water from './water.jsx'; import Water from './water.jsx';
export default function Ecs({camera, monopolizers, particleWorker, scale}) { export default function Ecs({monopolizers, particleWorker}) {
const app = useApp(); const app = useApp();
const mainEntityRef = useMainEntity(); const mainEntityRef = useMainEntity();
const [layers, setLayers] = useState([]); const [layers, setLayers] = useState([]);
@ -120,17 +120,22 @@ export default function Ecs({camera, monopolizers, particleWorker, scale}) {
} }
if (entity) { if (entity) {
const {Direction, Position, Wielder} = entity; const {Direction, Position, Wielder} = entity;
setPosition(Position.toJSON()); setPosition((position) => {
setProjected(Wielder.activeItem()?.project(Position.tile, Direction.quantize(4))); return position.x !== Position.x || position.y !== Position.y
? Position.toJSON()
: position;
});
setProjected((projected) => {
const newProjected = Wielder.activeItem()?.project(Position.tile, Direction.quantize(4));
return JSON.stringify(projected) !== JSON.stringify(newProjected)
? newProjected
: projected;
});
} }
}, [app.ambientLight, mainEntityRef]); }, [app.ambientLight, mainEntityRef]);
useEcsTick(onEcsTick); useEcsTick(onEcsTick);
return ( return (
<Container <>
scale={scale}
x={-camera.x}
y={-camera.y}
>
<Container> <Container>
{layers.map((layer, i) => ( {layers.map((layer, i) => (
<TileLayer <TileLayer
@ -162,6 +167,6 @@ export default function Ecs({camera, monopolizers, particleWorker, scale}) {
monopolizers={monopolizers} monopolizers={monopolizers}
particleWorker={particleWorker} particleWorker={particleWorker}
/> />
</Container> </>
) )
} }

View File

@ -1,14 +1,13 @@
import {SCALE_MODES} from '@pixi/constants'; import {SCALE_MODES} from '@pixi/constants';
import {BaseTexture, extensions} from '@pixi/core'; import {BaseTexture, extensions} from '@pixi/core';
import {Stage as PixiStage} from '@pixi/react'; import {Container, Stage as PixiStage} from '@pixi/react';
import {createElement, useContext} from 'react'; import {createElement, forwardRef, memo, useContext} from 'react';
import AssetsContext from '@/react/context/assets.js'; import AssetsContext from '@/react/context/assets.js';
import ClientContext from '@/react/context/client.js'; import ClientContext from '@/react/context/client.js';
import DebugContext from '@/react/context/debug.js'; import DebugContext from '@/react/context/debug.js';
import EcsContext from '@/react/context/ecs.js'; import EcsContext from '@/react/context/ecs.js';
import MainEntityContext from '@/react/context/main-entity.js'; import MainEntityContext from '@/react/context/main-entity.js';
import RadiansContext from '@/react/context/radians.js';
import {RESOLUTION} from '@/util/constants.js'; import {RESOLUTION} from '@/util/constants.js';
import Ecs from './ecs.jsx'; import Ecs from './ecs.jsx';
@ -28,7 +27,6 @@ const Contexts = [
DebugContext, DebugContext,
EcsContext, EcsContext,
MainEntityContext, MainEntityContext,
RadiansContext,
]; ];
const ContextBridge = ({children, render}) => { const ContextBridge = ({children, render}) => {
@ -57,7 +55,7 @@ export const Stage = ({children, ...props}) => {
); );
}; };
export default function Pixi({camera, monopolizers, particleWorker, scale}) { function Pixi({monopolizers, particleWorker}, ref) {
return ( return (
<Stage <Stage
className={styles.stage} className={styles.stage}
@ -67,13 +65,16 @@ export default function Pixi({camera, monopolizers, particleWorker, scale}) {
background: 0x0, background: 0x0,
}} }}
> >
<Ecs <Container
camera={camera} ref={ref}
monopolizers={monopolizers} >
particleWorker={particleWorker} <Ecs
scale={scale} monopolizers={monopolizers}
/> particleWorker={particleWorker}
/>
</Container>
</Stage> </Stage>
); );
} }
export default memo(forwardRef(Pixi));

View File

@ -36,6 +36,7 @@ function Ui({disconnected}) {
const chatInputRef = useRef(); const chatInputRef = useRef();
const latestTick = useRef(); const latestTick = useRef();
const gameRef = useRef(); const gameRef = useRef();
const pixiRef = useRef();
const mainEntityRef = useMainEntity(); const mainEntityRef = useMainEntity();
const [, setDebug] = useDebug(); const [, setDebug] = useDebug();
const ecsRef = useEcs(); const ecsRef = useEcs();
@ -326,16 +327,15 @@ function Ui({disconnected}) {
} }
}, []); }, []);
useEcsTick(onEcsTickAabbs); useEcsTick(onEcsTickAabbs);
const onEcsTickCamera = useCallback((payload, ecs) => { const onEcsTickCamera = useCallback((payload) => {
if (mainEntityRef.current) { if (mainEntityRef.current && payload[mainEntityRef.current]?.Camera) {
const mainEntityEntity = ecs.get(mainEntityRef.current); setCamera((camera) => ({
const x = Math.round((mainEntityEntity.Camera.x * scale) - RESOLUTION.x / 2); x: camera.x,
const y = Math.round((mainEntityEntity.Camera.y * scale) - RESOLUTION.y / 2); y: camera.y,
if (x !== camera.x || y !== camera.y) { ...payload[mainEntityRef.current].Camera,
setCamera({x, y}); }))
}
} }
}, [camera, mainEntityRef, scale]); }, [mainEntityRef]);
useEcsTick(onEcsTickCamera); useEcsTick(onEcsTickCamera);
useEffect(() => { useEffect(() => {
function onContextMenu(event) { function onContextMenu(event) {
@ -389,6 +389,14 @@ function Ui({disconnected}) {
payload: {type: 'swapSlots', value: [0, externalInventory, i]}, payload: {type: 'swapSlots', value: [0, externalInventory, i]},
}); });
}, [client, externalInventory]); }, [client, externalInventory]);
useEffect(() => {
if (!pixiRef.current) {
return;
}
pixiRef.current.scale.set(scale);
pixiRef.current.x = -Math.round((camera.x * scale) - RESOLUTION.x / 2);
pixiRef.current.y = -Math.round((camera.y * scale) - RESOLUTION.y / 2);
}, [camera, scale])
return ( return (
<div <div
className={styles.ui} className={styles.ui}
@ -494,10 +502,9 @@ function Ui({disconnected}) {
ref={gameRef} ref={gameRef}
> >
<Pixi <Pixi
camera={camera}
monopolizers={monopolizers.current} monopolizers={monopolizers.current}
particleWorker={particleWorker} particleWorker={particleWorker}
scale={scale} ref={pixiRef}
/> />
<Dom> <Dom>
<HotBar <HotBar

View File

@ -1,9 +1,14 @@
import {createContext, useContext} from 'react'; import {useCallback, useState} from 'react';
const context = createContext(); import useAnimationFrame from '@/react/hooks/use-animation-frame.js';
import {TAU} from '@/util/math.js';
export default context;
export function useRadians() { export function useRadians() {
return useContext(context); const [radians, setRadians] = useState(0);
useAnimationFrame(
useCallback((elapsed) => {
setRadians((radians) => radians + (elapsed * TAU));
}, []),
);
return radians;
} }

View File

@ -7,9 +7,6 @@ import ClientContext from '@/react/context/client.js';
import DebugContext from '@/react/context/debug.js'; import DebugContext from '@/react/context/debug.js';
import EcsContext from '@/react/context/ecs.js'; import EcsContext from '@/react/context/ecs.js';
import MainEntityContext from '@/react/context/main-entity.js'; import MainEntityContext from '@/react/context/main-entity.js';
import RadiansContext from '@/react/context/radians.js';
import useAnimationFrame from '@/react/hooks/use-animation-frame.js';
import {TAU} from '@/util/math.js';
import ClientEcs from '@/react/components/client-ecs.js'; import ClientEcs from '@/react/components/client-ecs.js';
@ -25,11 +22,6 @@ export default function PlaySpecific() {
const [disconnected, setDisconnected] = useState(false); const [disconnected, setDisconnected] = useState(false);
const params = useParams(); const params = useParams();
const [type, url] = params['*'].split('/'); const [type, url] = params['*'].split('/');
const [radians, setRadians] = useState(0);
const spin = useCallback((elapsed) => {
setRadians((radians) => radians + (elapsed * TAU));
}, []);
useAnimationFrame(spin);
useEffect(() => { useEffect(() => {
if (!Client) { if (!Client) {
return; return;
@ -174,9 +166,7 @@ export default function PlaySpecific() {
<EcsContext.Provider value={ecsRef}> <EcsContext.Provider value={ecsRef}>
<DebugContext.Provider value={debugTuple}> <DebugContext.Provider value={debugTuple}>
<AssetsContext.Provider value={assetsTuple}> <AssetsContext.Provider value={assetsTuple}>
<RadiansContext.Provider value={radians}> <Ui disconnected={disconnected} />
<Ui disconnected={disconnected} />
</RadiansContext.Provider>
</AssetsContext.Provider> </AssetsContext.Provider>
</DebugContext.Provider> </DebugContext.Provider>
</EcsContext.Provider> </EcsContext.Provider>