CardCreator reworked init to load everything in parallel

This commit is contained in:
Carlo Morgenstern 2021-10-24 18:43:23 +02:00
parent efde0b5ecd
commit aa036b169e

View file

@ -144,86 +144,63 @@ class CardCreator {
*/
async ensureInit() {
if (this.initPromise == null) this.initPromise = this.init();
await this.initPromise;
}
async init() {
this.bgImage = await loadImage(absolute('./resources/background.png'));
const commonImagesPromise = Promise.all([
loadImage(absolute('./resources/background.png')),
loadImage(absolute('./resources/minion.png')),
loadImage(absolute('./resources/mount.png')),
loadImage(absolute('./resources/ilvl-icon.png')),
loadImage(absolute('./resources/shadow.png')),
]).then(([background, minion, mount, ilvl, shadow]) => {
this.images = {
background, minion, mount, ilvl, shadow,
};
});
this.imgMinion = await loadImage(absolute('./resources/minion.png'));
this.imgMount = await loadImage(absolute('./resources/mount.png'));
this.imgIlvl = await loadImage(absolute('./resources/ilvl-icon.png'));
this.imgShadow = await loadImage(absolute('./resources/shadow.png'));
const classJobs = [
'alchemist', 'armorer', 'blacksmith', 'carpenter', 'culinarian', 'goldsmith', 'leatherworker', 'weaver',
'botanist', 'fisher', 'miner',
'gladiator', 'paladin', 'marauder', 'warrior', 'darkknight', 'gunbreaker',
'conjurer', 'whitemage', 'scholar', 'astrologian',
'archer', 'bard', 'machinist', 'dancer',
'lancer', 'dragoon', 'pugilist', 'monk', 'rogue', 'ninja', 'samurai',
'thaumaturge', 'blackmage', 'arcanist', 'summoner', 'redmage',
'bluemage',
];
this.imgAlchemist = await loadImage(absolute('./resources/class-jobs-icons/alchemist.png'));
this.imgArmorer = await loadImage(absolute('./resources/class-jobs-icons/armorer.png'));
this.imgBlacksmith = await loadImage(absolute('./resources/class-jobs-icons/blacksmith.png'));
this.imgCarpenter = await loadImage(absolute('./resources/class-jobs-icons/carpenter.png'));
this.imgCulinarian = await loadImage(absolute('./resources/class-jobs-icons/culinarian.png'));
this.imgGoldsmith = await loadImage(absolute('./resources/class-jobs-icons/goldsmith.png'));
this.imgLeatherworker = await loadImage(absolute('./resources/class-jobs-icons/leatherworker.png'));
this.imgWeaver = await loadImage(absolute('./resources/class-jobs-icons/weaver.png'));
const classJobIconsPromise = Promise.all(
classJobs.map(name => loadImage(absolute(`./resources/class-jobs-icons/${name}.png`)))
).then(images => {
this.cjIcons = {};
images.forEach((image, index) => this.cjIcons[classJobs[index]] = image);
});
this.imgBotanist = await loadImage(absolute('./resources/class-jobs-icons/botanist.png'));
this.imgFisher = await loadImage(absolute('./resources/class-jobs-icons/fisher.png'));
this.imgMiner = await loadImage(absolute('./resources/class-jobs-icons/miner.png'));
const jobBackgroundsPromise = Promise.all(
Array.from({ length: 38 }, (_, index) => loadImage(absolute(`./resources/class-jobs-backgrounds/${index + 1}.png`)))
).then(images => this.jobBackgrounds = images);
this.imgGladiator = await loadImage(absolute('./resources/class-jobs-icons/gladiator.png'));
this.imgPaladin = await loadImage(absolute('./resources/class-jobs-icons/paladin.png'));
this.imgMarauder = await loadImage(absolute('./resources/class-jobs-icons/marauder.png'));
this.imgWarrior = await loadImage(absolute('./resources/class-jobs-icons/warrior.png'));
this.imgDarkKnight = await loadImage(absolute('./resources/class-jobs-icons/darkknight.png'));
this.imgGunbreaker = await loadImage(absolute('./resources/class-jobs-icons/gunbreaker.png'));
const ilevelFilterPromise = createIlvlFilter(this.xivApiKey).then(filterIds => this.ilvlFilterIds = filterIds);
this.imgConjurer = await loadImage(absolute('./resources/class-jobs-icons/conjurer.png'));
this.imgWhitemage = await loadImage(absolute('./resources/class-jobs-icons/whitemage.png'));
this.imgScholar = await loadImage(absolute('./resources/class-jobs-icons/scholar.png'));
this.imgAstrologian = await loadImage(absolute('./resources/class-jobs-icons/astrologian.png'));
const minionCountPromise = fetch(`https://ffxivcollect.com/api/minions/`)
.then(response => response.json())
.then(data => this.minionCount = data.count);
this.imgArcher = await loadImage(absolute('./resources/class-jobs-icons/archer.png'));
this.imgBard = await loadImage(absolute('./resources/class-jobs-icons/bard.png'));
this.imgMachinist = await loadImage(absolute('./resources/class-jobs-icons/machinist.png'));
this.imgDancer = await loadImage(absolute('./resources/class-jobs-icons/dancer.png'));
const mountCountPromise = fetch(`https://ffxivcollect.com/api/mounts/`)
.then(response => response.json())
.then(data => this.mountCount = data.count);
this.imgLancer = await loadImage(absolute('./resources/class-jobs-icons/lancer.png'));
this.imgDragoon = await loadImage(absolute('./resources/class-jobs-icons/dragoon.png'));
this.imgPugilist = await loadImage(absolute('./resources/class-jobs-icons/pugilist.png'));
this.imgMonk = await loadImage(absolute('./resources/class-jobs-icons/monk.png'));
this.imgRogue = await loadImage(absolute('./resources/class-jobs-icons/rogue.png'));
this.imgNinja = await loadImage(absolute('./resources/class-jobs-icons/ninja.png'));
this.imgSamurai = await loadImage(absolute('./resources/class-jobs-icons/samurai.png'));
this.imgThaumaturge = await loadImage(absolute('./resources/class-jobs-icons/thaumaturge.png'));
this.imgBlackmage = await loadImage(absolute('./resources/class-jobs-icons/blackmage.png'));
this.imgArcanist = await loadImage(absolute('./resources/class-jobs-icons/arcanist.png'));
this.imgSummoner = await loadImage(absolute('./resources/class-jobs-icons/summoner.png'));
this.imgRedmage = await loadImage(absolute('./resources/class-jobs-icons/redmage.png'));
this.imgBluemage = await loadImage(absolute('./resources/class-jobs-icons/bluemage.png'));
this.imgJobBg = {};
for (let i = 1; i <= 38; i++) {
this.imgJobBg[i] = await loadImage(absolute(`./resources/class-jobs-backgrounds/${i}.png`));
}
this.ilvlFilterIds = await createIlvlFilter(this.xivApiKey);
await this.countMountsMinions();
}
async countMountsMinions() {
const minionResponse = await fetch(`https://ffxivcollect.com/api/minions/`);
const minionData = await minionResponse.json();
this.countMinion = minionData.count;
const mountResponse = await fetch(`https://ffxivcollect.com/api/mounts/`);
const mountData = await mountResponse.json();
this.countMount = mountData.count;
console.log(`Refreshed counts: ${this.countMinion} - ${this.countMount}`);
await Promise.all([
commonImagesPromise,
classJobIconsPromise,
jobBackgroundsPromise,
ilevelFilterPromise,
minionCountPromise,
mountCountPromise,
]);
}
async createCrest(crestAry) {
@ -347,7 +324,7 @@ class CardCreator {
const portrait = await loadImage(data.Character.Portrait);
ctx.drawImage(this.bgImage, 0, 0, canvasSize.width, canvasSize.height + 2);
ctx.drawImage(this.images.background, 0, 0, canvasSize.width, canvasSize.height + 2);
ctx.drawImage(portrait, 0, 120, 441, 600);
@ -365,9 +342,9 @@ class CardCreator {
// BLU returns a null UnlockedState.ID so we can't use it to pick the job image.
if (data.Character.ActiveClassJob.UnlockedState.ID != null) {
ctx.drawImage(this.imgJobBg[data.Character.ActiveClassJob.UnlockedState.ID], 450, 4, rectFullWidth, 110);
ctx.drawImage(this.jobBackgrounds[data.Character.ActiveClassJob.UnlockedState.ID], 450, 4, rectFullWidth, 110);
} else {
ctx.drawImage(this.imgJobBg[36], 450, 4, rectFullWidth, 110);
ctx.drawImage(this.jobBackgrounds[36], 450, 4, rectFullWidth, 110);
}
ctx.fillRect(rectStartX, rectStartRow2Y, rectHalfWidth, rectHeightRow2);
@ -407,8 +384,8 @@ class CardCreator {
ctx.font = smed;
const ilvl = this.getItemLevel(data.Character.GearSet.Gear);
ctx.drawImage(this.imgShadow, 441 - 143, 110, 170, 90);
ctx.drawImage(this.imgIlvl, 441 - 92, 132, 24, 27);
ctx.drawImage(this.images.shadow, 441 - 143, 110, 170, 90);
ctx.drawImage(this.images.ilvl, 441 - 92, 132, 24, 27);
ctx.fillText(ilvl, 441 - 65, 155);
ctx.fillStyle = white;
@ -470,12 +447,12 @@ class CardCreator {
// Minion & Mount percentages
let mountsPct = '0';
if (data.Mounts !== null) {
mountsPct = Math.ceil((data.Mounts.length / this.countMount) * 100);
mountsPct = Math.ceil((data.Mounts.length / this.mountCount) * 100);
}
let minionsPct = '0';
if (data.Minions !== null) {
minionsPct = Math.ceil((data.Minions.length / this.countMinion) * 100);
minionsPct = Math.ceil((data.Minions.length / this.minionCount) * 100);
}
const mountsMeasure = ctx.measureText(`${mountsPct}%`);
@ -490,8 +467,8 @@ class CardCreator {
ctx.fillText(strings.mounts, 480 + mountsMeasure.width + 5, textMountMinionY);
ctx.fillText(strings.minions, 685 + minionsMeasure.width + 5, textMountMinionY);
ctx.drawImage(this.imgMount, 620, iconMountMinionY, 32, 32);
ctx.drawImage(this.imgMinion, 834, iconMountMinionY, 19, 32);
ctx.drawImage(this.images.mount, 620, iconMountMinionY, 32, 32);
ctx.drawImage(this.images.minion, 834, iconMountMinionY, 19, 32);
ctx.fillStyle = white;
@ -501,48 +478,48 @@ class CardCreator {
ctx.textAlign = 'center';
let cJobsRowTextX = jobsRowTextStartX;
ctx.drawImage(this.imgAlchemist, 480, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.alchemist, 480, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[24].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgArmorer, 510, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.armorer, 510, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[20].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgBlacksmith, 540, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.blacksmith, 540, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[19].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgCarpenter, 570, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.carpenter, 570, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[18].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgCulinarian, 600, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.culinarian, 600, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[25].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgGoldsmith, 630, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.goldsmith, 630, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[21].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgLeatherworker, 660, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.leatherworker, 660, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[22].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgWeaver, 690, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.weaver, 690, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[23].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSpacer;
// Gathering
ctx.drawImage(this.imgBotanist, 750, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.botanist, 750, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[27].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgFisher, 780, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.fisher, 780, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[28].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgMiner, 810, jobsRowIcon3Y, 30, 30);
ctx.drawImage(this.cjIcons.miner, 810, jobsRowIcon3Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[26].Level, cJobsRowTextX, jobsRowText3Y);
cJobsRowTextX += jobsRowTextSize;
@ -550,39 +527,39 @@ class CardCreator {
cJobsRowTextX = jobsRowTextStartX;
if (data.Character.ClassJobs[0].UnlockedState.ID == 19) {
ctx.drawImage(this.imgPaladin, 480, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.paladin, 480, jobsRowIcon1Y, 30, 30);
} else {
ctx.drawImage(this.imgGladiator, 480, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.gladiator, 480, jobsRowIcon1Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[0].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
if (data.Character.ClassJobs[1].UnlockedState.ID == 21) {
ctx.drawImage(this.imgWarrior, 510, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.warrior, 510, jobsRowIcon1Y, 30, 30);
} else {
ctx.drawImage(this.imgMarauder, 510, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.marauder, 510, jobsRowIcon1Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[1].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgDarkKnight, 540, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.darkknight, 540, jobsRowIcon1Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[2].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgGunbreaker, 570, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.gunbreaker, 570, jobsRowIcon1Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[3].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSpacer;
// Healers
if (data.Character.ClassJobs[8].UnlockedState.ID == 24) {
ctx.drawImage(this.imgWhitemage, 630, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.whitemage, 630, jobsRowIcon1Y, 30, 30);
} else {
ctx.drawImage(this.imgConjurer, 630, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.conjurer, 630, jobsRowIcon1Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[8].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgScholar, 660, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.scholar, 660, jobsRowIcon1Y, 30, 30);
if (data.Character.ClassJobs[9].Level >= 30) {
ctx.fillText(data.Character.ClassJobs[9].Level, cJobsRowTextX, jobsRowText1Y);
} else {
@ -590,25 +567,25 @@ class CardCreator {
}
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgAstrologian, 690, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.astrologian, 690, jobsRowIcon1Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[10].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSpacer;
// DPS
// Ranged
if (data.Character.ClassJobs[11].UnlockedState.ID == 23) {
ctx.drawImage(this.imgBard, 750, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.bard, 750, jobsRowIcon1Y, 30, 30);
} else {
ctx.drawImage(this.imgArcher, 750, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.archer, 750, jobsRowIcon1Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[11].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgMachinist, 780, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.machinist, 780, jobsRowIcon1Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[12].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgDancer, 810, jobsRowIcon1Y, 30, 30);
ctx.drawImage(this.cjIcons.dancer, 810, jobsRowIcon1Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[13].Level, cJobsRowTextX, jobsRowText1Y);
cJobsRowTextX += jobsRowTextSize;
@ -616,56 +593,56 @@ class CardCreator {
cJobsRowTextX = jobsRowTextStartX;
if (data.Character.ClassJobs[5].UnlockedState.ID == 22) {
ctx.drawImage(this.imgDragoon, 480, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.dragoon, 480, jobsRowIcon2Y, 30, 30);
} else {
ctx.drawImage(this.imgLancer, 480, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.lancer, 480, jobsRowIcon2Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[5].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSize;
if (data.Character.ClassJobs[4].UnlockedState.ID == 20) {
ctx.drawImage(this.imgMonk, 510, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.monk, 510, jobsRowIcon2Y, 30, 30);
} else {
ctx.drawImage(this.imgPugilist, 510, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.pugilist, 510, jobsRowIcon2Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[4].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSize;
if (data.Character.ClassJobs[6].UnlockedState.ID == 30) {
ctx.drawImage(this.imgNinja, 540, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.ninja, 540, jobsRowIcon2Y, 30, 30);
} else {
ctx.drawImage(this.imgRogue, 540, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.rogue, 540, jobsRowIcon2Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[6].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgSamurai, 570, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.samurai, 570, jobsRowIcon2Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[7].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSpacer;
// Caster
if (data.Character.ClassJobs[14].UnlockedState.ID == 25) {
ctx.drawImage(this.imgBlackmage, 630, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.blackmage, 630, jobsRowIcon2Y, 30, 30);
} else {
ctx.drawImage(this.imgThaumaturge, 630, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.thaumaturge, 630, jobsRowIcon2Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[14].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSize;
if (data.Character.ClassJobs[15].UnlockedState.ID == 27) {
ctx.drawImage(this.imgSummoner, 660, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.summoner, 660, jobsRowIcon2Y, 30, 30);
} else {
ctx.drawImage(this.imgArcanist, 660, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.arcanist, 660, jobsRowIcon2Y, 30, 30);
}
ctx.fillText(data.Character.ClassJobs[15].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSize;
ctx.drawImage(this.imgRedmage, 690, jobsRowIcon2Y, 30, 30);
ctx.drawImage(this.cjIcons.redmage, 690, jobsRowIcon2Y, 30, 30);
ctx.fillText(data.Character.ClassJobs[16].Level, cJobsRowTextX, jobsRowText2Y);
cJobsRowTextX += jobsRowTextSize;
// Limited
ctx.drawImage(this.imgBluemage, 780, jobsRowIcon2Y, 33, 33);
ctx.drawImage(this.cjIcons.bluemage, 780, jobsRowIcon2Y, 33, 33);
ctx.fillText(data.Character.ClassJobs[17].Level, 796, jobsRowText2Y);
ctx.textAlign = 'left';