Skip to content

Commit c94e23d

Browse files
committed
Lazy load images to improve startup time
1 parent d22874b commit c94e23d

File tree

6 files changed

+94
-69
lines changed

6 files changed

+94
-69
lines changed

src/lib/canvas/bankImage.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,7 @@ class BankImageTask {
225225
public _bgSpriteData: CanvasImage = new CanvasImage();
226226
public bgSpriteList: Record<string, IBgSprite> = {};
227227
public treeImage!: CanvasImage;
228-
public ready!: Promise<void>;
229-
230-
public constructor() {
231-
this.ready = this.init();
232-
}
228+
public ready: boolean = false;
233229

234230
async init() {
235231
const colors: Record<BGSpriteName, string> = {
@@ -402,6 +398,10 @@ class BankImageTask {
402398
mahojiFlags?: BankFlag[];
403399
} & BaseCanvasArgs
404400
): Promise<BankImageResult> {
401+
if (!this.ready) {
402+
await this.init();
403+
this.ready = true;
404+
}
405405
let { user, collectionLog, title = '', showValue = true } = opts;
406406
const bank = opts.bank.clone();
407407
const flags = new Map(Object.entries(opts.flags ?? {}));

src/lib/canvas/chatHeadImage.ts

Lines changed: 66 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,57 @@
11
import path from 'node:path';
22
import { AttachmentBuilder } from 'discord.js';
3+
import type { Image } from 'skia-canvas';
34

45
import { createCanvas, loadAndCacheLocalImage, printWrappedText } from '@/lib/canvas/canvasUtil.js';
56
import { OSRSCanvas } from '@/lib/canvas/OSRSCanvas.js';
67

7-
const textBoxFile = loadAndCacheLocalImage('./src/lib/resources/images/textbox.png');
8+
type HeadKey =
9+
| 'mejJal'
10+
| 'jane'
11+
| 'santa'
12+
| 'izzy'
13+
| 'alry'
14+
| 'ketKeh'
15+
| 'gertrude'
16+
| 'antiSanta'
17+
| 'bunny'
18+
| 'minimus'
19+
| 'partyPete'
20+
| 'mysteriousFigure'
21+
| 'rudolph'
22+
| 'pumpkin'
23+
| 'marimbo'
24+
| 'spookling'
25+
| 'magnaboy'
26+
| 'wurMuTheMonkey';
827

9-
function loadChImg(fileName: string) {
10-
const basePath = './src/lib/resources/images/chat_heads/';
11-
return loadAndCacheLocalImage(path.join(basePath, fileName));
12-
}
28+
const basePath = './src/lib/resources/images';
29+
const chatBase = `${basePath}/chat_heads`;
1330

14-
const mejJalChatHead = loadChImg('mejJal.png');
15-
const janeChatHead = loadChImg('jane.png');
16-
const santaChatHead = loadChImg('santa.png');
17-
const izzyChatHead = loadChImg('izzy.png');
18-
const alryTheAnglerChatHead = loadChImg('alryTheAngler.png');
19-
const ketKehChatHead = loadChImg('ketKeh.png');
20-
const gertrudeChatHead = loadChImg('gertrude.png');
21-
const antiSantaChatHead = loadChImg('antisanta.png');
22-
const bunnyChatHead = loadChImg('bunny.png');
23-
const minimusHead = loadChImg('minimus.png');
24-
const pumpkinHead = loadChImg('pumpkin.png');
25-
const spookling = loadChImg('spookling.png');
26-
const monkeyChildChatHead = loadChImg('monkeychild.png');
27-
const magnaboyChatHead = loadChImg('magnaboy.png');
28-
const marimboChatHead = loadChImg('marimbo.png');
29-
const partyPeteHead = loadChImg('partyPete.png');
30-
const mysteriousFigureHead = loadChImg('mysteriousFigure.png');
31-
const rudolphChatHead = loadChImg('rudolph.png');
32-
33-
const chatHeads = {
34-
mejJal: mejJalChatHead,
35-
jane: janeChatHead,
36-
santa: santaChatHead,
37-
izzy: izzyChatHead,
38-
alry: alryTheAnglerChatHead,
39-
ketKeh: ketKehChatHead,
40-
gertrude: gertrudeChatHead,
41-
antiSanta: antiSantaChatHead,
42-
bunny: bunnyChatHead,
43-
minimus: minimusHead,
31+
const chatHeadPaths: Record<HeadKey, string> = {
32+
mejJal: 'mejJal.png',
33+
jane: 'jane.png',
34+
santa: 'santa.png',
35+
izzy: 'izzy.png',
36+
alry: 'alryTheAngler.png',
37+
ketKeh: 'ketKeh.png',
38+
gertrude: 'gertrude.png',
39+
antiSanta: 'antisanta.png',
40+
bunny: 'bunny.png',
41+
minimus: 'minimus.png',
4442

4543
// BSO
46-
partyPete: partyPeteHead,
47-
mysteriousFigure: mysteriousFigureHead,
48-
rudolph: rudolphChatHead,
49-
pumpkin: pumpkinHead,
50-
marimbo: marimboChatHead,
51-
spookling: spookling,
52-
magnaboy: magnaboyChatHead,
53-
wurMuTheMonkey: monkeyChildChatHead
44+
partyPete: 'partyPete.png',
45+
mysteriousFigure: 'mysteriousFigure.png',
46+
rudolph: 'rudolph.png',
47+
pumpkin: 'pumpkin.png',
48+
marimbo: 'marimbo.png',
49+
spookling: 'spookling.png',
50+
magnaboy: 'magnaboy.png',
51+
wurMuTheMonkey: 'monkeychild.png'
5452
};
5553

56-
const names: Record<keyof typeof chatHeads, string> = {
54+
const names: Record<HeadKey, string> = {
5755
mejJal: 'TzHaar-Mej-Jal',
5856
jane: 'Guildmaster Jane',
5957
santa: 'Santa',
@@ -76,20 +74,36 @@ const names: Record<keyof typeof chatHeads, string> = {
7674
wurMuTheMonkey: 'Wur Mu the Monkey'
7775
};
7876

79-
export async function newChatHeadImage({ content, head }: { content: string; head: keyof typeof chatHeads }) {
77+
const imagePromiseCache = new Map<string, Promise<Image>>();
78+
79+
const loadOnce = (absPath: string): Promise<any> => {
80+
let p = imagePromiseCache.get(absPath);
81+
if (!p) {
82+
p = loadAndCacheLocalImage(absPath);
83+
imagePromiseCache.set(absPath, p);
84+
}
85+
return p;
86+
};
87+
88+
const getTextbox = () => loadOnce(path.join(basePath, 'textbox.png'));
89+
const getChatHead = (key: HeadKey) => loadOnce(path.join(chatBase, chatHeadPaths[key]));
90+
91+
export async function newChatHeadImage({ content, head }: { content: string; head: HeadKey }) {
8092
const canvas = createCanvas(519, 142);
8193
const ctx = canvas.getContext('2d');
8294
ctx.imageSmoothingEnabled = false;
83-
const headImage = await chatHeads[head];
84-
const bg = await textBoxFile;
95+
96+
const [bg, headImage] = await Promise.all([getTextbox(), getChatHead(head)]);
8597

8698
ctx.drawImage(bg, 0, 0);
8799
ctx.drawImage(headImage, 28, bg.height / 2 - headImage.height / 2);
88100
ctx.font = '16px RuneScape Quill 8';
89101

90102
ctx.fillStyle = '#810303';
91-
const nameWidth = Math.floor(ctx.measureText(names[head]).width);
92-
ctx.fillText(names[head], Math.floor(307 - nameWidth / 2), 36);
103+
const name = names[head];
104+
const nameWidth = Math.floor(ctx.measureText(name).width);
105+
ctx.fillText(name, Math.floor(307 - nameWidth / 2), 36);
106+
93107
ctx.fillStyle = '#000';
94108
printWrappedText(ctx, content, 307, 58, 361);
95109

@@ -108,14 +122,12 @@ export async function newChatHeadImage({ content, head }: { content: string; hea
108122
return scaledCanvas.toBuffer();
109123
}
110124

111-
export default async function chatHeadImage({ content, head }: { content: string; head: keyof typeof chatHeads }) {
125+
export default async function chatHeadImage({ content, head }: { content: string; head: HeadKey }) {
112126
const image = await newChatHeadImage({ content, head });
113127
return new AttachmentBuilder(image);
114128
}
115129

116-
export async function mahojiChatHead({ content, head }: { content: string; head: keyof typeof chatHeads }) {
130+
export async function mahojiChatHead({ content, head }: { content: string; head: HeadKey }) {
117131
const image = await newChatHeadImage({ content, head });
118-
return {
119-
files: [{ attachment: image, name: 'image.jpg' }]
120-
};
132+
return { files: [{ attachment: image, name: 'image.jpg' }] };
121133
}

src/lib/canvas/generateGearImage.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ export async function generateGearImage({
239239
petID?: number | null;
240240
gearTemplate?: number;
241241
} & BaseCanvasArgs) {
242+
if (!bankImageTask.ready) {
243+
await bankImageTask.init();
244+
bankImageTask.ready = true;
245+
}
242246
const {
243247
sprite,
244248
uniqueSprite,

src/lib/canvas/pohImage.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ const FOLDERS = [
4040
class PoHImage {
4141
public imageCache: Map<number, CanvasImage> = new Map();
4242
public bgImages: CanvasImage[] = [];
43-
initPromise: Promise<void> | null = this.init();
44-
initFinished = false;
43+
public ready: boolean = false;
4544

4645
async init() {
4746
this.bgImages.push(await loadAndCacheLocalImage('./src/lib/poh/images/bg_1.jpg'));
@@ -57,7 +56,6 @@ class PoHImage {
5756
this.imageCache.set(id, image);
5857
}
5958
}
60-
this.initFinished = true;
6159
}
6260

6361
generateCanvas(bgId: number): [Canvas, CanvasContext] {
@@ -93,7 +91,10 @@ class PoHImage {
9391
}
9492

9593
async run(poh: PlayerOwnedHouse, showSpaces = true) {
96-
if (!this.initFinished) await this.initPromise;
94+
if (!this.ready) {
95+
await this.init();
96+
this.ready = true;
97+
}
9798
const [canvas, ctx] = this.generateCanvas(poh.background_id);
9899
for (const [key, objects] of objectEntries(Placeholders)) {
99100
if (!key || !objects) continue;

src/mahoji/commands/fake.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { randInt } from '@oldschoolgg/rng';
2+
import type { Image } from 'skia-canvas';
23

34
import {
45
type CanvasContext,
@@ -8,7 +9,7 @@ import {
89
measureTextWidth
910
} from '@/lib/canvas/canvasUtil.js';
1011

11-
const bg = loadAndCacheLocalImage('./src/lib/resources/images/tob-bg.png');
12+
let bg: Image | null = null;
1213

1314
const randomMessages = ['omfgggggg', '!#@$@#$@##@$', 'adfsjklfadkjsl;l', 'l00000l wtf'];
1415

@@ -189,8 +190,10 @@ export const fakeCommand: OSBMahojiCommand = {
189190
ctx.font = '16px OSRSFont';
190191
ctx.fillStyle = '#000000';
191192

192-
const image = await bg;
193-
ctx.drawImage(image, 0, 0, image.width, image.height);
193+
if (!bg) {
194+
bg = await loadAndCacheLocalImage('./src/lib/resources/images/tob-bg.png');
195+
}
196+
ctx.drawImage(bg, 0, 0, bg.width, bg.height);
194197
for (const [names, fn] of thingMap) {
195198
if (names.has(options.type.toLowerCase())) {
196199
fn(ctx, options.username);

src/mahoji/commands/fakepm.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import type { Image } from 'skia-canvas';
2+
13
import { canvasToBuffer, createCanvas, loadAndCacheLocalImage } from '@/lib/canvas/canvasUtil.js';
24

3-
const bg = loadAndCacheLocalImage('./src/lib/resources/images/pm-bg.png');
5+
let bg: Image | null = null;
46

57
export const fakepmCommand: OSBMahojiCommand = {
68
name: 'fakepm',
@@ -23,8 +25,11 @@ export const fakepmCommand: OSBMahojiCommand = {
2325
const canvas = createCanvas(376, 174);
2426
const ctx = canvas.getContext('2d');
2527
ctx.font = '16px OSRSFont';
26-
const img = await bg;
27-
ctx.drawImage(img, 0, 0, img.width, img.height);
28+
29+
if (!bg) {
30+
bg = await loadAndCacheLocalImage('./src/lib/resources/images/pm-bg.png');
31+
}
32+
ctx.drawImage(bg, 0, 0, bg.width, bg.height);
2833

2934
ctx.fillStyle = '#000000';
3035
ctx.fillText(`From ${options.username}: ${options.message}`, 6, 98);

0 commit comments

Comments
 (0)