Throttle loading of player images to improve performance

This commit is contained in:
James Lyne 2021-01-26 21:07:56 +00:00
parent df487ec364
commit 21220c986a

View File

@ -17,8 +17,18 @@
import {DynmapPlayer} from "@/dynmap"; import {DynmapPlayer} from "@/dynmap";
import {useStore} from "@/store"; import {useStore} from "@/store";
interface HeadQueueEntry {
cacheKey: string;
account: string;
size: string;
image: HTMLImageElement;
}
const headCache = new Map<string, HTMLImageElement>(), const headCache = new Map<string, HTMLImageElement>(),
headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>(); headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>(),
headsLoading = new Set<string>(),
headQueue: HeadQueueEntry[] = [];
export const getMinecraftTime = (serverTime: number) => { export const getMinecraftTime = (serverTime: number) => {
const day = serverTime >= 0 && serverTime < 13700; const day = serverTime >= 0 && serverTime < 13700;
@ -54,23 +64,46 @@ export const getMinecraftHead = (player: DynmapPlayer | string, size: string): P
faceImage.onload = function() { faceImage.onload = function() {
headCache.set(cacheKey, faceImage); headCache.set(cacheKey, faceImage);
headsLoading.delete(cacheKey);
tickHeadQueue();
resolve(faceImage); resolve(faceImage);
}; };
faceImage.onerror = function(e) { faceImage.onerror = function(e) {
console.warn(`Failed to retrieve face of ${account} with size ${size}!`); console.warn(`Failed to retrieve face of ${account} with size ${size}!`);
headsLoading.delete(cacheKey);
tickHeadQueue();
reject(e); reject(e);
}; };
const src = (size === 'body') ? `faces/body/${account}.png` :`faces/${size}x${size}/${account}.png`; headQueue.push({
faceImage.src = concatURL(window.config.url.markers, src); account,
size,
cacheKey,
image: faceImage,
});
}).finally(() => headUnresolvedCache.delete(cacheKey)) as Promise<HTMLImageElement>; }).finally(() => headUnresolvedCache.delete(cacheKey)) as Promise<HTMLImageElement>;
headUnresolvedCache.set(cacheKey, promise); headUnresolvedCache.set(cacheKey, promise);
tickHeadQueue();
return promise; return promise;
} }
const tickHeadQueue = () => {
if(headsLoading.size > 8 || !headQueue.length) {
return;
}
const head = headQueue.pop() as HeadQueueEntry,
src = (head.size === 'body') ? `faces/body/${head.account}.png` :`faces/${head.size}x${head.size}/${head.account}.png`;
headsLoading.add(head.cacheKey);
head.image.src = concatURL(window.config.url.markers, src);
tickHeadQueue();
}
export const concatURL = (base: string, addition: string) => { export const concatURL = (base: string, addition: string) => {
if(base.indexOf('?') >= 0) { if(base.indexOf('?') >= 0) {
return base + escape(addition); return base + escape(addition);