chore: apply prettier on all files (#8)
* chore: apply prettier on all files
* chore: add prettier npm script
* Update .prettierrc
Co-authored-by: Axel Cocat <ax.cocat@gmail.com>
* Update .prettierignore
Co-authored-by: Axel Cocat <ax.cocat@gmail.com>
* Update .prettierignore
Co-authored-by: Axel Cocat <ax.cocat@gmail.com>
* Update .prettierignore
Co-authored-by: Axel Cocat <ax.cocat@gmail.com>
* chore: apply prettier with new conf
* Revert "chore: apply prettier with new conf"
This reverts commit db2a04c03f.
* chore: apply prettier correctly
* chore: update .prettierignore
* chore: restore viewer.min.js minification
* chore: apply again prettier
Co-authored-by: Stefano Borzi <stefano.borzi@fedex.com>
Co-authored-by: Axel Cocat <ax.cocat@gmail.com>
This commit is contained in:
parent
fe21209817
commit
8331e4dd73
15 changed files with 504 additions and 228 deletions
21
.prettierignore
Normal file
21
.prettierignore
Normal file
|
|
@ -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
|
||||||
9
.prettierrc
Normal file
9
.prettierrc
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"printWidth": 140,
|
||||||
|
"useTabs": true,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "always"
|
||||||
|
}
|
||||||
22
package-lock.json
generated
22
package-lock.json
generated
|
|
@ -41,6 +41,7 @@
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.0.0",
|
||||||
"nodemon": "^2.0.15",
|
"nodemon": "^2.0.15",
|
||||||
|
"prettier": "^2.6.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
|
|
@ -3644,6 +3645,21 @@
|
||||||
"node": ">=4"
|
"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": {
|
"node_modules/pretty-ms": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
|
||||||
|
|
@ -7983,6 +7999,12 @@
|
||||||
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
|
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
|
||||||
"dev": true
|
"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": {
|
"pretty-ms": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
"start": "node --expose-gc build/armory/main.js",
|
"start": "node --expose-gc build/armory/main.js",
|
||||||
"watch": "concurrently \"tsc -w --project .\" \"npm run nodemon\"",
|
"watch": "concurrently \"tsc -w --project .\" \"npm run nodemon\"",
|
||||||
"nodemon": "nodemon -q -w build -w config.json build/armory/main.js",
|
"nodemon": "nodemon -q -w build -w config.json build/armory/main.js",
|
||||||
|
"prettier": "prettier . -w",
|
||||||
"fetchdata": "node build/tools/fetchdata.js",
|
"fetchdata": "node build/tools/fetchdata.js",
|
||||||
"cleardata": "rimraf data/bone data/meta data/mo3 data/textures"
|
"cleardata": "rimraf data/bone data/meta data/mo3 data/textures"
|
||||||
},
|
},
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.0.0",
|
||||||
"nodemon": "^2.0.15",
|
"nodemon": "^2.0.15",
|
||||||
|
"prettier": "^2.6.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,9 @@ export class Armory {
|
||||||
}
|
}
|
||||||
app.locals.locals = locals;
|
app.locals.locals = locals;
|
||||||
|
|
||||||
app.engine(".hbs", handlebarsEngine({
|
app.engine(
|
||||||
|
".hbs",
|
||||||
|
handlebarsEngine({
|
||||||
extname: "hbs",
|
extname: "hbs",
|
||||||
partialsDir: path.join(process.cwd(), "static", "partials"),
|
partialsDir: path.join(process.cwd(), "static", "partials"),
|
||||||
layoutsDir: path.join(process.cwd(), "static"),
|
layoutsDir: path.join(process.cwd(), "static"),
|
||||||
|
|
@ -100,7 +102,8 @@ export class Armory {
|
||||||
helpers: {
|
helpers: {
|
||||||
...require("handlebars-helpers")(),
|
...require("handlebars-helpers")(),
|
||||||
},
|
},
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
app.set("view engine", "handlebars");
|
app.set("view engine", "handlebars");
|
||||||
app.set("views", path.join(process.cwd(), "static"));
|
app.set("views", path.join(process.cwd(), "static"));
|
||||||
|
|
||||||
|
|
@ -122,11 +125,13 @@ export class Armory {
|
||||||
}
|
}
|
||||||
return req.socket.remoteAddress;
|
return req.socket.remoteAddress;
|
||||||
});
|
});
|
||||||
app.use(morgan(":method :url :status - ID :id - IP :ip - :response-time ms", {
|
app.use(
|
||||||
|
morgan(":method :url :status - ID :id - IP :ip - :response-time ms", {
|
||||||
stream: {
|
stream: {
|
||||||
write: (msg) => this.logger.http(msg.trim()),
|
write: (msg) => this.logger.http(msg.trim()),
|
||||||
},
|
},
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
app.use("/js", express.static(`static/js`));
|
app.use("/js", express.static(`static/js`));
|
||||||
app.use("/css", express.static(`static/css`));
|
app.use("/css", express.static(`static/css`));
|
||||||
|
|
@ -198,7 +203,7 @@ export class Armory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getRealm(realm: string): IRealmConfig {
|
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<string> {
|
public async getDatabaseCharset(realm: string): Promise<string> {
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ export class Config {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
const key = Config.getEnvKey(parentName + i);
|
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) {
|
if (!found) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -131,10 +131,14 @@ export class Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getEnvKey(key: string): string {
|
private static getEnvKey(key: string): string {
|
||||||
return Config.envPrefix + "_" + key
|
return (
|
||||||
|
Config.envPrefix +
|
||||||
|
"_" +
|
||||||
|
key
|
||||||
.replace(/\./g, "__")
|
.replace(/\./g, "__")
|
||||||
.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)
|
.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
|
||||||
.toUpperCase();
|
.toUpperCase()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static parseEnvValue(value: string, model: any): any {
|
private static parseEnvValue(value: string, model: any): any {
|
||||||
|
|
@ -173,4 +177,4 @@ export class Config {
|
||||||
}
|
}
|
||||||
return missing;
|
return missing;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,22 +38,22 @@ export class DataTablesSsp {
|
||||||
private start: number;
|
private start: number;
|
||||||
private length: number;
|
private length: number;
|
||||||
private _order: {
|
private _order: {
|
||||||
column: number,
|
column: number;
|
||||||
dir: string,
|
dir: string;
|
||||||
}[];
|
}[];
|
||||||
private columns: {
|
private columns: {
|
||||||
data: number,
|
data: number;
|
||||||
name: string,
|
name: string;
|
||||||
searchable: boolean,
|
searchable: boolean;
|
||||||
orderable: boolean,
|
orderable: boolean;
|
||||||
search: {
|
search: {
|
||||||
value: string,
|
value: string;
|
||||||
regex: boolean,
|
regex: boolean;
|
||||||
}
|
};
|
||||||
}[];
|
}[];
|
||||||
private search: {
|
private search: {
|
||||||
value: string,
|
value: string;
|
||||||
regex: boolean,
|
regex: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
private wheres: string[] = [];
|
private wheres: string[] = [];
|
||||||
|
|
@ -69,10 +69,10 @@ export class DataTablesSsp {
|
||||||
this.start = parseInt(query.start as string, 10);
|
this.start = parseInt(query.start as string, 10);
|
||||||
this.length = parseInt(query.length as string, 10);
|
this.length = parseInt(query.length as string, 10);
|
||||||
this.draw = parseInt(query.draw as string, 10);
|
this.draw = parseInt(query.draw as string, 10);
|
||||||
this._order = (query.order as { column: string, dir: string }[])
|
this._order = (query.order as { column: string; dir: string }[]).map((order) => {
|
||||||
.map(order => { return { column: parseInt(order.column, 10), dir: order.dir, }; });
|
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 => {
|
this.columns = (query.columns as { data: string; name: string; searchable: string; orderable: string; search: any }[]).map((column) => {
|
||||||
return {
|
return {
|
||||||
data: parseInt(column.data, 10),
|
data: parseInt(column.data, 10),
|
||||||
name: column.name,
|
name: column.name,
|
||||||
|
|
@ -93,7 +93,7 @@ export class DataTablesSsp {
|
||||||
}
|
}
|
||||||
|
|
||||||
private colSettingsToStr(colSettings: IColumnSettings) {
|
private colSettingsToStr(colSettings: IColumnSettings) {
|
||||||
const db = colSettings.database ? ("`" + colSettings.database + "`.") : "";
|
const db = colSettings.database ? "`" + colSettings.database + "`." : "";
|
||||||
return `${db}\`${colSettings.table || this.table}\`.\`${colSettings.name}\``;
|
return `${db}\`${colSettings.table || this.table}\`.\`${colSettings.name}\``;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,19 +153,16 @@ export class DataTablesSsp {
|
||||||
this.filterBindings.push(`%${this.search.value}%`);
|
this.filterBindings.push(`%${this.search.value}%`);
|
||||||
}
|
}
|
||||||
if (filterWheres.length > 0) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sql(): string {
|
public sql(): string {
|
||||||
const columns = [
|
const columns = [...this.columnSettings.map((c) => this.colSettingsToStr(c)), ...this.extraDataColumns];
|
||||||
...this.columnSettings.map(c => this.colSettingsToStr(c)),
|
|
||||||
...this.extraDataColumns,
|
|
||||||
];
|
|
||||||
return `
|
return `
|
||||||
SELECT ${columns.join(", ")}
|
SELECT ${columns.join(", ")}
|
||||||
FROM ${this.table}
|
FROM ${this.table}
|
||||||
|
|
@ -199,10 +196,7 @@ export class DataTablesSsp {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(queryTimeout: number = 10_000): Promise<IResult> {
|
public async run(queryTimeout: number = 10_000): Promise<IResult> {
|
||||||
this.limit()
|
this.limit().order().join().filter();
|
||||||
.order()
|
|
||||||
.join()
|
|
||||||
.filter();
|
|
||||||
|
|
||||||
const bindings = [...this.filterBindings, ...this.customBindings];
|
const bindings = [...this.filterBindings, ...this.customBindings];
|
||||||
|
|
||||||
|
|
@ -226,7 +220,7 @@ export class DataTablesSsp {
|
||||||
values: bindings,
|
values: bindings,
|
||||||
timeout: queryTimeout,
|
timeout: queryTimeout,
|
||||||
});
|
});
|
||||||
rows = (rows as any[][]).map(row => {
|
rows = (rows as any[][]).map((row) => {
|
||||||
for (let i = 0; i < this.columnSettings.length; ++i) {
|
for (let i = 0; i < this.columnSettings.length; ++i) {
|
||||||
const col = this.columnSettings[i];
|
const col = this.columnSettings[i];
|
||||||
if (col.formatter !== undefined) {
|
if (col.formatter !== undefined) {
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ export class CharacterController {
|
||||||
this.itemInventoryTypes = {};
|
this.itemInventoryTypes = {};
|
||||||
const itemsRetail = await this.armory.dbc.itemRetail().toArray();
|
const itemsRetail = await this.armory.dbc.itemRetail().toArray();
|
||||||
for await (const item of this.armory.dbc.item()) {
|
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) {
|
if (retailItem !== undefined) {
|
||||||
this.itemInventoryTypes[item.id] = retailItem.inventoryType;
|
this.itemInventoryTypes[item.id] = retailItem.inventoryType;
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +109,7 @@ export class CharacterController {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.gemItems = {};
|
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;
|
this.gemItems[row.id] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,16 +127,17 @@ export class CharacterController {
|
||||||
this.itemSocketBonuses[row.entry] = row.socketBonus;
|
this.itemSocketBonuses[row.entry] = row.socketBonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mountSpells = await this.armory.dbc.spell()
|
const mountSpells = await this.armory.dbc
|
||||||
.filter(m => m.mechanic === SpellMechanicMounted)
|
.spell()
|
||||||
|
.filter((m) => m.mechanic === SpellMechanicMounted)
|
||||||
.toArray();
|
.toArray();
|
||||||
this.mountSpells = mountSpells.map(spell => spell.id);
|
this.mountSpells = mountSpells.map((spell) => spell.id);
|
||||||
this.mountBySpellId = {};
|
this.mountBySpellId = {};
|
||||||
for (const spell of mountSpells) {
|
for (const spell of mountSpells) {
|
||||||
const mount = await this.armory.dbc.mount().find(m => m.sourceSpellId === spell.id);
|
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 icon = await this.armory.dbc.spellIcon().find((icon) => icon.id === spell.spellIconId);
|
||||||
if (mount !== undefined) {
|
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) {
|
if (display !== undefined) {
|
||||||
this.mountBySpellId[spell.id] = {
|
this.mountBySpellId[spell.id] = {
|
||||||
creatureDisplayId: display.creatureDisplayInfoId,
|
creatureDisplayId: display.creatureDisplayInfoId,
|
||||||
|
|
@ -171,7 +172,7 @@ export class CharacterController {
|
||||||
|
|
||||||
const equipmentData = await this.getEquipmentData(realmName, charData.guid);
|
const equipmentData = await this.getEquipmentData(realmName, charData.guid);
|
||||||
const customization = this.getCustomizationOptions(charData);
|
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).icon = this.itemIcons[row.itemEntry];
|
||||||
(row as any).gems = this.getGemsFromEnchantments(row.enchantments);
|
(row as any).gems = this.getGemsFromEnchantments(row.enchantments);
|
||||||
(row as any).enchantments = this.filterEnchantments(row.itemEntry, row.enchantments);
|
(row as any).enchantments = this.filterEnchantments(row.itemEntry, row.enchantments);
|
||||||
|
|
@ -264,7 +265,7 @@ export class CharacterController {
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
categories: await this.armory.dbc.achievementCategory().toArray(),
|
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[];
|
const data = rows as RowDataPacket[] as IEquipmentData[];
|
||||||
|
|
||||||
for (const row of data) {
|
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.classId = item.classId;
|
||||||
row.subclassId = item.subclassId;
|
row.subclassId = item.subclassId;
|
||||||
}
|
}
|
||||||
|
|
@ -363,29 +364,27 @@ export class CharacterController {
|
||||||
timeout: this.armory.config.dbQueryTimeout,
|
timeout: this.armory.config.dbQueryTimeout,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (rows as RowDataPacket[])
|
return (rows as RowDataPacket[]).map((row) => this.mountBySpellId[row.spell]).filter((m) => m !== undefined);
|
||||||
.map(row => this.mountBySpellId[row.spell])
|
|
||||||
.filter(m => m !== undefined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getModelViewerItems(equipmentData: IEquipmentData[], charClass: number): Promise<number[][]> {
|
private async getModelViewerItems(equipmentData: IEquipmentData[], charClass: number): Promise<number[][]> {
|
||||||
if (charClass !== 3) {
|
if (charClass !== 3) {
|
||||||
// Keep ranged weapon only if the character is a hunter
|
// 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.
|
const visibleEquipment = equipmentData.filter(
|
||||||
filter(item =>
|
(item) =>
|
||||||
[0, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 16, 17, 18].includes(item.slot) && // visible slots
|
[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[][] = [];
|
const items: number[][] = [];
|
||||||
for (const equipment of visibleEquipment) {
|
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) {
|
if (modifiedAppearance === undefined) {
|
||||||
continue;
|
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) {
|
if (appearance === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -400,52 +399,53 @@ export class CharacterController {
|
||||||
return enchantments
|
return enchantments
|
||||||
.trim()
|
.trim()
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.map(enchant => parseInt(enchant))
|
.map((enchant) => parseInt(enchant))
|
||||||
.filter(enchant => enchant !== 0);
|
.filter((enchant) => enchant !== 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getGemsFromEnchantments(enchantments: string): number[] {
|
private getGemsFromEnchantments(enchantments: string): number[] {
|
||||||
return this.parseEnchantmentsString(enchantments)
|
return this.parseEnchantmentsString(enchantments)
|
||||||
.filter(enchant => enchant in this.enchantSrcItems && this.enchantSrcItems[enchant] in this.gemItems)
|
.filter((enchant) => enchant in this.enchantSrcItems && this.enchantSrcItems[enchant] in this.gemItems)
|
||||||
.map(enchant => this.enchantSrcItems[enchant]);
|
.map((enchant) => this.enchantSrcItems[enchant]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private filterEnchantments(item: number, enchantments: string): number[] {
|
private filterEnchantments(item: number, enchantments: string): number[] {
|
||||||
const socketBonus = this.itemSocketBonuses[item];
|
const socketBonus = this.itemSocketBonuses[item];
|
||||||
return this.parseEnchantmentsString(enchantments)
|
return this.parseEnchantmentsString(enchantments).filter(
|
||||||
.filter(enchant => enchant in this.enchantSrcItems && !(this.enchantSrcItems[enchant] in this.gemItems) && enchant !== socketBonus);
|
(enchant) => enchant in this.enchantSrcItems && !(this.enchantSrcItems[enchant] in this.gemItems) && enchant !== socketBonus,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCustomizationOptions(charData: ICharacterData): ICustomizationOption[] {
|
private getCustomizationOptions(charData: ICharacterData): ICustomizationOption[] {
|
||||||
const data = this.armory.characterCustomization.getCharacterCustomizationData(charData.race, charData.gender);
|
const data = this.armory.characterCustomization.getCharacterCustomizationData(charData.race, charData.gender);
|
||||||
const options = [];
|
const options = [];
|
||||||
const setOptionByChoiceIndex = (optionName: string, choiceIndex: number) => {
|
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) {
|
if (option !== undefined) {
|
||||||
const choice = option.Choices.find(choice => choice.OrderIndex === choiceIndex);
|
const choice = option.Choices.find((choice) => choice.OrderIndex === choiceIndex);
|
||||||
if (choice !== undefined) {
|
if (choice !== undefined) {
|
||||||
options.push({ optionId: option.Id, choiceId: choice.Id });
|
options.push({ optionId: option.Id, choiceId: choice.Id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const setOptionByChoiceName = (optionName: string, choiceName: string) => {
|
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) {
|
if (option !== undefined) {
|
||||||
const choice = option.Choices.find(ch => ch.Name === choiceName);
|
const choice = option.Choices.find((ch) => ch.Name === choiceName);
|
||||||
if (choice !== undefined) {
|
if (choice !== undefined) {
|
||||||
options.push({ optionId: option.Id, choiceId: choice.Id });
|
options.push({ optionId: option.Id, choiceId: choice.Id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const setOptionByChoiceId = (optionName: string, choiceId: number) => {
|
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) {
|
if (option !== undefined) {
|
||||||
options.push({ optionId: option.Id, choiceId: choiceId });
|
options.push({ optionId: option.Id, choiceId: choiceId });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const optionMapping = {
|
const optionMapping = {
|
||||||
"Face": charData.face,
|
Face: charData.face,
|
||||||
"Skin Color": charData.skin,
|
"Skin Color": charData.skin,
|
||||||
"Hair Style": charData.hairStyle,
|
"Hair Style": charData.hairStyle,
|
||||||
"Hair Color": charData.hairColor,
|
"Hair Color": charData.hairColor,
|
||||||
|
|
@ -458,19 +458,54 @@ export class CharacterController {
|
||||||
switch (charData.race) {
|
switch (charData.race) {
|
||||||
case 1: // Human
|
case 1: // Human
|
||||||
if (charData.gender === 0) {
|
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(
|
||||||
setOptionByChoiceName("Beard", { 0: "Short", 1: "Chin Puff", 2: "Soul Patch", 3: "Goatee", 4: "Goatee", 5: "None", 6: "Goatee", 7: "None", 8: "None" }[charData.facialStyle]);
|
"Mustache",
|
||||||
setOptionByChoiceName("Sideburns", { 0: "Medium", 1: "None", 2: "None", 3: "Medium", 4: "Long", 5: "Long", 6: "None", 8: "None", 7: "None" }[charData.facialStyle]);
|
{ 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("Eyebrows", "Natural");
|
||||||
setOptionByChoiceName("Face Shape", "Narrow");
|
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 {
|
} else {
|
||||||
setOptionByChoiceIndex("Piercings", charData.facialStyle);
|
setOptionByChoiceIndex("Piercings", charData.facialStyle);
|
||||||
setOptionByChoiceName("Eyebrows", "Natural");
|
setOptionByChoiceName("Eyebrows", "Natural");
|
||||||
setOptionByChoiceName("Face Shape", "Narrow");
|
setOptionByChoiceName("Face Shape", "Narrow");
|
||||||
setOptionByChoiceName("Makeup", "None");
|
setOptionByChoiceName("Makeup", "None");
|
||||||
setOptionByChoiceName("Necklace", "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) {
|
if (charData.class === 6) {
|
||||||
// Death Knight
|
// Death Knight
|
||||||
|
|
@ -482,14 +517,32 @@ export class CharacterController {
|
||||||
setOptionByChoiceIndex("Tattoo Color", 0);
|
setOptionByChoiceIndex("Tattoo Color", 0);
|
||||||
setOptionByChoiceIndex("Eyebrows", 0);
|
setOptionByChoiceIndex("Eyebrows", 0);
|
||||||
if (charData.gender === 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);
|
setOptionByChoiceIndex("Beard", charData.facialStyle);
|
||||||
setOptionByChoiceName("Earrings", "None");
|
setOptionByChoiceName("Earrings", "None");
|
||||||
setOptionByChoiceName("Nose Ring", "None");
|
setOptionByChoiceName("Nose Ring", "None");
|
||||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||||
} else {
|
} else {
|
||||||
setOptionByChoiceIndex("Earrings", { 0: 0, 1: 1, 2: 2, 3: 3, 4: 0, 5: 4 }[charData.facialStyle]);
|
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
|
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||||
}
|
}
|
||||||
if (charData.class === 6) {
|
if (charData.class === 6) {
|
||||||
|
|
@ -519,7 +572,10 @@ export class CharacterController {
|
||||||
setOptionByChoiceName("Ears", "Thin");
|
setOptionByChoiceName("Ears", "Thin");
|
||||||
setOptionByChoiceName("Scars", "None");
|
setOptionByChoiceName("Scars", "None");
|
||||||
if (charData.gender === 0) {
|
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("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("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]);
|
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("Horn Decoration", "None");
|
||||||
setOptionByChoiceName("Tail", charData.gender === 0 ? "Long" : "Short");
|
setOptionByChoiceName("Tail", charData.gender === 0 ? "Long" : "Short");
|
||||||
if (charData.gender === 0) {
|
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(
|
||||||
setOptionByChoiceName("Tendrils", { 0: "None", 1: "Splayed", 2: "Double", 3: "Fanned", 4: "Single", 5: "Paired", 6: "Uniform", 7: "Twin" }[charData.facialStyle]);
|
"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 {
|
} 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) {
|
if (charData.class === 6) {
|
||||||
// Death Knight
|
// Death Knight
|
||||||
|
|
@ -568,8 +635,28 @@ export class CharacterController {
|
||||||
setOptionByChoiceName("War Paint", "None");
|
setOptionByChoiceName("War Paint", "None");
|
||||||
setOptionByChoiceName("War Paint Color", "None");
|
setOptionByChoiceName("War Paint Color", "None");
|
||||||
if (charData.gender === 0) {
|
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(
|
||||||
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]);
|
"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("Earrings", "None");
|
||||||
setOptionByChoiceName("Nose Ring", "None");
|
setOptionByChoiceName("Nose Ring", "None");
|
||||||
setOptionByChoiceName("Tusks", "Natural");
|
setOptionByChoiceName("Tusks", "Natural");
|
||||||
|
|
@ -589,13 +676,71 @@ export class CharacterController {
|
||||||
case 5: // Undead
|
case 5: // Undead
|
||||||
setOptionByChoiceName("Skin Type", "Bony");
|
setOptionByChoiceName("Skin Type", "Bony");
|
||||||
if (charData.gender === 0) {
|
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]);
|
setOptionByChoiceName(
|
||||||
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]);
|
"Jaw Features",
|
||||||
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]);
|
{
|
||||||
|
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 {
|
} else {
|
||||||
setOptionByChoiceName("Face Features", { 0: "None", 1: "None", 2: "Strapped", 3: "Rotting", 4: "None", 5: "None", 6: "None", 7: "Putrid" }[charData.facialStyle]);
|
setOptionByChoiceName(
|
||||||
setOptionByChoiceName("Jaw Features", { 0: "Intact", 1: "Stitched", 2: "Intact", 3: "Intact", 4: "Bonejawed", 5: "Toothy", 6: "Cheeky", 7: "Intact" }[charData.facialStyle]);
|
"Face Features",
|
||||||
setOptionByChoiceId("Eye Color", { 0: 5337, 1: 5337, 2: 6305, 3: 5337, 4: 5337, 5: 6305, 6: 5337, 7: 5337 }[charData.facialStyle]);
|
{ 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) {
|
if (charData.class === 6) {
|
||||||
// Death Knight
|
// Death Knight
|
||||||
|
|
@ -614,9 +759,18 @@ export class CharacterController {
|
||||||
setOptionByChoiceName("Body Paint", "None");
|
setOptionByChoiceName("Body Paint", "None");
|
||||||
setOptionByChoiceIndex("Paint Color", 0);
|
setOptionByChoiceIndex("Paint Color", 0);
|
||||||
if (charData.gender === 0) {
|
if (charData.gender === 0) {
|
||||||
setOptionByChoiceName("Hair", { 0: "Mane", 1: "Braids", 2: "Chops", 3: "Sideburns", 4: "Mane", 5: "Wrapped", 6: "Braids" }[charData.facialStyle]);
|
setOptionByChoiceName(
|
||||||
setOptionByChoiceName("Facial Hair", { 0: "Clean", 1: "Braid", 2: "Beard", 3: "Wrapped", 4: "Curtain", 5: "Clean", 6: "Split" }[charData.facialStyle]);
|
"Hair",
|
||||||
setOptionByChoiceName("Nose Ring", { 0: "None", 1: "Small", 2: "Open", 3: "None", 4: "None", 5: "Bead", 6: "Open" }[charData.facialStyle]);
|
{ 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
|
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||||
} else {
|
} else {
|
||||||
setOptionByChoiceIndex("Hair", charData.facialStyle);
|
setOptionByChoiceIndex("Hair", charData.facialStyle);
|
||||||
|
|
@ -634,8 +788,38 @@ export class CharacterController {
|
||||||
setOptionByChoiceName("Body Paint Color", "None");
|
setOptionByChoiceName("Body Paint Color", "None");
|
||||||
setOptionByChoiceName("Piercing", "None");
|
setOptionByChoiceName("Piercing", "None");
|
||||||
if (charData.gender === 0) {
|
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(
|
||||||
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]);
|
"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);
|
setOptionByChoiceIndex("Face Paint Color", charData.hairColor + 1);
|
||||||
setOptionByChoiceName("Earrings", "None");
|
setOptionByChoiceName("Earrings", "None");
|
||||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||||
|
|
@ -712,16 +896,18 @@ export class CharacterController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTalentTrees(classId: number) {
|
private async getTalentTrees(classId: number) {
|
||||||
const items = await this.armory.dbc.talentTab()
|
const items = await this.armory.dbc
|
||||||
.filter(tab => tab.classMask === Math.pow(2, classId - 1))
|
.talentTab()
|
||||||
.map(async tab => {
|
.filter((tab) => tab.classMask === Math.pow(2, classId - 1))
|
||||||
const icon = await this.armory.dbc.spellIcon().find(icon => icon.id === tab.spellIconId);
|
.map(async (tab) => {
|
||||||
const spells = await this.armory.dbc.talent()
|
const icon = await this.armory.dbc.spellIcon().find((icon) => icon.id === tab.spellIconId);
|
||||||
.filter(row => row.tabId === tab.id)
|
const spells = await this.armory.dbc
|
||||||
.map(async row => {
|
.talent()
|
||||||
const spell = await this.armory.dbc.spell().find(spell => spell.id === row.spellRank0);
|
.filter((row) => row.tabId === tab.id)
|
||||||
const icon = await this.armory.dbc.spellIcon().find(icon => icon.id === spell?.spellIconId);
|
.map(async (row) => {
|
||||||
return { ...row, icon: this.processSpellIconTexture(icon?.textureFilename ?? ""), };
|
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();
|
.toArray();
|
||||||
return {
|
return {
|
||||||
|
|
@ -735,11 +921,7 @@ export class CharacterController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private processSpellIconTexture(texturePath: string): string {
|
private processSpellIconTexture(texturePath: string): string {
|
||||||
return texturePath
|
return texturePath.toLowerCase().replace("interface\\icons\\", "").replace("interface\\spellbook\\", "").replace(/\.$/, "");
|
||||||
.toLowerCase()
|
|
||||||
.replace("interface\\icons\\", "")
|
|
||||||
.replace("interface\\spellbook\\", "")
|
|
||||||
.replace(/\.$/, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getGlyphs(realm: string, character: number): Promise<any[][]> {
|
private async getGlyphs(realm: string, character: number): Promise<any[][]> {
|
||||||
|
|
@ -755,9 +937,9 @@ export class CharacterController {
|
||||||
|
|
||||||
const glyphs = [[], []];
|
const glyphs = [[], []];
|
||||||
for (const row of rows as RowDataPacket[]) {
|
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) {
|
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) {
|
if (glyph === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -768,11 +950,12 @@ export class CharacterController {
|
||||||
return glyphs;
|
return glyphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getAchievements(realm: string, charData: ICharacterData): Promise<{ achievements: any[]; earned: { [key: number]: any }; }> {
|
private async getAchievements(realm: string, charData: ICharacterData): Promise<{ achievements: any[]; earned: { [key: number]: any } }> {
|
||||||
const promises = await this.armory.dbc.achievement()
|
const promises = await this.armory.dbc
|
||||||
.filter(ach => ach.faction === -1 || ach.faction === Utils.getFactionFromRaceId(charData.race))
|
.achievement()
|
||||||
|
.filter((ach) => ach.faction === -1 || ach.faction === Utils.getFactionFromRaceId(charData.race))
|
||||||
.map(async (ach) => {
|
.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 {
|
return {
|
||||||
id: ach.id,
|
id: ach.id,
|
||||||
category: ach.category,
|
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({
|
const [rows, fields] = await this.armory.getCharactersDb(realm).query({
|
||||||
sql: `
|
sql: `
|
||||||
SELECT totalKills, todayKills, yesterdayKills
|
SELECT totalKills, todayKills, yesterdayKills
|
||||||
|
|
@ -841,7 +1024,7 @@ export class CharacterController {
|
||||||
timeout: this.armory.config.dbQueryTimeout,
|
timeout: this.armory.config.dbQueryTimeout,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (rows as RowDataPacket[]).map(row => {
|
return (rows as RowDataPacket[]).map((row) => {
|
||||||
row.emblem = Utils.makeEmblemObject(row, false);
|
row.emblem = Utils.makeEmblemObject(row, false);
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -64,24 +64,28 @@ export class GuildController {
|
||||||
{ name: "name", table: "characters", collation: `${charSet}_general_ci` },
|
{ name: "name", table: "characters", collation: `${charSet}_general_ci` },
|
||||||
{ name: "rank" },
|
{ name: "rank" },
|
||||||
{ name: "level", table: "characters" },
|
{ 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: "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 = [
|
ssp.joins = [{ table1: "guild_member", column1: "guid", table2: "characters", column2: "guid", kind: "LEFT" }];
|
||||||
{ table1: "guild_member", column1: "guid", table2: "characters", column2: "guid", kind: "LEFT" },
|
|
||||||
];
|
|
||||||
ssp.extraDataColumns = ["`characters`.`gender`"];
|
ssp.extraDataColumns = ["`characters`.`gender`"];
|
||||||
|
|
||||||
if (this.armory.config.hideGameMasters) {
|
if (this.armory.config.hideGameMasters) {
|
||||||
ssp.joins.push({ table1: "characters", column1: "account", table2: "account_access", column2: "id", database2: realm.authDatabase, kind: "LEFT" });
|
ssp.joins.push({
|
||||||
ssp = ssp.where(`\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`);
|
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
|
const result = await ssp.where("`guildid` = ?", guildId).where("`deleteInfos_Account` IS NULL").run(this.armory.config.dbQueryTimeout);
|
||||||
.where("`guildid` = ?", guildId)
|
|
||||||
.where("`deleteInfos_Account` IS NULL")
|
|
||||||
.run(this.armory.config.dbQueryTimeout);
|
|
||||||
|
|
||||||
const ranks = await this.getGuildRanks(realm, guildId);
|
const ranks = await this.getGuildRanks(realm, guildId);
|
||||||
(result as any).ranks = {};
|
(result as any).ranks = {};
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,13 @@ export class IndexController {
|
||||||
public async index(req: express.Request, res: express.Response): Promise<void> {
|
public async index(req: express.Request, res: express.Response): Promise<void> {
|
||||||
res.render("index.hbs", {
|
res.render("index.hbs", {
|
||||||
title: "Armory",
|
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<void> {
|
public async search(req: express.Request, res: express.Response, next: express.NextFunction): Promise<void> {
|
||||||
const realmName = req.query.realm as string;
|
const realmName = req.query.realm as string;
|
||||||
const realm = realmName === undefined ?
|
const realm = realmName === undefined ? this.armory.config.realms[0] : this.armory.config.realms.find((r) => r.name === realmName);
|
||||||
this.armory.config.realms[0] :
|
|
||||||
this.armory.config.realms.find(r => r.name === realmName);
|
|
||||||
if (realm === undefined) {
|
if (realm === undefined) {
|
||||||
return next(400);
|
return next(400);
|
||||||
}
|
}
|
||||||
|
|
@ -34,9 +32,9 @@ export class IndexController {
|
||||||
{ name: "name", collation: `${charSet}_general_ci` },
|
{ name: "name", collation: `${charSet}_general_ci` },
|
||||||
{ table: "guild", name: "name" },
|
{ table: "guild", name: "name" },
|
||||||
{ name: "level" },
|
{ 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: "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 = [
|
ssp.joins = [
|
||||||
{ table1: "characters", column1: "guid", table2: "guild_member", column2: "guid", kind: "LEFT" },
|
{ table1: "characters", column1: "guid", table2: "guild_member", column2: "guid", kind: "LEFT" },
|
||||||
|
|
@ -45,13 +43,20 @@ export class IndexController {
|
||||||
ssp.extraDataColumns = ["`characters`.`gender`"];
|
ssp.extraDataColumns = ["`characters`.`gender`"];
|
||||||
|
|
||||||
if (this.armory.config.hideGameMasters) {
|
if (this.armory.config.hideGameMasters) {
|
||||||
ssp.joins.push({ table1: "characters", column1: "account", table2: "account_access", column2: "id", database2: realm.authDatabase, kind: "LEFT" });
|
ssp.joins.push({
|
||||||
ssp = ssp.where(`\`account_access\`.\`id\` IS NULL OR \`account_access\`.\`RealmID\` NOT IN (-1, ${realm.realmId}) OR \`account_access\`.\`gmlevel\` = 0`);
|
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
|
const result = await ssp.where("`deleteInfos_Account` IS NULL").run(this.armory.config.dbQueryTimeout);
|
||||||
.where("`deleteInfos_Account` IS NULL")
|
|
||||||
.run(this.armory.config.dbQueryTimeout);
|
|
||||||
(result as any).realm = realm.name;
|
(result as any).realm = realm.name;
|
||||||
|
|
||||||
res.json(result);
|
res.json(result);
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,13 @@ class AsyncGenWrapper<T> implements IAsyncGeneratorWithArrayMethods<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static from<T>(array: T[]): AsyncGenWrapper<T> {
|
public static from<T>(array: T[]): AsyncGenWrapper<T> {
|
||||||
return new AsyncGenWrapper<T>(async function* () {
|
return new AsyncGenWrapper<T>(
|
||||||
|
(async function* () {
|
||||||
for (const x of array) {
|
for (const x of array) {
|
||||||
yield x;
|
yield x;
|
||||||
}
|
}
|
||||||
}());
|
})(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async *[Symbol.asyncIterator](): AsyncGenerator<T> {
|
public async *[Symbol.asyncIterator](): AsyncGenerator<T> {
|
||||||
|
|
@ -217,11 +219,10 @@ class DbcReader<T> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerCols = headerLine.value
|
const headerCols = headerLine.value.map((header) => camelCase(header).replace(/[\[\]]/g, ""));
|
||||||
.map(header => camelCase(header).replace(/[\[\]]/g, ""));
|
|
||||||
|
|
||||||
for await (const arr of itr) {
|
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 = {};
|
const row = {};
|
||||||
headerCols.forEach((header, headerIdx) => {
|
headerCols.forEach((header, headerIdx) => {
|
||||||
if (this.fields.length === 0 || this.fields.includes(header)) {
|
if (this.fields.length === 0 || this.fields.includes(header)) {
|
||||||
|
|
@ -242,7 +243,8 @@ class DbcReader<T> {
|
||||||
const str = chunk.toString();
|
const str = chunk.toString();
|
||||||
// Iterate over each character, keep track of current column (of the returned array)
|
// Iterate over each character, keep track of current column (of the returned array)
|
||||||
for (let c = 0; c < str.length; ++c) {
|
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)) {
|
if (!(col in arr)) {
|
||||||
arr[col] = ""; // Create a new column (start with empty string) if necessary
|
arr[col] = ""; // Create a new column (start with empty string) if necessary
|
||||||
}
|
}
|
||||||
|
|
@ -263,14 +265,14 @@ class DbcReader<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a comma and we're not in a quoted field, move on to the next column
|
// 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;
|
++col;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a newline (CRLF) and we're not in a quoted field, skip the next character
|
// 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
|
// 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;
|
yield arr;
|
||||||
arr.length = 0; // Clear the row
|
arr.length = 0; // Clear the row
|
||||||
col = 0;
|
col = 0;
|
||||||
|
|
@ -280,7 +282,7 @@ class DbcReader<T> {
|
||||||
|
|
||||||
// If it's a newline (LF or CR) and we're not in a quoted field,
|
// 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
|
// 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;
|
yield arr;
|
||||||
arr.length = 0; // Clear the row
|
arr.length = 0; // Clear the row
|
||||||
col = 0;
|
col = 0;
|
||||||
|
|
@ -327,7 +329,19 @@ const dbcFields = {
|
||||||
spell: ["id", "mechanic", "spellIconId"],
|
spell: ["id", "mechanic", "spellIconId"],
|
||||||
spellItemEnchantment: ["id", "srcItemId"],
|
spellItemEnchantment: ["id", "srcItemId"],
|
||||||
spellIcon: ["id", "textureFilename"],
|
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"],
|
talentTab: ["id", "nameLang0", "spellIconId", "classMask"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -350,17 +364,26 @@ export class DbcManager {
|
||||||
|
|
||||||
public async loadAllFiles(): Promise<void> {
|
public async loadAllFiles(): Promise<void> {
|
||||||
this._achievement = await this.read<IAchievement>(DbcFiles.achievement, dbcFields.achievement).toArray();
|
this._achievement = await this.read<IAchievement>(DbcFiles.achievement, dbcFields.achievement).toArray();
|
||||||
this._achievementCategory = await this.read<IAchievementCategory>(DbcFiles.achievementCategory, dbcFields.achievementCategory).toArray();
|
this._achievementCategory = await this.read<IAchievementCategory>(
|
||||||
|
DbcFiles.achievementCategory,
|
||||||
|
dbcFields.achievementCategory,
|
||||||
|
).toArray();
|
||||||
this._glyphProperties = await this.read<IGlyphProperties>(DbcFiles.glyphProperties, dbcFields.glyphProperties).toArray();
|
this._glyphProperties = await this.read<IGlyphProperties>(DbcFiles.glyphProperties, dbcFields.glyphProperties).toArray();
|
||||||
this._item = await this.read<IItemDbc>(DbcFiles.item, dbcFields.item).toArray();
|
this._item = await this.read<IItemDbc>(DbcFiles.item, dbcFields.item).toArray();
|
||||||
this._itemRetail = await this.read<IItemRetailDbc>(DbcFiles.itemRetail, dbcFields.itemRetail).toArray();
|
this._itemRetail = await this.read<IItemRetailDbc>(DbcFiles.itemRetail, dbcFields.itemRetail).toArray();
|
||||||
this._itemAppearance = await this.read<IItemAppearanceDbc>(DbcFiles.itemAppearance, dbcFields.itemAppearance).toArray();
|
this._itemAppearance = await this.read<IItemAppearanceDbc>(DbcFiles.itemAppearance, dbcFields.itemAppearance).toArray();
|
||||||
this._itemModifiedAppearance = await this.read<IItemModifiedAppearanceDbc>(DbcFiles.itemModifiedAppearance, dbcFields.itemModifiedAppearance).toArray();
|
this._itemModifiedAppearance = await this.read<IItemModifiedAppearanceDbc>(
|
||||||
|
DbcFiles.itemModifiedAppearance,
|
||||||
|
dbcFields.itemModifiedAppearance,
|
||||||
|
).toArray();
|
||||||
this._itemDisplayInfo = await this.read<IItemDisplayInfoDbc>(DbcFiles.itemDisplayInfo, dbcFields.itemDisplayInfo).toArray();
|
this._itemDisplayInfo = await this.read<IItemDisplayInfoDbc>(DbcFiles.itemDisplayInfo, dbcFields.itemDisplayInfo).toArray();
|
||||||
this._mount = await this.read<IMountDbc>(DbcFiles.mount, dbcFields.mount).toArray();
|
this._mount = await this.read<IMountDbc>(DbcFiles.mount, dbcFields.mount).toArray();
|
||||||
this._mountDisplay = await this.read<IMountXDisplayDbc>(DbcFiles.mountDisplay, dbcFields.mountDisplay).toArray();
|
this._mountDisplay = await this.read<IMountXDisplayDbc>(DbcFiles.mountDisplay, dbcFields.mountDisplay).toArray();
|
||||||
this._spell = await this.read<ISpellDbc>(DbcFiles.spell, dbcFields.spell).toArray();
|
this._spell = await this.read<ISpellDbc>(DbcFiles.spell, dbcFields.spell).toArray();
|
||||||
this._spellItemEnchantment = await this.read<ISpellItemEnchantmentDbc>(DbcFiles.spellItemEnchantment, dbcFields.spellItemEnchantment).toArray();
|
this._spellItemEnchantment = await this.read<ISpellItemEnchantmentDbc>(
|
||||||
|
DbcFiles.spellItemEnchantment,
|
||||||
|
dbcFields.spellItemEnchantment,
|
||||||
|
).toArray();
|
||||||
this._spellIcon = await this.read<ISpellIcon>(DbcFiles.spellIcon, dbcFields.spellIcon).toArray();
|
this._spellIcon = await this.read<ISpellIcon>(DbcFiles.spellIcon, dbcFields.spellIcon).toArray();
|
||||||
this._talent = await this.read<ITalent>(DbcFiles.talent, dbcFields.talent).toArray();
|
this._talent = await this.read<ITalent>(DbcFiles.talent, dbcFields.talent).toArray();
|
||||||
this._talentTab = await this.read<ITalentTab>(DbcFiles.talentTab, dbcFields.talentTab).toArray();
|
this._talentTab = await this.read<ITalentTab>(DbcFiles.talentTab, dbcFields.talentTab).toArray();
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,12 @@ class Progress {
|
||||||
}
|
}
|
||||||
|
|
||||||
private createProgressBar(text: string, total: number): cliProgress.SingleBar {
|
private createProgressBar(text: string, total: number): cliProgress.SingleBar {
|
||||||
const progress = new cliProgress.SingleBar({
|
const progress = new cliProgress.SingleBar(
|
||||||
|
{
|
||||||
format: `${text} {bar} {percentage}% ({value} / {total})`,
|
format: `${text} {bar} {percentage}% ({value} / {total})`,
|
||||||
}, cliProgress.Presets.shades_classic);
|
},
|
||||||
|
cliProgress.Presets.shades_classic,
|
||||||
|
);
|
||||||
progress.start(total, 0);
|
progress.start(total, 0);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
@ -163,25 +166,13 @@ function queueTexturesAndModels(item: any): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadRaces(): Promise<void> {
|
async function downloadRaces(): Promise<void> {
|
||||||
const races = [
|
const races = ["human", "nightelf", "dwarf", "gnome", "draenei", "orc", "troll", "tauren", "bloodelf", "scourge"];
|
||||||
"human",
|
|
||||||
"nightelf",
|
|
||||||
"dwarf",
|
|
||||||
"gnome",
|
|
||||||
"draenei",
|
|
||||||
"orc",
|
|
||||||
"troll",
|
|
||||||
"tauren",
|
|
||||||
"bloodelf",
|
|
||||||
"scourge",
|
|
||||||
];
|
|
||||||
const genders = ["male", "female"];
|
const genders = ["male", "female"];
|
||||||
const raceGenderCombo = races.map((race) => [race + genders[0], race + genders[1]]).flat();
|
const raceGenderCombo = races.map((race) => [race + genders[0], race + genders[1]]).flat();
|
||||||
|
|
||||||
const progress = new Progress("Downloading races data...", raceGenderCombo.length);
|
const progress = new Progress("Downloading races data...", raceGenderCombo.length);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(raceGenderCombo)
|
||||||
.for(raceGenderCombo)
|
|
||||||
.withConcurrency(4)
|
.withConcurrency(4)
|
||||||
.process(async (race) => {
|
.process(async (race) => {
|
||||||
const characterJson = await download("meta/character", `${race}.json`);
|
const characterJson = await download("meta/character", `${race}.json`);
|
||||||
|
|
@ -191,7 +182,11 @@ async function downloadRaces(): Promise<void> {
|
||||||
for (const option of customizationJson.Options) {
|
for (const option of customizationJson.Options) {
|
||||||
for (const choice of option.Choices) {
|
for (const choice of option.Choices) {
|
||||||
for (const element of choice.Elements) {
|
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);
|
modelsDownloadQueue.add(element.SkinnedModel.CollectionFileDataID);
|
||||||
}
|
}
|
||||||
if (element.BoneSet !== null && typeof element.BoneSet.BoneFileDataID === "number" && element.BoneSet.BoneFileDataID !== 0) {
|
if (element.BoneSet !== null && typeof element.BoneSet.BoneFileDataID === "number" && element.BoneSet.BoneFileDataID !== 0) {
|
||||||
|
|
@ -202,7 +197,7 @@ async function downloadRaces(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const textureFiles = Object.keys(customizationJson.TextureFiles)
|
const textureFiles = Object.keys(customizationJson.TextureFiles)
|
||||||
.map(key => customizationJson.TextureFiles[key])
|
.map((key) => customizationJson.TextureFiles[key])
|
||||||
.flat();
|
.flat();
|
||||||
for (const file of textureFiles) {
|
for (const file of textureFiles) {
|
||||||
texturesDownloadQueue.add(file.FileDataId);
|
texturesDownloadQueue.add(file.FileDataId);
|
||||||
|
|
@ -215,12 +210,14 @@ async function downloadRaces(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadArmors(): Promise<void> {
|
async function downloadArmors(): Promise<void> {
|
||||||
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);
|
const progress = new Progress("Downloading armor data...", rows.length);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(rows)
|
||||||
.for(rows)
|
|
||||||
.withConcurrency(50)
|
.withConcurrency(50)
|
||||||
.process(async (row) => {
|
.process(async (row) => {
|
||||||
const modifiedAppearance = dbcItemModifiedAppearanceByItemId[row.id];
|
const modifiedAppearance = dbcItemModifiedAppearanceByItemId[row.id];
|
||||||
|
|
@ -247,12 +244,14 @@ async function downloadArmors(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadWeapons(): Promise<void> {
|
async function downloadWeapons(): Promise<void> {
|
||||||
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);
|
const progress = new Progress("Downloading weapon data...", rows.length);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(rows)
|
||||||
.for(rows)
|
|
||||||
.withConcurrency(50)
|
.withConcurrency(50)
|
||||||
.process(async (row) => {
|
.process(async (row) => {
|
||||||
const modifiedAppearance = dbcItemModifiedAppearanceByItemId[row.id];
|
const modifiedAppearance = dbcItemModifiedAppearanceByItemId[row.id];
|
||||||
|
|
@ -307,11 +306,13 @@ async function readDbcData(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadMounts(): Promise<void> {
|
async function downloadMounts(): Promise<void> {
|
||||||
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);
|
const progress = new Progress("Downloading mount data...", mountSpells.length);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(mountSpells)
|
||||||
.for(mountSpells)
|
|
||||||
.withConcurrency(50)
|
.withConcurrency(50)
|
||||||
.process(async (spell) => {
|
.process(async (spell) => {
|
||||||
const mount = dbcMountBySourceSpellId[spell.id];
|
const mount = dbcMountBySourceSpellId[spell.id];
|
||||||
|
|
@ -333,8 +334,7 @@ async function downloadMounts(): Promise<void> {
|
||||||
async function downloadTextures(): Promise<void> {
|
async function downloadTextures(): Promise<void> {
|
||||||
const progress = new Progress("Downloading textures...", texturesDownloadQueue.size);
|
const progress = new Progress("Downloading textures...", texturesDownloadQueue.size);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(Array.from(texturesDownloadQueue))
|
||||||
.for(Array.from(texturesDownloadQueue))
|
|
||||||
.withConcurrency(25)
|
.withConcurrency(25)
|
||||||
.process(async (fileDataId) => {
|
.process(async (fileDataId) => {
|
||||||
await download("textures", `${fileDataId}.png`);
|
await download("textures", `${fileDataId}.png`);
|
||||||
|
|
@ -347,8 +347,7 @@ async function downloadTextures(): Promise<void> {
|
||||||
async function downloadModels(): Promise<void> {
|
async function downloadModels(): Promise<void> {
|
||||||
const progress = new Progress("Downloading models...", modelsDownloadQueue.size);
|
const progress = new Progress("Downloading models...", modelsDownloadQueue.size);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(Array.from(modelsDownloadQueue))
|
||||||
.for(Array.from(modelsDownloadQueue))
|
|
||||||
.withConcurrency(25)
|
.withConcurrency(25)
|
||||||
.process(async (fileDataId) => {
|
.process(async (fileDataId) => {
|
||||||
await download("mo3", `${fileDataId}.mo3`);
|
await download("mo3", `${fileDataId}.mo3`);
|
||||||
|
|
@ -361,8 +360,7 @@ async function downloadModels(): Promise<void> {
|
||||||
async function downloadBones(): Promise<void> {
|
async function downloadBones(): Promise<void> {
|
||||||
const progress = new Progress("Downloading bones...", bonesDownloadQueue.size);
|
const progress = new Progress("Downloading bones...", bonesDownloadQueue.size);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(Array.from(bonesDownloadQueue))
|
||||||
.for(Array.from(bonesDownloadQueue))
|
|
||||||
.withConcurrency(25)
|
.withConcurrency(25)
|
||||||
.process(async (fileDataId) => {
|
.process(async (fileDataId) => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -384,8 +382,7 @@ async function parseModels(): Promise<void> {
|
||||||
const files = await glob("data/mo3/*.mo3");
|
const files = await glob("data/mo3/*.mo3");
|
||||||
const progress = new Progress("Reading model files for texture references...", files.length);
|
const progress = new Progress("Reading model files for texture references...", files.length);
|
||||||
|
|
||||||
await promisepool.PromisePool
|
await promisepool.PromisePool.for(files)
|
||||||
.for(files)
|
|
||||||
.withConcurrency(20)
|
.withConcurrency(20)
|
||||||
.process(async (file) => {
|
.process(async (file) => {
|
||||||
const buffer = await fsp.readFile(file);
|
const buffer = await fsp.readFile(file);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
function waitForEmblemImages($emblem) {
|
function waitForEmblemImages($emblem) {
|
||||||
return Promise.all($emblem.find(".images img").map((idx, img) => {
|
return Promise.all(
|
||||||
|
$emblem.find(".images img").map((idx, img) => {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
if (img.complete) {
|
if (img.complete) {
|
||||||
res();
|
res();
|
||||||
|
|
@ -8,7 +9,8 @@ function waitForEmblemImages($emblem) {
|
||||||
img.addEventListener("error", rej);
|
img.addEventListener("error", rej);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGuildEmblem(emblem, el) {
|
function createGuildEmblem(emblem, el) {
|
||||||
|
|
@ -16,7 +18,8 @@ function createGuildEmblem(emblem, el) {
|
||||||
const canvas = $emblem.find("canvas")[0];
|
const canvas = $emblem.find("canvas")[0];
|
||||||
const ctx = canvas.getContext("2d");
|
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 = $("<div>").addClass("images").appendTo($emblem);
|
const $images = $("<div>").addClass("images").appendTo($emblem);
|
||||||
const bgUpper = $("<img>").attr("src", imgUrl("Background", "U", emblem.background)).appendTo($images)[0];
|
const bgUpper = $("<img>").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 canvas = $emblem.find("canvas")[0];
|
||||||
const ctx = canvas.getContext("2d");
|
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 = $("<div>").addClass("images").appendTo($emblem);
|
const $images = $("<div>").addClass("images").appendTo($emblem);
|
||||||
const banner = $("<img>").attr("src", imgUrl(teamSize)).appendTo($images)[0];
|
const banner = $("<img>").attr("src", imgUrl(teamSize)).appendTo($images)[0];
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
window.parent.postMessage({
|
window.parent.postMessage(
|
||||||
|
{
|
||||||
url: window.location.pathname.replace(handlebarsData.websiteRoot, ""),
|
url: window.location.pathname.replace(handlebarsData.websiteRoot, ""),
|
||||||
}, "*");
|
},
|
||||||
|
"*",
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
"outDir": "build",
|
"outDir": "build",
|
||||||
"moduleResolution": "node"
|
"moduleResolution": "node"
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": ["node_modules"],
|
||||||
"node_modules"
|
|
||||||
],
|
|
||||||
"include": ["src/**/*.ts"]
|
"include": ["src/**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue