Skip to content

Commit 8659c79

Browse files
committed
Performance improvements
1 parent b9ca811 commit 8659c79

File tree

4 files changed

+91
-127
lines changed

4 files changed

+91
-127
lines changed

client/Card.tsx

Lines changed: 62 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -144,64 +144,13 @@ export function isCardPropsEqual(a: CardProps, b: CardProps) {
144144
);
145145
}
146146

147-
const CardImpl = React.forwardRef(function CardImpl(props: CardProps, ref: Ref<PixiContainer>) {
148-
const containerRef = useRef() as MutableRefObject<PixiContainer>;
149-
150-
useImperativeHandle(ref, () => containerRef.current);
151-
152-
let text = props.info.text;
153-
let keywords = collapseKeywords(props.info.keywords);
154-
155-
if (keywords.length > 0) {
156-
text = `${keywords.map(getDisplayName).join(", ")}\n${text}`.trim();
157-
}
158-
159-
let propsText: string[] = [];
160-
for (const [name, value] of Object.entries(props.state.props)) {
161-
if (value != undefined) {
162-
const upperName = name.charAt(0).toUpperCase() + name.slice(1);
163-
propsText.push(`${upperName}: ${value.name ?? value}`);
164-
}
165-
}
166-
167-
if (propsText.length > 0) {
168-
text = `${text}\n${propsText.join(", ")}`;
169-
}
170-
171-
return (
172-
<Container ref={containerRef}>
173-
<Text anchor={[0.5, 0]} x={cardWidth / 2 + 20} y={28} text={props.state.name} style={{ fontSize: 32, tint: 0 }} />
174-
<Text
175-
anchor={[0.5, 0]}
176-
x={cardWidth / 2}
177-
y={283}
178-
text={props.info.type.toUpperCase()}
179-
style={{ fontSize: 28, tint: 0 }}
180-
/>
181-
<Text
182-
anchor={[0.5, 0.5]}
183-
x={cardWidth / 2}
184-
y={cardHeight * (3 / 4) + 15}
185-
text={text}
186-
style={{ fontSize: 32, align: "center", maxWidth: cardWidth - 20, letterSpacing: 1 }}
187-
/>
188-
<Text
189-
anchor={[0.5, 0.5]}
190-
x={40}
191-
y={40}
192-
text={Math.max(0, props.info.cost.money)}
193-
style={{ fontSize: 32, tint: 0 }}
194-
/>
195-
<Text
196-
anchor={[0.5, 0.5]}
197-
x={40}
198-
y={92}
199-
text={Math.max(0, props.info.cost.agents) || ""}
200-
style={{ fontSize: 32, tint: 0 }}
201-
/>
202-
</Container>
203-
);
204-
});
147+
const imageTexture = moize((name: string) => {
148+
const imageTexture = Texture.from(`/images/${name}.png`);
149+
imageTexture.baseTexture.mipmap = MIPMAP_MODES.ON;
150+
return imageTexture;
151+
}, {
152+
maxSize: Infinity
153+
})
205154

206155
const getTextures = moize(() => {
207156
const border = Texture.from("/border_base.png");
@@ -258,29 +207,6 @@ export default React.memo(
258207
const glowFilterRef = useRef(new GlowFilter());
259208
const dimFilterRef = useRef(new PixiFilters.ColorMatrixFilter());
260209
const windFilterRef = useRef(new WindFilter());
261-
const [texture, setTexture] = useState(null as RenderTexture | null);
262-
const app = useApp();
263-
264-
function renderTexture() {
265-
if (containerRef.current && texture == null) {
266-
const renderTexture = RenderTexture.create({
267-
width: cardWidth,
268-
height: cardHeight,
269-
});
270-
271-
app.renderer.render(containerRef.current, { renderTexture });
272-
setTexture(renderTexture);
273-
}
274-
}
275-
276-
useEffect(() => {
277-
if (texture != null) {
278-
setTexture(null);
279-
texture.destroy();
280-
}
281-
282-
return () => texture?.destroy();
283-
}, [props.info, props.state]);
284210

285211
useImperativeHandle(ref, () => containerRef.current);
286212

@@ -414,23 +340,6 @@ export default React.memo(
414340
});
415341
}, [props.shouldGlow]);
416342

417-
const info = texture ? (
418-
<Sprite texture={texture} />
419-
) : (
420-
<CardImpl
421-
{...props}
422-
ref={(c) => {
423-
if (c != null) {
424-
containerRef.current = c;
425-
renderTexture();
426-
}
427-
}}
428-
/>
429-
);
430-
431-
const imageTexture = Texture.from(`/images/${props.state.name}.png`);
432-
imageTexture.baseTexture.mipmap = MIPMAP_MODES.ON;
433-
434343
const textures = getTextures();
435344

436345
const levelCosmeticTexture: Texture = {
@@ -445,18 +354,71 @@ export default React.memo(
445354
<Sprite width={cardWidth} height={cardHeight} texture={levelCosmeticTexture} ref={levelCosmeticRef} />
446355
);
447356

357+
let text = props.info.text;
358+
let keywords = collapseKeywords(props.info.keywords);
359+
360+
if (keywords.length > 0) {
361+
text = `${keywords.map(getDisplayName).join(", ")}\n${text}`.trim();
362+
}
363+
364+
let propsText: string[] = [];
365+
for (const [name, value] of Object.entries(props.state.props)) {
366+
if (value != undefined) {
367+
const upperName = name.charAt(0).toUpperCase() + name.slice(1);
368+
propsText.push(`${upperName}: ${value.name ?? value}`);
369+
}
370+
}
371+
372+
if (propsText.length > 0) {
373+
text = `${text}\n${propsText.join(", ")}`;
374+
}
375+
448376
return (
449377
<Container pivot={[cardWidth / 2, cardHeight / 2]} filters={[dimFilterRef.current, glowFilterRef.current]}>
450378
<Rectangle fill={0xffffff} width={cardWidth - 20} height={cardHeight - 40} x={10} y={14} ref={colorRef} />
451-
<Sprite width={cardWidth - 55} height={cardHeight / 2 - 40} x={30} y={60} texture={imageTexture} />
379+
<Sprite width={cardWidth - 55} height={cardHeight / 2 - 40} x={30} y={60} texture={imageTexture(props.state.name)} />
452380
<Sprite width={cardWidth} height={cardHeight} texture={textures.border} />
453381
<Sprite width={cardWidth} height={cardHeight} texture={textures.borderType} ref={borderTypeRef} />
454382
<Container filters={props.cosmetic?.top ? [windFilterRef.current] : []}>
455383
<Sprite width={cardWidth} height={cardHeight} texture={textures.borderBanner} ref={borderBannerRef} />
456384
<Sprite width={cardWidth} height={cardHeight} texture={textures.borderCost} ref={borderCostRef} />
457385
<Sprite width={cardWidth} height={cardHeight} texture={textures.borderAgents} ref={borderAgentsRef} />
458386
<Sprite width={cardWidth} height={cardHeight} texture={textures.borderTint} ref={borderTintRef} />
459-
{info}
387+
<Text
388+
anchor={[0.5, 0]}
389+
x={cardWidth / 2 + 20}
390+
y={28}
391+
text={props.state.name}
392+
style={{ fontSize: 32, tint: 0 }}
393+
/>
394+
<Text
395+
anchor={[0.5, 0]}
396+
x={cardWidth / 2}
397+
y={283}
398+
text={props.info.type.toUpperCase()}
399+
style={{ fontSize: 28, tint: 0 }}
400+
/>
401+
<Text
402+
anchor={[0.5, 0.5]}
403+
x={cardWidth / 2}
404+
y={cardHeight * (3 / 4) + 15}
405+
text={text}
406+
style={{ fontSize: 32, align: "center", maxWidth: cardWidth - 20, letterSpacing: 1 }}
407+
/>
408+
<Text
409+
anchor={[0.5, 0.5]}
410+
x={40}
411+
y={40}
412+
text={Math.max(0, props.info.cost.money)}
413+
style={{ fontSize: 32, tint: 0 }}
414+
/>
415+
<Text
416+
anchor={[0.5, 0.5]}
417+
x={40}
418+
y={92}
419+
text={Math.max(0, props.info.cost.agents) || ""}
420+
style={{ fontSize: 32, tint: 0 }}
421+
/>
460422
</Container>
461423
{levelCosmetic}
462424
</Container>

client/game/EndTurn.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
1-
import React, { useContext } from "react";
21
import { Container } from "@pixi/react";
3-
import Text from "../Text.js";
4-
import Rectangle from "../Rectangle.js";
2+
import React, { useCallback, useContext } from "react";
53
import { targetResolution } from "../Camera.js";
4+
import Rectangle from "../Rectangle.js";
5+
import Text from "../Text.js";
66
import { ConnectionContext, PlanContext } from "./Game.js";
77

88
export default function EndTurn() {
99
const connection = useContext(ConnectionContext);
10-
const { plan, setPlan } = useContext(PlanContext);
10+
const { plan } = useContext(PlanContext);
1111

1212
const width = 400;
1313
const height = 100;
1414
const x = targetResolution.width - width;
1515
const y = (targetResolution.height - height) / 2;
1616

17-
function pointerdown() {
17+
const pointerdown = useCallback(() => {
1818
connection.plan(plan);
19-
setPlan([]);
20-
}
19+
}, [connection, plan]);
2120

2221
return (
2322
<Container x={x} y={y} eventMode="static" pointerdown={pointerdown}>

client/game/Game.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ export default function Game(props: { message: string }) {
5555
const cards = useRef({} as { [id: string]: CardAnimationState });
5656
const timeColorFilterRef = useTimeColorFilter();
5757
const [highlight, setHighlight] = useState([] as Target[]);
58-
const [plan, setPlan] = useState([] as PlanProps[]);
5958

6059
useEffect(() => {
6160
cache.current.reset();
@@ -66,23 +65,21 @@ export default function Game(props: { message: string }) {
6665
<CacheContext.Provider value={cache.current}>
6766
<CardAnimationContext.Provider value={cards}>
6867
<HighlightContext.Provider value={{ highlight, setHighlight }}>
69-
<PlanContext.Provider value={{ plan, setPlan }}>
70-
<Container filters={[timeColorFilterRef.current]} sortableChildren>
71-
<Table />
72-
<OpponentBoard />
73-
<Board />
74-
<EndTurn />
75-
<OpponentGrave />
76-
<Grave />
77-
<Plan />
78-
<OpponentHand />
79-
<Resources />
80-
<Concede />
81-
<HandAndDeck />
82-
<Explanations />
83-
<Message text={props.message} />
84-
</Container>
85-
</PlanContext.Provider>
68+
<Container filters={[timeColorFilterRef.current]} sortableChildren>
69+
<Table />
70+
<OpponentBoard />
71+
<Board />
72+
<EndTurn />
73+
<OpponentGrave />
74+
<Grave />
75+
<Plan />
76+
<OpponentHand />
77+
<Resources />
78+
<Concede />
79+
<HandAndDeck />
80+
<Explanations />
81+
<Message text={props.message} />
82+
</Container>
8683
</HighlightContext.Provider>
8784
</CardAnimationContext.Provider>
8885
</CacheContext.Provider>

client/queue/Queue.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import { NoirClientSocket, QueueName } from "../../common/network.js";
66
import Button from "../Button.js";
77
import { targetResolution } from "../Camera.js";
88
import { loadCardsFromAction, serverOrigin, trpc } from "../cards.js";
9-
import Game, { ConnectionContext, CosmeticContext, PlayerContext } from "../game/Game.js";
9+
import Game, { ConnectionContext, CosmeticContext, PlanContext, PlayerContext } from "../game/Game.js";
1010
import { getUsername, useClientDispatch, useClientSelector } from "../store.js";
1111
import { setWon } from "../wins.js";
1212
import { CardCosmetic } from "../../common/card.js";
1313
import { batch } from "react-redux";
14+
import { PlanProps } from "../../common/util.js";
1415

1516
export default function Queue(props: { params: { queue: string; deck?: string } }) {
1617
let [player, setPlayer] = useState(null as PlayerId | null);
@@ -21,6 +22,7 @@ export default function Queue(props: { params: { queue: string; deck?: string }
2122
const [message, setMessage] = useState("");
2223
const [_, setLocation] = useLocation();
2324
const dispatch = useClientDispatch();
25+
const [plan, setPlan] = useState([] as PlanProps[]);
2426

2527
useEffect(() => {
2628
const socket: NoirClientSocket = io(serverOrigin);
@@ -35,6 +37,8 @@ export default function Queue(props: { params: { queue: string; deck?: string }
3537
for (const action of actions) {
3638
dispatch(action);
3739
}
40+
41+
setPlan([]);
3842
});
3943
})();
4044
});
@@ -114,7 +118,9 @@ export default function Queue(props: { params: { queue: string; deck?: string }
114118
>
115119
<PlayerContext.Provider value={player}>
116120
<CosmeticContext.Provider value={cosmetics}>
117-
<Game message={message} />
121+
<PlanContext.Provider value={{ plan, setPlan }}>
122+
<Game message={message} />
123+
</PlanContext.Provider>
118124
</CosmeticContext.Provider>
119125
</PlayerContext.Provider>
120126
</ConnectionContext.Provider>

0 commit comments

Comments
 (0)