diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..0e6b8cc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,21 @@ +.tmp +.idea +.vscode +.npmrc +.nvmrc +node_modules/ +.env* +/data/ +build/ +build-tools/ +logs/ +reports/ +coverage/ +dist/ +**/*.md +**/*.yml +package-lock.json +static/**/*.min.js +static/**/*.min.css +static/**/*.hbs +config.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..e1157be --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "printWidth": 140, + "useTabs": true, + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always" +} diff --git a/package-lock.json b/package-lock.json index e1df4cc..67e746b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "@types/uuid": "^8.3.4", "concurrently": "^7.0.0", "nodemon": "^2.0.15", + "prettier": "^2.6.0", "rimraf": "^3.0.2", "typescript": "^4.5.5" } @@ -3644,6 +3645,21 @@ "node": ">=4" } }, + "node_modules/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", @@ -7983,6 +7999,12 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", + "dev": true + }, "pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", diff --git a/package.json b/package.json index 25e6073..c1ab37a 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "start": "node --expose-gc build/armory/main.js", "watch": "concurrently \"tsc -w --project .\" \"npm run nodemon\"", "nodemon": "nodemon -q -w build -w config.json build/armory/main.js", + "prettier": "prettier . -w", "fetchdata": "node build/tools/fetchdata.js", "cleardata": "rimraf data/bone data/meta data/mo3 data/textures" }, @@ -26,6 +27,7 @@ "@types/uuid": "^8.3.4", "concurrently": "^7.0.0", "nodemon": "^2.0.15", + "prettier": "^2.6.0", "rimraf": "^3.0.2", "typescript": "^4.5.5" }, diff --git a/src/armory/Armory.ts b/src/armory/Armory.ts index dc94a85..7f457da 100644 --- a/src/armory/Armory.ts +++ b/src/armory/Armory.ts @@ -92,15 +92,18 @@ export class Armory { } app.locals.locals = locals; - app.engine(".hbs", handlebarsEngine({ - extname: "hbs", - partialsDir: path.join(process.cwd(), "static", "partials"), - layoutsDir: path.join(process.cwd(), "static"), - defaultLayout: "layout.hbs", - helpers: { - ...require("handlebars-helpers")(), - }, - })); + app.engine( + ".hbs", + handlebarsEngine({ + extname: "hbs", + partialsDir: path.join(process.cwd(), "static", "partials"), + layoutsDir: path.join(process.cwd(), "static"), + defaultLayout: "layout.hbs", + helpers: { + ...require("handlebars-helpers")(), + }, + }), + ); app.set("view engine", "handlebars"); app.set("views", path.join(process.cwd(), "static")); @@ -122,11 +125,13 @@ export class Armory { } return req.socket.remoteAddress; }); - app.use(morgan(":method :url :status - ID :id - IP :ip - :response-time ms", { - stream: { - write: (msg) => this.logger.http(msg.trim()), - }, - })); + app.use( + morgan(":method :url :status - ID :id - IP :ip - :response-time ms", { + stream: { + write: (msg) => this.logger.http(msg.trim()), + }, + }), + ); app.use("/js", express.static(`static/js`)); app.use("/css", express.static(`static/css`)); @@ -198,7 +203,7 @@ export class Armory { } public getRealm(realm: string): IRealmConfig { - return this.config.realms.find(r => r.name.toLowerCase() === realm.toLowerCase()); + return this.config.realms.find((r) => r.name.toLowerCase() === realm.toLowerCase()); } public async getDatabaseCharset(realm: string): Promise { diff --git a/src/armory/Config.ts b/src/armory/Config.ts index 3a9427f..c3af755 100644 --- a/src/armory/Config.ts +++ b/src/armory/Config.ts @@ -105,7 +105,7 @@ export class Config { let i = 0; while (true) { const key = Config.getEnvKey(parentName + i); - const found = Object.keys(process.env).some(k => k.startsWith(key)); + const found = Object.keys(process.env).some((k) => k.startsWith(key)); if (!found) { break; } @@ -131,10 +131,14 @@ export class Config { } private static getEnvKey(key: string): string { - return Config.envPrefix + "_" + key - .replace(/\./g, "__") - .replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`) - .toUpperCase(); + return ( + Config.envPrefix + + "_" + + key + .replace(/\./g, "__") + .replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`) + .toUpperCase() + ); } private static parseEnvValue(value: string, model: any): any { @@ -173,4 +177,4 @@ export class Config { } return missing; } -}; +} diff --git a/src/armory/DataTablesSsp.ts b/src/armory/DataTablesSsp.ts index 36324f9..ee8b8e9 100644 --- a/src/armory/DataTablesSsp.ts +++ b/src/armory/DataTablesSsp.ts @@ -38,22 +38,22 @@ export class DataTablesSsp { private start: number; private length: number; private _order: { - column: number, - dir: string, + column: number; + dir: string; }[]; private columns: { - data: number, - name: string, - searchable: boolean, - orderable: boolean, + data: number; + name: string; + searchable: boolean; + orderable: boolean; search: { - value: string, - regex: boolean, - } + value: string; + regex: boolean; + }; }[]; private search: { - value: string, - regex: boolean, + value: string; + regex: boolean; }; private wheres: string[] = []; @@ -69,18 +69,18 @@ export class DataTablesSsp { this.start = parseInt(query.start as string, 10); this.length = parseInt(query.length as string, 10); this.draw = parseInt(query.draw as string, 10); - this._order = (query.order as { column: string, dir: string }[]) - .map(order => { return { column: parseInt(order.column, 10), dir: order.dir, }; }); - this.columns = (query.columns as { data: string, name: string, searchable: string, orderable: string, search: any }[]) - .map(column => { - return { - data: parseInt(column.data, 10), - name: column.name, - searchable: column.searchable === "true", - orderable: column.orderable === "true", - search: { value: column.search.value, regex: column.search.regex === "true" }, - }; - }); + this._order = (query.order as { column: string; dir: string }[]).map((order) => { + return { column: parseInt(order.column, 10), dir: order.dir }; + }); + this.columns = (query.columns as { data: string; name: string; searchable: string; orderable: string; search: any }[]).map((column) => { + return { + data: parseInt(column.data, 10), + name: column.name, + searchable: column.searchable === "true", + orderable: column.orderable === "true", + search: { value: column.search.value, regex: column.search.regex === "true" }, + }; + }); this.search = { value: (query.search as any).value as string, regex: (query.search as any).regex === "true", @@ -93,7 +93,7 @@ export class DataTablesSsp { } private colSettingsToStr(colSettings: IColumnSettings) { - const db = colSettings.database ? ("`" + colSettings.database + "`.") : ""; + const db = colSettings.database ? "`" + colSettings.database + "`." : ""; return `${db}\`${colSettings.table || this.table}\`.\`${colSettings.name}\``; } @@ -153,19 +153,16 @@ export class DataTablesSsp { this.filterBindings.push(`%${this.search.value}%`); } if (filterWheres.length > 0) { - this.filterWhereSql = "(" + filterWheres.map(w => `(${w})`).join(" OR ") + ")"; + this.filterWhereSql = "(" + filterWheres.map((w) => `(${w})`).join(" OR ") + ")"; } } - this.customWhereSql = this.wheres.map(w => `(${w})`).join(" AND "); + this.customWhereSql = this.wheres.map((w) => `(${w})`).join(" AND "); return this; } public sql(): string { - const columns = [ - ...this.columnSettings.map(c => this.colSettingsToStr(c)), - ...this.extraDataColumns, - ]; + const columns = [...this.columnSettings.map((c) => this.colSettingsToStr(c)), ...this.extraDataColumns]; return ` SELECT ${columns.join(", ")} FROM ${this.table} @@ -199,10 +196,7 @@ export class DataTablesSsp { } public async run(queryTimeout: number = 10_000): Promise { - this.limit() - .order() - .join() - .filter(); + this.limit().order().join().filter(); const bindings = [...this.filterBindings, ...this.customBindings]; @@ -226,7 +220,7 @@ export class DataTablesSsp { values: bindings, timeout: queryTimeout, }); - rows = (rows as any[][]).map(row => { + rows = (rows as any[][]).map((row) => { for (let i = 0; i < this.columnSettings.length; ++i) { const col = this.columnSettings[i]; if (col.formatter !== undefined) { diff --git a/src/armory/controllers/CharacterController.ts b/src/armory/controllers/CharacterController.ts index fcdbf19..243c0ac 100644 --- a/src/armory/controllers/CharacterController.ts +++ b/src/armory/controllers/CharacterController.ts @@ -90,7 +90,7 @@ export class CharacterController { this.itemInventoryTypes = {}; const itemsRetail = await this.armory.dbc.itemRetail().toArray(); for await (const item of this.armory.dbc.item()) { - const retailItem = itemsRetail.find(row => row.id === item.id); + const retailItem = itemsRetail.find((row) => row.id === item.id); if (retailItem !== undefined) { this.itemInventoryTypes[item.id] = retailItem.inventoryType; } @@ -109,7 +109,7 @@ export class CharacterController { } this.gemItems = {}; - for await (const row of this.armory.dbc.item().filter(item => item.classId === ItemClassGem)) { + for await (const row of this.armory.dbc.item().filter((item) => item.classId === ItemClassGem)) { this.gemItems[row.id] = true; } @@ -127,16 +127,17 @@ export class CharacterController { this.itemSocketBonuses[row.entry] = row.socketBonus; } - const mountSpells = await this.armory.dbc.spell() - .filter(m => m.mechanic === SpellMechanicMounted) + const mountSpells = await this.armory.dbc + .spell() + .filter((m) => m.mechanic === SpellMechanicMounted) .toArray(); - this.mountSpells = mountSpells.map(spell => spell.id); + this.mountSpells = mountSpells.map((spell) => spell.id); this.mountBySpellId = {}; for (const spell of mountSpells) { - const mount = await this.armory.dbc.mount().find(m => m.sourceSpellId === spell.id); - const icon = await this.armory.dbc.spellIcon().find(icon => icon.id === spell.spellIconId); + const mount = await this.armory.dbc.mount().find((m) => m.sourceSpellId === spell.id); + const icon = await this.armory.dbc.spellIcon().find((icon) => icon.id === spell.spellIconId); if (mount !== undefined) { - const display = await this.armory.dbc.mountDisplay().find(d => d.mountId === mount.id); + const display = await this.armory.dbc.mountDisplay().find((d) => d.mountId === mount.id); if (display !== undefined) { this.mountBySpellId[spell.id] = { creatureDisplayId: display.creatureDisplayInfoId, @@ -171,7 +172,7 @@ export class CharacterController { const equipmentData = await this.getEquipmentData(realmName, charData.guid); const customization = this.getCustomizationOptions(charData); - const equipment = equipmentData.map(row => { + const equipment = equipmentData.map((row) => { (row as any).icon = this.itemIcons[row.itemEntry]; (row as any).gems = this.getGemsFromEnchantments(row.enchantments); (row as any).enchantments = this.filterEnchantments(row.itemEntry, row.enchantments); @@ -264,7 +265,7 @@ export class CharacterController { res.json({ categories: await this.armory.dbc.achievementCategory().toArray(), - ...await this.getAchievements(realm.name, charData), + ...(await this.getAchievements(realm.name, charData)), }); } @@ -344,7 +345,7 @@ export class CharacterController { const data = rows as RowDataPacket[] as IEquipmentData[]; for (const row of data) { - const item = await this.armory.dbc.item().find(item => item.id === row.itemEntry); + const item = await this.armory.dbc.item().find((item) => item.id === row.itemEntry); row.classId = item.classId; row.subclassId = item.subclassId; } @@ -363,29 +364,27 @@ export class CharacterController { timeout: this.armory.config.dbQueryTimeout, }); - return (rows as RowDataPacket[]) - .map(row => this.mountBySpellId[row.spell]) - .filter(m => m !== undefined); + return (rows as RowDataPacket[]).map((row) => this.mountBySpellId[row.spell]).filter((m) => m !== undefined); } private async getModelViewerItems(equipmentData: IEquipmentData[], charClass: number): Promise { if (charClass !== 3) { // Keep ranged weapon only if the character is a hunter - equipmentData = equipmentData.filter(row => row.slot !== 17); + equipmentData = equipmentData.filter((row) => row.slot !== 17); } - const visibleEquipment = equipmentData. - filter(item => + const visibleEquipment = equipmentData.filter( + (item) => [0, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 16, 17, 18].includes(item.slot) && // visible slots - item.itemEntry !== 5976 // filter out Guild Tabard (displays blank otherwise) - ); + item.itemEntry !== 5976, // filter out Guild Tabard (displays blank otherwise) + ); const items: number[][] = []; for (const equipment of visibleEquipment) { - const modifiedAppearance = await this.armory.dbc.itemModifiedAppearance().find(row => row.itemId === equipment.itemEntry); + const modifiedAppearance = await this.armory.dbc.itemModifiedAppearance().find((row) => row.itemId === equipment.itemEntry); if (modifiedAppearance === undefined) { continue; } - const appearance = await this.armory.dbc.itemAppearance().find(row => row.id === modifiedAppearance.itemAppearanceId); + const appearance = await this.armory.dbc.itemAppearance().find((row) => row.id === modifiedAppearance.itemAppearanceId); if (appearance === undefined) { continue; } @@ -400,52 +399,53 @@ export class CharacterController { return enchantments .trim() .split(" ") - .map(enchant => parseInt(enchant)) - .filter(enchant => enchant !== 0); + .map((enchant) => parseInt(enchant)) + .filter((enchant) => enchant !== 0); } private getGemsFromEnchantments(enchantments: string): number[] { return this.parseEnchantmentsString(enchantments) - .filter(enchant => enchant in this.enchantSrcItems && this.enchantSrcItems[enchant] in this.gemItems) - .map(enchant => this.enchantSrcItems[enchant]); + .filter((enchant) => enchant in this.enchantSrcItems && this.enchantSrcItems[enchant] in this.gemItems) + .map((enchant) => this.enchantSrcItems[enchant]); } private filterEnchantments(item: number, enchantments: string): number[] { const socketBonus = this.itemSocketBonuses[item]; - return this.parseEnchantmentsString(enchantments) - .filter(enchant => enchant in this.enchantSrcItems && !(this.enchantSrcItems[enchant] in this.gemItems) && enchant !== socketBonus); + return this.parseEnchantmentsString(enchantments).filter( + (enchant) => enchant in this.enchantSrcItems && !(this.enchantSrcItems[enchant] in this.gemItems) && enchant !== socketBonus, + ); } private getCustomizationOptions(charData: ICharacterData): ICustomizationOption[] { const data = this.armory.characterCustomization.getCharacterCustomizationData(charData.race, charData.gender); const options = []; const setOptionByChoiceIndex = (optionName: string, choiceIndex: number) => { - const option = data.Options.find(opt => opt.Name === optionName); + const option = data.Options.find((opt) => opt.Name === optionName); if (option !== undefined) { - const choice = option.Choices.find(choice => choice.OrderIndex === choiceIndex); + const choice = option.Choices.find((choice) => choice.OrderIndex === choiceIndex); if (choice !== undefined) { options.push({ optionId: option.Id, choiceId: choice.Id }); } } }; const setOptionByChoiceName = (optionName: string, choiceName: string) => { - const option = data.Options.find(opt => opt.Name === optionName); + const option = data.Options.find((opt) => opt.Name === optionName); if (option !== undefined) { - const choice = option.Choices.find(ch => ch.Name === choiceName); + const choice = option.Choices.find((ch) => ch.Name === choiceName); if (choice !== undefined) { options.push({ optionId: option.Id, choiceId: choice.Id }); } } }; const setOptionByChoiceId = (optionName: string, choiceId: number) => { - const option = data.Options.find(opt => opt.Name === optionName); + const option = data.Options.find((opt) => opt.Name === optionName); if (option !== undefined) { options.push({ optionId: option.Id, choiceId: choiceId }); } }; const optionMapping = { - "Face": charData.face, + Face: charData.face, "Skin Color": charData.skin, "Hair Style": charData.hairStyle, "Hair Color": charData.hairColor, @@ -458,19 +458,54 @@ export class CharacterController { switch (charData.race) { case 1: // Human if (charData.gender === 0) { - setOptionByChoiceName("Mustache", { 0: "Horseshoe", 1: "Brush", 2: "Horseshoe", 3: "None", 4: "Brush", 5: "Brush", 6: "Horseshoe", 7: "Brush", 8: "None" }[charData.facialStyle]); - setOptionByChoiceName("Beard", { 0: "Short", 1: "Chin Puff", 2: "Soul Patch", 3: "Goatee", 4: "Goatee", 5: "None", 6: "Goatee", 7: "None", 8: "None" }[charData.facialStyle]); - setOptionByChoiceName("Sideburns", { 0: "Medium", 1: "None", 2: "None", 3: "Medium", 4: "Long", 5: "Long", 6: "None", 8: "None", 7: "None" }[charData.facialStyle]); + setOptionByChoiceName( + "Mustache", + { 0: "Horseshoe", 1: "Brush", 2: "Horseshoe", 3: "None", 4: "Brush", 5: "Brush", 6: "Horseshoe", 7: "Brush", 8: "None" }[ + charData.facialStyle + ], + ); + setOptionByChoiceName( + "Beard", + { 0: "Short", 1: "Chin Puff", 2: "Soul Patch", 3: "Goatee", 4: "Goatee", 5: "None", 6: "Goatee", 7: "None", 8: "None" }[ + charData.facialStyle + ], + ); + setOptionByChoiceName( + "Sideburns", + { 0: "Medium", 1: "None", 2: "None", 3: "Medium", 4: "Long", 5: "Long", 6: "None", 8: "None", 7: "None" }[charData.facialStyle], + ); setOptionByChoiceName("Eyebrows", "Natural"); setOptionByChoiceName("Face Shape", "Narrow"); - setOptionByChoiceId("Eye Color", { 0: 4138, 1: 4140, 2: 4130, 3: 4136, 4: 4141, 5: 4134, 6: 4130, 7: 4138, 8: 4144, 9: 4135, 10: 4126, 11: 4136 }[charData.face]); + setOptionByChoiceId( + "Eye Color", + { 0: 4138, 1: 4140, 2: 4130, 3: 4136, 4: 4141, 5: 4134, 6: 4130, 7: 4138, 8: 4144, 9: 4135, 10: 4126, 11: 4136 }[charData.face], + ); } else { setOptionByChoiceIndex("Piercings", charData.facialStyle); setOptionByChoiceName("Eyebrows", "Natural"); setOptionByChoiceName("Face Shape", "Narrow"); setOptionByChoiceName("Makeup", "None"); setOptionByChoiceName("Necklace", "None"); - setOptionByChoiceId("Eye Color", { 0: 4162, 1: 4153, 2: 4161, 3: 4164, 4: 4154, 5: 4160, 6: 4160, 7: 4157, 8: 4152, 9: 4154, 10: 4155, 11: 4165, 12: 4163, 13: 4155, 14: 4151 }[charData.face]); + setOptionByChoiceId( + "Eye Color", + { + 0: 4162, + 1: 4153, + 2: 4161, + 3: 4164, + 4: 4154, + 5: 4160, + 6: 4160, + 7: 4157, + 8: 4152, + 9: 4154, + 10: 4155, + 11: 4165, + 12: 4163, + 13: 4155, + 14: 4151, + }[charData.face], + ); } if (charData.class === 6) { // Death Knight @@ -482,14 +517,32 @@ export class CharacterController { setOptionByChoiceIndex("Tattoo Color", 0); setOptionByChoiceIndex("Eyebrows", 0); if (charData.gender === 0) { - setOptionByChoiceName("Mustache", { 0: "Trimmed", 1: "Bushy", 2: "Grand", 3: "Thin Braids", 4: "Wise", 5: "Thick Braids", 6: "Fancy", 7: "Bold", 8: "Tied", 9: "None", 10: "None", }[charData.facialStyle]); + setOptionByChoiceName( + "Mustache", + { + 0: "Trimmed", + 1: "Bushy", + 2: "Grand", + 3: "Thin Braids", + 4: "Wise", + 5: "Thick Braids", + 6: "Fancy", + 7: "Bold", + 8: "Tied", + 9: "None", + 10: "None", + }[charData.facialStyle], + ); setOptionByChoiceIndex("Beard", charData.facialStyle); setOptionByChoiceName("Earrings", "None"); setOptionByChoiceName("Nose Ring", "None"); setOptionByChoiceIndex("Eye Color", 0); // TODO } else { setOptionByChoiceIndex("Earrings", { 0: 0, 1: 1, 2: 2, 3: 3, 4: 0, 5: 4 }[charData.facialStyle]); - setOptionByChoiceName("Piercings", { 0: "None", 1: "None", 2: "None", 3: "None", 4: "Right Nostril", 5: "None" }[charData.facialStyle]); + setOptionByChoiceName( + "Piercings", + { 0: "None", 1: "None", 2: "None", 3: "None", 4: "Right Nostril", 5: "None" }[charData.facialStyle], + ); setOptionByChoiceIndex("Eye Color", 0); // TODO } if (charData.class === 6) { @@ -519,7 +572,10 @@ export class CharacterController { setOptionByChoiceName("Ears", "Thin"); setOptionByChoiceName("Scars", "None"); if (charData.gender === 0) { - setOptionByChoiceName("Sideburns", { 0: "None", 1: "Groomed", 2: "None", 3: "Short", 4: "Medium", 5: "Groomed" }[charData.facialStyle]); + setOptionByChoiceName( + "Sideburns", + { 0: "None", 1: "Groomed", 2: "None", 3: "Short", 4: "Medium", 5: "Groomed" }[charData.facialStyle], + ); setOptionByChoiceName("Mustache", { 0: "None", 1: "Groomed", 2: "None", 3: "Thin", 4: "None", 5: "None" }[charData.facialStyle]); setOptionByChoiceName("Beard", { 0: "None", 1: "Trimmed", 2: "Full", 3: "None", 4: "Short", 5: "Long" }[charData.facialStyle]); setOptionByChoiceName("Eyebrows", { 0: "Shaved", 1: "Short", 2: "Long", 3: "Flat", 4: "Short", 5: "Owl" }[charData.facialStyle]); @@ -549,10 +605,21 @@ export class CharacterController { setOptionByChoiceName("Horn Decoration", "None"); setOptionByChoiceName("Tail", charData.gender === 0 ? "Long" : "Short"); if (charData.gender === 0) { - setOptionByChoiceName("Facial Hair", { 0: "Bare", 1: "Bare", 2: "Burns", 3: "Chops", 4: "Mustache", 5: "Soul Patch", 6: "Handlebar", 7: "Bare" }[charData.facialStyle]); - setOptionByChoiceName("Tendrils", { 0: "None", 1: "Splayed", 2: "Double", 3: "Fanned", 4: "Single", 5: "Paired", 6: "Uniform", 7: "Twin" }[charData.facialStyle]); + setOptionByChoiceName( + "Facial Hair", + { 0: "Bare", 1: "Bare", 2: "Burns", 3: "Chops", 4: "Mustache", 5: "Soul Patch", 6: "Handlebar", 7: "Bare" }[ + charData.facialStyle + ], + ); + setOptionByChoiceName( + "Tendrils", + { 0: "None", 1: "Splayed", 2: "Double", 3: "Fanned", 4: "Single", 5: "Paired", 6: "Uniform", 7: "Twin" }[charData.facialStyle], + ); } else { - setOptionByChoiceName("Horns", { 0: "Sweeping", 1: "Curled", 2: "Curved", 3: "Thick", 4: "Wide", 5: "Grand", 6: "Short" }[charData.facialStyle]); + setOptionByChoiceName( + "Horns", + { 0: "Sweeping", 1: "Curled", 2: "Curved", 3: "Thick", 4: "Wide", 5: "Grand", 6: "Short" }[charData.facialStyle], + ); } if (charData.class === 6) { // Death Knight @@ -568,8 +635,28 @@ export class CharacterController { setOptionByChoiceName("War Paint", "None"); setOptionByChoiceName("War Paint Color", "None"); if (charData.gender === 0) { - setOptionByChoiceName("Beard", { 0: "None", 1: "Stubble", 2: "Thick", 3: "Full", 4: "Tied", 5: "Braid", 6: "Twin Braids", 7: "None", 8: "Ringed", 9: "Split", 10: "Goatee" }[charData.facialStyle]); - setOptionByChoiceName("Sideburns", { 0: "None", 1: "None", 2: "Full", 3: "Low", 4: "Full", 5: "None", 6: "None", 7: "Braids", 8: "None", 9: "Full", 10: "Thick" }[charData.facialStyle]); + setOptionByChoiceName( + "Beard", + { + 0: "None", + 1: "Stubble", + 2: "Thick", + 3: "Full", + 4: "Tied", + 5: "Braid", + 6: "Twin Braids", + 7: "None", + 8: "Ringed", + 9: "Split", + 10: "Goatee", + }[charData.facialStyle], + ); + setOptionByChoiceName( + "Sideburns", + { 0: "None", 1: "None", 2: "Full", 3: "Low", 4: "Full", 5: "None", 6: "None", 7: "Braids", 8: "None", 9: "Full", 10: "Thick" }[ + charData.facialStyle + ], + ); setOptionByChoiceName("Earrings", "None"); setOptionByChoiceName("Nose Ring", "None"); setOptionByChoiceName("Tusks", "Natural"); @@ -589,13 +676,71 @@ export class CharacterController { case 5: // Undead setOptionByChoiceName("Skin Type", "Bony"); if (charData.gender === 0) { - setOptionByChoiceName("Jaw Features", { 0: "Intact", 1: "Rot-Kissed", 2: "Intact", 3: "Slackjawed", 4: "Drooler", 5: "Intact", 6: "Slackjawed", 7: "Drooler", 8: "Bonejawed", 9: "Jawsome", 10: "Toothy", 11: "Unhinged", 12: "Cheeky", 13: "Loose", 14: "Intact", 15: "Slackjawed", 16: "Slobber" }[charData.facialStyle]); - setOptionByChoiceIndex("Face Features", { 0: 0, 1: 0, 2: 1, 3: 1, 4: 1, 5: 2, 6: 3, 7: 3, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0, 14: 4, 15: 4, 16: 0 }[charData.facialStyle]); - setOptionByChoiceId("Eye Color", { 0: 5330, 1: 5330, 2: 6304, 3: 6304, 4: 6304, 5: 5330, 6: 5330, 7: 5330, 8: 5330, 9: 5330, 10: 6304, 11: 6304, 12: 5330, 13: 5330, 14: 5330, 15: 5330, 16: 5330 }[charData.facialStyle]); + setOptionByChoiceName( + "Jaw Features", + { + 0: "Intact", + 1: "Rot-Kissed", + 2: "Intact", + 3: "Slackjawed", + 4: "Drooler", + 5: "Intact", + 6: "Slackjawed", + 7: "Drooler", + 8: "Bonejawed", + 9: "Jawsome", + 10: "Toothy", + 11: "Unhinged", + 12: "Cheeky", + 13: "Loose", + 14: "Intact", + 15: "Slackjawed", + 16: "Slobber", + }[charData.facialStyle], + ); + setOptionByChoiceIndex( + "Face Features", + { 0: 0, 1: 0, 2: 1, 3: 1, 4: 1, 5: 2, 6: 3, 7: 3, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0, 14: 4, 15: 4, 16: 0 }[ + charData.facialStyle + ], + ); + setOptionByChoiceId( + "Eye Color", + { + 0: 5330, + 1: 5330, + 2: 6304, + 3: 6304, + 4: 6304, + 5: 5330, + 6: 5330, + 7: 5330, + 8: 5330, + 9: 5330, + 10: 6304, + 11: 6304, + 12: 5330, + 13: 5330, + 14: 5330, + 15: 5330, + 16: 5330, + }[charData.facialStyle], + ); } else { - setOptionByChoiceName("Face Features", { 0: "None", 1: "None", 2: "Strapped", 3: "Rotting", 4: "None", 5: "None", 6: "None", 7: "Putrid" }[charData.facialStyle]); - setOptionByChoiceName("Jaw Features", { 0: "Intact", 1: "Stitched", 2: "Intact", 3: "Intact", 4: "Bonejawed", 5: "Toothy", 6: "Cheeky", 7: "Intact" }[charData.facialStyle]); - setOptionByChoiceId("Eye Color", { 0: 5337, 1: 5337, 2: 6305, 3: 5337, 4: 5337, 5: 6305, 6: 5337, 7: 5337 }[charData.facialStyle]); + setOptionByChoiceName( + "Face Features", + { 0: "None", 1: "None", 2: "Strapped", 3: "Rotting", 4: "None", 5: "None", 6: "None", 7: "Putrid" }[charData.facialStyle], + ); + setOptionByChoiceName( + "Jaw Features", + { 0: "Intact", 1: "Stitched", 2: "Intact", 3: "Intact", 4: "Bonejawed", 5: "Toothy", 6: "Cheeky", 7: "Intact" }[ + charData.facialStyle + ], + ); + setOptionByChoiceId( + "Eye Color", + { 0: 5337, 1: 5337, 2: 6305, 3: 5337, 4: 5337, 5: 6305, 6: 5337, 7: 5337 }[charData.facialStyle], + ); } if (charData.class === 6) { // Death Knight @@ -614,9 +759,18 @@ export class CharacterController { setOptionByChoiceName("Body Paint", "None"); setOptionByChoiceIndex("Paint Color", 0); if (charData.gender === 0) { - setOptionByChoiceName("Hair", { 0: "Mane", 1: "Braids", 2: "Chops", 3: "Sideburns", 4: "Mane", 5: "Wrapped", 6: "Braids" }[charData.facialStyle]); - setOptionByChoiceName("Facial Hair", { 0: "Clean", 1: "Braid", 2: "Beard", 3: "Wrapped", 4: "Curtain", 5: "Clean", 6: "Split" }[charData.facialStyle]); - setOptionByChoiceName("Nose Ring", { 0: "None", 1: "Small", 2: "Open", 3: "None", 4: "None", 5: "Bead", 6: "Open" }[charData.facialStyle]); + setOptionByChoiceName( + "Hair", + { 0: "Mane", 1: "Braids", 2: "Chops", 3: "Sideburns", 4: "Mane", 5: "Wrapped", 6: "Braids" }[charData.facialStyle], + ); + setOptionByChoiceName( + "Facial Hair", + { 0: "Clean", 1: "Braid", 2: "Beard", 3: "Wrapped", 4: "Curtain", 5: "Clean", 6: "Split" }[charData.facialStyle], + ); + setOptionByChoiceName( + "Nose Ring", + { 0: "None", 1: "Small", 2: "Open", 3: "None", 4: "None", 5: "Bead", 6: "Open" }[charData.facialStyle], + ); setOptionByChoiceIndex("Eye Color", 0); // TODO } else { setOptionByChoiceIndex("Hair", charData.facialStyle); @@ -634,8 +788,38 @@ export class CharacterController { setOptionByChoiceName("Body Paint Color", "None"); setOptionByChoiceName("Piercing", "None"); if (charData.gender === 0) { - setOptionByChoiceName("Tusks", { 0: "Tusked", 1: "Gougers", 2: "Mammoth", 3: "Spears", 4: "Bridle", 5: "Tusked", 6: "Gougers", 7: "Mammoth", 8: "Spears", 9: "Bridle", 10: "Gougers" }[charData.facialStyle]); - setOptionByChoiceName("Face Paint", { 0: "None", 1: "None", 2: "None", 3: "None", 4: "None", 5: "Berserker", 6: "Fangs", 7: "Mask", 8: "Oni", 9: "Prophet", 10: "War" }[charData.facialStyle]); + setOptionByChoiceName( + "Tusks", + { + 0: "Tusked", + 1: "Gougers", + 2: "Mammoth", + 3: "Spears", + 4: "Bridle", + 5: "Tusked", + 6: "Gougers", + 7: "Mammoth", + 8: "Spears", + 9: "Bridle", + 10: "Gougers", + }[charData.facialStyle], + ); + setOptionByChoiceName( + "Face Paint", + { + 0: "None", + 1: "None", + 2: "None", + 3: "None", + 4: "None", + 5: "Berserker", + 6: "Fangs", + 7: "Mask", + 8: "Oni", + 9: "Prophet", + 10: "War", + }[charData.facialStyle], + ); setOptionByChoiceIndex("Face Paint Color", charData.hairColor + 1); setOptionByChoiceName("Earrings", "None"); setOptionByChoiceIndex("Eye Color", 0); // TODO @@ -712,16 +896,18 @@ export class CharacterController { } private async getTalentTrees(classId: number) { - const items = await this.armory.dbc.talentTab() - .filter(tab => tab.classMask === Math.pow(2, classId - 1)) - .map(async tab => { - const icon = await this.armory.dbc.spellIcon().find(icon => icon.id === tab.spellIconId); - const spells = await this.armory.dbc.talent() - .filter(row => row.tabId === tab.id) - .map(async row => { - const spell = await this.armory.dbc.spell().find(spell => spell.id === row.spellRank0); - const icon = await this.armory.dbc.spellIcon().find(icon => icon.id === spell?.spellIconId); - return { ...row, icon: this.processSpellIconTexture(icon?.textureFilename ?? ""), }; + const items = await this.armory.dbc + .talentTab() + .filter((tab) => tab.classMask === Math.pow(2, classId - 1)) + .map(async (tab) => { + const icon = await this.armory.dbc.spellIcon().find((icon) => icon.id === tab.spellIconId); + const spells = await this.armory.dbc + .talent() + .filter((row) => row.tabId === tab.id) + .map(async (row) => { + const spell = await this.armory.dbc.spell().find((spell) => spell.id === row.spellRank0); + const icon = await this.armory.dbc.spellIcon().find((icon) => icon.id === spell?.spellIconId); + return { ...row, icon: this.processSpellIconTexture(icon?.textureFilename ?? "") }; }) .toArray(); return { @@ -735,11 +921,7 @@ export class CharacterController { } private processSpellIconTexture(texturePath: string): string { - return texturePath - .toLowerCase() - .replace("interface\\icons\\", "") - .replace("interface\\spellbook\\", "") - .replace(/\.$/, ""); + return texturePath.toLowerCase().replace("interface\\icons\\", "").replace("interface\\spellbook\\", "").replace(/\.$/, ""); } private async getGlyphs(realm: string, character: number): Promise { @@ -755,9 +937,9 @@ export class CharacterController { const glyphs = [[], []]; for (const row of rows as RowDataPacket[]) { - const glyphIds = [row.glyph1, row.glyph2, row.glyph3, row.glyph4, row.glyph5, row.glyph6].filter(id => id !== 0); + const glyphIds = [row.glyph1, row.glyph2, row.glyph3, row.glyph4, row.glyph5, row.glyph6].filter((id) => id !== 0); for (const glyphId of glyphIds) { - const glyph = await this.armory.dbc.glyphProperties().find(g => g.id === glyphId); + const glyph = await this.armory.dbc.glyphProperties().find((g) => g.id === glyphId); if (glyph === undefined) { continue; } @@ -768,11 +950,12 @@ export class CharacterController { return glyphs; } - private async getAchievements(realm: string, charData: ICharacterData): Promise<{ achievements: any[]; earned: { [key: number]: any }; }> { - const promises = await this.armory.dbc.achievement() - .filter(ach => ach.faction === -1 || ach.faction === Utils.getFactionFromRaceId(charData.race)) + private async getAchievements(realm: string, charData: ICharacterData): Promise<{ achievements: any[]; earned: { [key: number]: any } }> { + const promises = await this.armory.dbc + .achievement() + .filter((ach) => ach.faction === -1 || ach.faction === Utils.getFactionFromRaceId(charData.race)) .map(async (ach) => { - const icon = await this.armory.dbc.spellIcon().find(icon => icon.id === ach.iconId); + const icon = await this.armory.dbc.spellIcon().find((icon) => icon.id === ach.iconId); return { id: ach.id, category: ach.category, @@ -807,7 +990,7 @@ export class CharacterController { }; } - private async getPvpKills(realm: string, charGuid: number): Promise<{ total: number, today: number, yesterday: number }> { + private async getPvpKills(realm: string, charGuid: number): Promise<{ total: number; today: number; yesterday: number }> { const [rows, fields] = await this.armory.getCharactersDb(realm).query({ sql: ` SELECT totalKills, todayKills, yesterdayKills @@ -841,7 +1024,7 @@ export class CharacterController { timeout: this.armory.config.dbQueryTimeout, }); - return (rows as RowDataPacket[]).map(row => { + return (rows as RowDataPacket[]).map((row) => { row.emblem = Utils.makeEmblemObject(row, false); return row; }); diff --git a/src/armory/controllers/GuildController.ts b/src/armory/controllers/GuildController.ts index df92261..6296ab5 100644 --- a/src/armory/controllers/GuildController.ts +++ b/src/armory/controllers/GuildController.ts @@ -64,24 +64,28 @@ export class GuildController { { name: "name", table: "characters", collation: `${charSet}_general_ci` }, { name: "rank" }, { name: "level", table: "characters" }, - { name: "class", table: "characters", formatter: cls => Utils.classNames[cls] }, + { name: "class", table: "characters", formatter: (cls) => Utils.classNames[cls] }, { name: "race", table: "characters", formatter: (race, row) => `${Utils.raceNames[race]}_${row[6] === 0 ? "male" : "female"}` }, - { name: "online", table: "characters", formatter: online => online === 1 }, + { name: "online", table: "characters", formatter: (online) => online === 1 }, ]); - ssp.joins = [ - { table1: "guild_member", column1: "guid", table2: "characters", column2: "guid", kind: "LEFT" }, - ]; + ssp.joins = [{ table1: "guild_member", column1: "guid", table2: "characters", column2: "guid", kind: "LEFT" }]; ssp.extraDataColumns = ["`characters`.`gender`"]; if (this.armory.config.hideGameMasters) { - ssp.joins.push({ table1: "characters", column1: "account", table2: "account_access", column2: "id", database2: realm.authDatabase, kind: "LEFT" }); - ssp = ssp.where(`\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`); + ssp.joins.push({ + table1: "characters", + column1: "account", + table2: "account_access", + column2: "id", + database2: realm.authDatabase, + kind: "LEFT", + }); + ssp = ssp.where( + `\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`, + ); } - const result = await ssp - .where("`guildid` = ?", guildId) - .where("`deleteInfos_Account` IS NULL") - .run(this.armory.config.dbQueryTimeout); + const result = await ssp.where("`guildid` = ?", guildId).where("`deleteInfos_Account` IS NULL").run(this.armory.config.dbQueryTimeout); const ranks = await this.getGuildRanks(realm, guildId); (result as any).ranks = {}; diff --git a/src/armory/controllers/IndexController.ts b/src/armory/controllers/IndexController.ts index 0322a6f..954ad01 100644 --- a/src/armory/controllers/IndexController.ts +++ b/src/armory/controllers/IndexController.ts @@ -14,15 +14,13 @@ export class IndexController { public async index(req: express.Request, res: express.Response): Promise { res.render("index.hbs", { title: "Armory", - realms: this.armory.config.realms.map(r => r.name), + realms: this.armory.config.realms.map((r) => r.name), }); } public async search(req: express.Request, res: express.Response, next: express.NextFunction): Promise { const realmName = req.query.realm as string; - const realm = realmName === undefined ? - this.armory.config.realms[0] : - this.armory.config.realms.find(r => r.name === realmName); + const realm = realmName === undefined ? this.armory.config.realms[0] : this.armory.config.realms.find((r) => r.name === realmName); if (realm === undefined) { return next(400); } @@ -34,9 +32,9 @@ export class IndexController { { name: "name", collation: `${charSet}_general_ci` }, { table: "guild", name: "name" }, { name: "level" }, - { name: "class", formatter: cls => Utils.classNames[cls] }, + { name: "class", formatter: (cls) => Utils.classNames[cls] }, { name: "race", formatter: (race, row) => `${Utils.raceNames[race]}_${row[6] === 0 ? "male" : "female"}` }, - { name: "online", formatter: online => online === 1 }, + { name: "online", formatter: (online) => online === 1 }, ]); ssp.joins = [ { table1: "characters", column1: "guid", table2: "guild_member", column2: "guid", kind: "LEFT" }, @@ -45,13 +43,20 @@ export class IndexController { ssp.extraDataColumns = ["`characters`.`gender`"]; if (this.armory.config.hideGameMasters) { - ssp.joins.push({ table1: "characters", column1: "account", table2: "account_access", column2: "id", database2: realm.authDatabase, kind: "LEFT" }); - ssp = ssp.where(`\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`); + ssp.joins.push({ + table1: "characters", + column1: "account", + table2: "account_access", + column2: "id", + database2: realm.authDatabase, + kind: "LEFT", + }); + ssp = ssp.where( + `\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`, + ); } - const result = await ssp - .where("`deleteInfos_Account` IS NULL") - .run(this.armory.config.dbQueryTimeout); + const result = await ssp.where("`deleteInfos_Account` IS NULL").run(this.armory.config.dbQueryTimeout); (result as any).realm = realm.name; res.json(result); diff --git a/src/armory/data/DbcReader.ts b/src/armory/data/DbcReader.ts index 212e502..f931488 100644 --- a/src/armory/data/DbcReader.ts +++ b/src/armory/data/DbcReader.ts @@ -148,11 +148,13 @@ class AsyncGenWrapper implements IAsyncGeneratorWithArrayMethods { } public static from(array: T[]): AsyncGenWrapper { - return new AsyncGenWrapper(async function* () { - for (const x of array) { - yield x; - } - }()); + return new AsyncGenWrapper( + (async function* () { + for (const x of array) { + yield x; + } + })(), + ); } public async *[Symbol.asyncIterator](): AsyncGenerator { @@ -217,11 +219,10 @@ class DbcReader { return; } - const headerCols = headerLine.value - .map(header => camelCase(header).replace(/[\[\]]/g, "")); + const headerCols = headerLine.value.map((header) => camelCase(header).replace(/[\[\]]/g, "")); for await (const arr of itr) { - const cols = arr.map(value => isNaN(value as any) ? value : parseInt(value, 10)); + const cols = arr.map((value) => (isNaN(value as any) ? value : parseInt(value, 10))); const row = {}; headerCols.forEach((header, headerIdx) => { if (this.fields.length === 0 || this.fields.includes(header)) { @@ -242,7 +243,8 @@ class DbcReader { const str = chunk.toString(); // Iterate over each character, keep track of current column (of the returned array) for (let c = 0; c < str.length; ++c) { - let ch = str[c], nch = str[c + 1]; // Current character, next character + let ch = str[c], + nch = str[c + 1]; // Current character, next character if (!(col in arr)) { arr[col] = ""; // Create a new column (start with empty string) if necessary } @@ -263,14 +265,14 @@ class DbcReader { } // If it's a comma and we're not in a quoted field, move on to the next column - if (ch == ',' && !quote) { + if (ch == "," && !quote) { ++col; continue; } // If it's a newline (CRLF) and we're not in a quoted field, skip the next character // and move on to the next row and move to column 0 of that new row - if (ch == '\r' && nch == '\n' && !quote) { + if (ch == "\r" && nch == "\n" && !quote) { yield arr; arr.length = 0; // Clear the row col = 0; @@ -280,7 +282,7 @@ class DbcReader { // If it's a newline (LF or CR) and we're not in a quoted field, // move on to the next row and move to column 0 of that new row - if (!quote && (ch == '\r' || ch == '\n')) { + if (!quote && (ch == "\r" || ch == "\n")) { yield arr; arr.length = 0; // Clear the row col = 0; @@ -327,7 +329,19 @@ const dbcFields = { spell: ["id", "mechanic", "spellIconId"], spellItemEnchantment: ["id", "srcItemId"], spellIcon: ["id", "textureFilename"], - talent: ["id", "tabId", "tierId", "columnIndex", "spellRank0", "spellRank1", "spellRank2", "spellRank3", "spellRank4", "prereqTalent0", "prereqRank0"], + talent: [ + "id", + "tabId", + "tierId", + "columnIndex", + "spellRank0", + "spellRank1", + "spellRank2", + "spellRank3", + "spellRank4", + "prereqTalent0", + "prereqRank0", + ], talentTab: ["id", "nameLang0", "spellIconId", "classMask"], }; @@ -350,17 +364,26 @@ export class DbcManager { public async loadAllFiles(): Promise { this._achievement = await this.read(DbcFiles.achievement, dbcFields.achievement).toArray(); - this._achievementCategory = await this.read(DbcFiles.achievementCategory, dbcFields.achievementCategory).toArray(); + this._achievementCategory = await this.read( + DbcFiles.achievementCategory, + dbcFields.achievementCategory, + ).toArray(); this._glyphProperties = await this.read(DbcFiles.glyphProperties, dbcFields.glyphProperties).toArray(); this._item = await this.read(DbcFiles.item, dbcFields.item).toArray(); this._itemRetail = await this.read(DbcFiles.itemRetail, dbcFields.itemRetail).toArray(); this._itemAppearance = await this.read(DbcFiles.itemAppearance, dbcFields.itemAppearance).toArray(); - this._itemModifiedAppearance = await this.read(DbcFiles.itemModifiedAppearance, dbcFields.itemModifiedAppearance).toArray(); + this._itemModifiedAppearance = await this.read( + DbcFiles.itemModifiedAppearance, + dbcFields.itemModifiedAppearance, + ).toArray(); this._itemDisplayInfo = await this.read(DbcFiles.itemDisplayInfo, dbcFields.itemDisplayInfo).toArray(); this._mount = await this.read(DbcFiles.mount, dbcFields.mount).toArray(); this._mountDisplay = await this.read(DbcFiles.mountDisplay, dbcFields.mountDisplay).toArray(); this._spell = await this.read(DbcFiles.spell, dbcFields.spell).toArray(); - this._spellItemEnchantment = await this.read(DbcFiles.spellItemEnchantment, dbcFields.spellItemEnchantment).toArray(); + this._spellItemEnchantment = await this.read( + DbcFiles.spellItemEnchantment, + dbcFields.spellItemEnchantment, + ).toArray(); this._spellIcon = await this.read(DbcFiles.spellIcon, dbcFields.spellIcon).toArray(); this._talent = await this.read(DbcFiles.talent, dbcFields.talent).toArray(); this._talentTab = await this.read(DbcFiles.talentTab, dbcFields.talentTab).toArray(); diff --git a/src/tools/fetchdata.ts b/src/tools/fetchdata.ts index 9e6b412..10335c5 100644 --- a/src/tools/fetchdata.ts +++ b/src/tools/fetchdata.ts @@ -54,9 +54,12 @@ class Progress { } private createProgressBar(text: string, total: number): cliProgress.SingleBar { - const progress = new cliProgress.SingleBar({ - format: `${text} {bar} {percentage}% ({value} / {total})`, - }, cliProgress.Presets.shades_classic); + const progress = new cliProgress.SingleBar( + { + format: `${text} {bar} {percentage}% ({value} / {total})`, + }, + cliProgress.Presets.shades_classic, + ); progress.start(total, 0); return progress; } @@ -163,25 +166,13 @@ function queueTexturesAndModels(item: any): void { } async function downloadRaces(): Promise { - const races = [ - "human", - "nightelf", - "dwarf", - "gnome", - "draenei", - "orc", - "troll", - "tauren", - "bloodelf", - "scourge", - ]; + const races = ["human", "nightelf", "dwarf", "gnome", "draenei", "orc", "troll", "tauren", "bloodelf", "scourge"]; const genders = ["male", "female"]; const raceGenderCombo = races.map((race) => [race + genders[0], race + genders[1]]).flat(); const progress = new Progress("Downloading races data...", raceGenderCombo.length); - await promisepool.PromisePool - .for(raceGenderCombo) + await promisepool.PromisePool.for(raceGenderCombo) .withConcurrency(4) .process(async (race) => { const characterJson = await download("meta/character", `${race}.json`); @@ -191,7 +182,11 @@ async function downloadRaces(): Promise { for (const option of customizationJson.Options) { for (const choice of option.Choices) { for (const element of choice.Elements) { - if (element.SkinnedModel !== null && typeof element.SkinnedModel.CollectionFileDataID === "number" && element.SkinnedModel.CollectionFileDataID !== 0) { + if ( + element.SkinnedModel !== null && + typeof element.SkinnedModel.CollectionFileDataID === "number" && + element.SkinnedModel.CollectionFileDataID !== 0 + ) { modelsDownloadQueue.add(element.SkinnedModel.CollectionFileDataID); } if (element.BoneSet !== null && typeof element.BoneSet.BoneFileDataID === "number" && element.BoneSet.BoneFileDataID !== 0) { @@ -202,7 +197,7 @@ async function downloadRaces(): Promise { } const textureFiles = Object.keys(customizationJson.TextureFiles) - .map(key => customizationJson.TextureFiles[key]) + .map((key) => customizationJson.TextureFiles[key]) .flat(); for (const file of textureFiles) { texturesDownloadQueue.add(file.FileDataId); @@ -215,12 +210,14 @@ async function downloadRaces(): Promise { } async function downloadArmors(): Promise { - const rows = await dbc.item().filter((row) => row.classId === classIdArmor).toArray(); + const rows = await dbc + .item() + .filter((row) => row.classId === classIdArmor) + .toArray(); const progress = new Progress("Downloading armor data...", rows.length); - await promisepool.PromisePool - .for(rows) + await promisepool.PromisePool.for(rows) .withConcurrency(50) .process(async (row) => { const modifiedAppearance = dbcItemModifiedAppearanceByItemId[row.id]; @@ -247,12 +244,14 @@ async function downloadArmors(): Promise { } async function downloadWeapons(): Promise { - const rows = await dbc.item().filter((row) => row.classId === classIdWeapon).toArray(); + const rows = await dbc + .item() + .filter((row) => row.classId === classIdWeapon) + .toArray(); const progress = new Progress("Downloading weapon data...", rows.length); - await promisepool.PromisePool - .for(rows) + await promisepool.PromisePool.for(rows) .withConcurrency(50) .process(async (row) => { const modifiedAppearance = dbcItemModifiedAppearanceByItemId[row.id]; @@ -307,11 +306,13 @@ async function readDbcData(): Promise { } async function downloadMounts(): Promise { - const mountSpells = await dbc.spell().filter(spell => spell.mechanic === spellMechanicMounted).toArray(); + const mountSpells = await dbc + .spell() + .filter((spell) => spell.mechanic === spellMechanicMounted) + .toArray(); const progress = new Progress("Downloading mount data...", mountSpells.length); - await promisepool.PromisePool - .for(mountSpells) + await promisepool.PromisePool.for(mountSpells) .withConcurrency(50) .process(async (spell) => { const mount = dbcMountBySourceSpellId[spell.id]; @@ -333,8 +334,7 @@ async function downloadMounts(): Promise { async function downloadTextures(): Promise { const progress = new Progress("Downloading textures...", texturesDownloadQueue.size); - await promisepool.PromisePool - .for(Array.from(texturesDownloadQueue)) + await promisepool.PromisePool.for(Array.from(texturesDownloadQueue)) .withConcurrency(25) .process(async (fileDataId) => { await download("textures", `${fileDataId}.png`); @@ -347,8 +347,7 @@ async function downloadTextures(): Promise { async function downloadModels(): Promise { const progress = new Progress("Downloading models...", modelsDownloadQueue.size); - await promisepool.PromisePool - .for(Array.from(modelsDownloadQueue)) + await promisepool.PromisePool.for(Array.from(modelsDownloadQueue)) .withConcurrency(25) .process(async (fileDataId) => { await download("mo3", `${fileDataId}.mo3`); @@ -361,8 +360,7 @@ async function downloadModels(): Promise { async function downloadBones(): Promise { const progress = new Progress("Downloading bones...", bonesDownloadQueue.size); - await promisepool.PromisePool - .for(Array.from(bonesDownloadQueue)) + await promisepool.PromisePool.for(Array.from(bonesDownloadQueue)) .withConcurrency(25) .process(async (fileDataId) => { try { @@ -384,8 +382,7 @@ async function parseModels(): Promise { const files = await glob("data/mo3/*.mo3"); const progress = new Progress("Reading model files for texture references...", files.length); - await promisepool.PromisePool - .for(files) + await promisepool.PromisePool.for(files) .withConcurrency(20) .process(async (file) => { const buffer = await fsp.readFile(file); diff --git a/static/js/emblems.js b/static/js/emblems.js index ed1d9d3..cfce3aa 100644 --- a/static/js/emblems.js +++ b/static/js/emblems.js @@ -1,14 +1,16 @@ function waitForEmblemImages($emblem) { - return Promise.all($emblem.find(".images img").map((idx, img) => { - return new Promise((res, rej) => { - if (img.complete) { - res(); - } else { - img.addEventListener("load", res); - img.addEventListener("error", rej); - } - }); - })); + return Promise.all( + $emblem.find(".images img").map((idx, img) => { + return new Promise((res, rej) => { + if (img.complete) { + res(); + } else { + img.addEventListener("load", res); + img.addEventListener("error", rej); + } + }); + }), + ); } function createGuildEmblem(emblem, el) { @@ -16,7 +18,8 @@ function createGuildEmblem(emblem, el) { const canvas = $emblem.find("canvas")[0]; const ctx = canvas.getContext("2d"); - const imgUrl = (type, section, value, value2) => `${handlebarsData.websiteRoot}/img/guild-emblems/${type}_${value}${value2 ? ("_" + value2) : ""}_T${section}_U.PNG`; + const imgUrl = (type, section, value, value2) => + `${handlebarsData.websiteRoot}/img/guild-emblems/${type}_${value}${value2 ? "_" + value2 : ""}_T${section}_U.PNG`; const $images = $("
").addClass("images").appendTo($emblem); const bgUpper = $("").attr("src", imgUrl("Background", "U", emblem.background)).appendTo($images)[0]; @@ -64,7 +67,10 @@ function createArenaEmblem(teamSize, emblem, el) { const canvas = $emblem.find("canvas")[0]; const ctx = canvas.getContext("2d"); - const imgUrl = (teamSize, type, value) => `${handlebarsData.websiteRoot}/img/arena-banners/PVP-Banner${teamSize ? ("-" + teamSize) : ""}${type ? ("-" + type) : ""}${value ? ("-" + value) : ""}.PNG`; + const imgUrl = (teamSize, type, value) => + `${handlebarsData.websiteRoot}/img/arena-banners/PVP-Banner${teamSize ? "-" + teamSize : ""}${type ? "-" + type : ""}${ + value ? "-" + value : "" + }.PNG`; const $images = $("
").addClass("images").appendTo($emblem); const banner = $("").attr("src", imgUrl(teamSize)).appendTo($images)[0]; diff --git a/static/js/sync-url.js b/static/js/sync-url.js index cb2401a..a32d3dc 100644 --- a/static/js/sync-url.js +++ b/static/js/sync-url.js @@ -1,3 +1,6 @@ -window.parent.postMessage({ - url: window.location.pathname.replace(handlebarsData.websiteRoot, ""), -}, "*"); +window.parent.postMessage( + { + url: window.location.pathname.replace(handlebarsData.websiteRoot, ""), + }, + "*", +); diff --git a/tsconfig.json b/tsconfig.json index e6ec662..1af51b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,6 @@ "outDir": "build", "moduleResolution": "node" }, - "exclude": [ - "node_modules" - ], + "exclude": ["node_modules"], "include": ["src/**/*.ts"] }