chore: apply prettier with new conf
This commit is contained in:
parent
6a4720e59b
commit
db2a04c03f
13 changed files with 2107 additions and 2109 deletions
|
|
@ -1,18 +1,18 @@
|
|||
import * as path from 'path';
|
||||
import * as uuid from 'uuid';
|
||||
import { Express } from 'express';
|
||||
import * as express from 'express';
|
||||
import * as winston from 'winston';
|
||||
import * as morgan from 'morgan';
|
||||
import { Pool, createPool } from 'mysql2/promise';
|
||||
import { engine as handlebarsEngine } from 'express-handlebars';
|
||||
import * as path from "path";
|
||||
import * as uuid from "uuid";
|
||||
import { Express } from "express";
|
||||
import * as express from "express";
|
||||
import * as winston from "winston";
|
||||
import * as morgan from "morgan";
|
||||
import { Pool, createPool } from "mysql2/promise";
|
||||
import { engine as handlebarsEngine } from "express-handlebars";
|
||||
|
||||
import { Config, IRealmConfig } from './Config';
|
||||
import { DbcManager } from './data/DbcReader';
|
||||
import { CharacterCustomization } from './data/CharacterCustomization';
|
||||
import { IndexController } from './controllers/IndexController';
|
||||
import { CharacterController } from './controllers/CharacterController';
|
||||
import { GuildController } from './controllers/GuildController';
|
||||
import { Config, IRealmConfig } from "./Config";
|
||||
import { DbcManager } from "./data/DbcReader";
|
||||
import { CharacterCustomization } from "./data/CharacterCustomization";
|
||||
import { IndexController } from "./controllers/IndexController";
|
||||
import { CharacterController } from "./controllers/CharacterController";
|
||||
import { GuildController } from "./controllers/GuildController";
|
||||
|
||||
export class Armory {
|
||||
public characterCustomization: CharacterCustomization;
|
||||
|
|
@ -31,30 +31,30 @@ export class Armory {
|
|||
this.characterCustomization = new CharacterCustomization();
|
||||
this.charsDbs = {};
|
||||
this.logger = winston.createLogger({
|
||||
level: 'info',
|
||||
level: "info",
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss:ms" }),
|
||||
winston.format.printf((info) => `[${info.timestamp}] [${info.level.toUpperCase()}]: ${info.message}`),
|
||||
),
|
||||
transports: [
|
||||
new winston.transports.Console({ level: 'debug' }),
|
||||
new winston.transports.File({ filename: path.join('logs', 'armory.error.log'), level: 'error' }),
|
||||
new winston.transports.File({ filename: path.join('logs', 'armory.combined.log'), level: 'http' }),
|
||||
new winston.transports.Console({ level: "debug" }),
|
||||
new winston.transports.File({ filename: path.join("logs", "armory.error.log"), level: "error" }),
|
||||
new winston.transports.File({ filename: path.join("logs", "armory.combined.log"), level: "http" }),
|
||||
],
|
||||
});
|
||||
this.charsetCache = {};
|
||||
|
||||
this.errorNames = {
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
500: 'Internal Server Error',
|
||||
400: "Bad Request",
|
||||
401: "Unauthorized",
|
||||
403: "Forbidden",
|
||||
404: "Not Found",
|
||||
500: "Internal Server Error",
|
||||
};
|
||||
this.errorDescriptions = {
|
||||
400: 'Invalid request.',
|
||||
404: 'Sorry, we could not find what you were looking for.',
|
||||
500: 'An unexpected internal error has occurred. Please contact the site owner.',
|
||||
400: "Invalid request.",
|
||||
404: "Sorry, we could not find what you were looking for.",
|
||||
500: "An unexpected internal error has occurred. Please contact the site owner.",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -62,21 +62,21 @@ export class Armory {
|
|||
const app: Express = express();
|
||||
const listenPort = 48733;
|
||||
|
||||
this.logger.info('Loading config...');
|
||||
this.logger.info("Loading config...");
|
||||
this.config = await Config.load(this.logger);
|
||||
this.logger.info('Loading data files...');
|
||||
this.logger.info("Loading data files...");
|
||||
if (this.config.loadDbcs) {
|
||||
await this.dbc.loadAllFiles();
|
||||
}
|
||||
await this.characterCustomization.loadData();
|
||||
|
||||
this.logger.info('Connecting to databases...');
|
||||
this.logger.info("Connecting to databases...");
|
||||
this.worldDb = createPool(this.config.worldDatabase);
|
||||
for (const realm of this.config.realms) {
|
||||
this.charsDbs[realm.name.toLowerCase()] = createPool(realm.charactersDatabase);
|
||||
}
|
||||
|
||||
this.logger.info('Starting server...');
|
||||
this.logger.info("Starting server...");
|
||||
|
||||
const locals = {
|
||||
aowow: this.config.aowowUrl,
|
||||
|
|
@ -93,70 +93,70 @@ export class Armory {
|
|||
app.locals.locals = locals;
|
||||
|
||||
app.engine(
|
||||
'.hbs',
|
||||
".hbs",
|
||||
handlebarsEngine({
|
||||
extname: 'hbs',
|
||||
partialsDir: path.join(process.cwd(), 'static', 'partials'),
|
||||
layoutsDir: path.join(process.cwd(), 'static'),
|
||||
defaultLayout: 'layout.hbs',
|
||||
extname: "hbs",
|
||||
partialsDir: path.join(process.cwd(), "static", "partials"),
|
||||
layoutsDir: path.join(process.cwd(), "static"),
|
||||
defaultLayout: "layout.hbs",
|
||||
helpers: {
|
||||
...require('handlebars-helpers')(),
|
||||
...require("handlebars-helpers")(),
|
||||
},
|
||||
}),
|
||||
);
|
||||
app.set('view engine', 'handlebars');
|
||||
app.set('views', path.join(process.cwd(), 'static'));
|
||||
app.set("view engine", "handlebars");
|
||||
app.set("views", path.join(process.cwd(), "static"));
|
||||
|
||||
app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
req.id = uuid.v4();
|
||||
next();
|
||||
});
|
||||
|
||||
morgan.token('id', (req: express.Request) => {
|
||||
morgan.token("id", (req: express.Request) => {
|
||||
return req.id;
|
||||
});
|
||||
morgan.token('ip', (req: express.Request) => {
|
||||
const forwardedFor = req.headers['x-forwarded-for'];
|
||||
morgan.token("ip", (req: express.Request) => {
|
||||
const forwardedFor = req.headers["x-forwarded-for"];
|
||||
if (forwardedFor) {
|
||||
if (typeof forwardedFor === 'string') {
|
||||
if (typeof forwardedFor === "string") {
|
||||
return forwardedFor;
|
||||
}
|
||||
return forwardedFor.join(', ');
|
||||
return forwardedFor.join(", ");
|
||||
}
|
||||
return req.socket.remoteAddress;
|
||||
});
|
||||
app.use(
|
||||
morgan(':method :url :status - ID :id - IP :ip - :response-time ms', {
|
||||
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`));
|
||||
app.use('/img', express.static(`static/img`));
|
||||
app.use('/data/mo3', express.static(`data/mo3`));
|
||||
app.use('/data/meta', express.static(`data/meta`));
|
||||
app.use('/data/bone', express.static(`data/bone`));
|
||||
app.use('/data/textures', express.static(`data/textures`));
|
||||
app.use('/data/background.png', express.static(`data/modelviewer-background.png`));
|
||||
app.use("/js", express.static(`static/js`));
|
||||
app.use("/css", express.static(`static/css`));
|
||||
app.use("/img", express.static(`static/img`));
|
||||
app.use("/data/mo3", express.static(`data/mo3`));
|
||||
app.use("/data/meta", express.static(`data/meta`));
|
||||
app.use("/data/bone", express.static(`data/bone`));
|
||||
app.use("/data/textures", express.static(`data/textures`));
|
||||
app.use("/data/background.png", express.static(`data/modelviewer-background.png`));
|
||||
|
||||
const indexController = new IndexController(this);
|
||||
app.get('/', this.wrapRoute(indexController.index.bind(indexController)));
|
||||
app.get('/search', this.wrapRoute(indexController.search.bind(indexController)));
|
||||
app.get("/", this.wrapRoute(indexController.index.bind(indexController)));
|
||||
app.get("/search", this.wrapRoute(indexController.search.bind(indexController)));
|
||||
|
||||
const charsController = new CharacterController(this);
|
||||
await charsController.load();
|
||||
app.get('/character/:realm/:name', this.wrapRoute(charsController.character.bind(charsController)));
|
||||
app.get('/character/:realm/:name/talents', this.wrapRoute(charsController.talents.bind(charsController)));
|
||||
app.get('/character/:realm/:name/achievements', this.wrapRoute(charsController.achievements.bind(charsController)));
|
||||
app.get('/character/:realm/:character/achievements/data', this.wrapRoute(charsController.achievementsData.bind(charsController)));
|
||||
app.get('/character/:realm/:name/pvp', this.wrapRoute(charsController.pvp.bind(charsController)));
|
||||
app.get("/character/:realm/:name", this.wrapRoute(charsController.character.bind(charsController)));
|
||||
app.get("/character/:realm/:name/talents", this.wrapRoute(charsController.talents.bind(charsController)));
|
||||
app.get("/character/:realm/:name/achievements", this.wrapRoute(charsController.achievements.bind(charsController)));
|
||||
app.get("/character/:realm/:character/achievements/data", this.wrapRoute(charsController.achievementsData.bind(charsController)));
|
||||
app.get("/character/:realm/:name/pvp", this.wrapRoute(charsController.pvp.bind(charsController)));
|
||||
|
||||
const guildsController = new GuildController(this);
|
||||
app.get('/guild/:realm/:name', this.wrapRoute(guildsController.guild.bind(guildsController)));
|
||||
app.get('/guild/:realm/:guild/members', this.wrapRoute(guildsController.members.bind(guildsController)));
|
||||
app.get("/guild/:realm/:name", this.wrapRoute(guildsController.guild.bind(guildsController)));
|
||||
app.get("/guild/:realm/:guild/members", this.wrapRoute(guildsController.members.bind(guildsController)));
|
||||
|
||||
app.use((err, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
// Error handler
|
||||
|
|
@ -167,11 +167,11 @@ export class Armory {
|
|||
}
|
||||
|
||||
let status = 500;
|
||||
if (typeof err === 'number') {
|
||||
if (typeof err === "number") {
|
||||
status = err;
|
||||
}
|
||||
|
||||
res.status(status).render('error.hbs', this.getErrorViewData(status, req));
|
||||
res.status(status).render("error.hbs", this.getErrorViewData(status, req));
|
||||
});
|
||||
|
||||
app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
|
|
@ -179,21 +179,21 @@ export class Armory {
|
|||
res.status(404);
|
||||
|
||||
// Respond with html page
|
||||
if (req.accepts('html')) {
|
||||
return res.render('error.hbs', this.getErrorViewData(404, req));
|
||||
if (req.accepts("html")) {
|
||||
return res.render("error.hbs", this.getErrorViewData(404, req));
|
||||
}
|
||||
|
||||
// Respond with json
|
||||
if (req.accepts('json')) {
|
||||
if (req.accepts("json")) {
|
||||
return res.json({ error: this.errorNames[404] });
|
||||
}
|
||||
|
||||
// Default to plain-text
|
||||
res.type('txt').send(this.errorNames[404]);
|
||||
res.type("txt").send(this.errorNames[404]);
|
||||
});
|
||||
|
||||
this.gc();
|
||||
app.listen(listenPort, '0.0.0.0', () => {
|
||||
app.listen(listenPort, "0.0.0.0", () => {
|
||||
this.logger.info(`Server is listening on 0.0.0.0:${listenPort}.`);
|
||||
});
|
||||
}
|
||||
|
|
@ -251,8 +251,8 @@ export class Armory {
|
|||
private getErrorViewData(status: number, req: express.Request) {
|
||||
return {
|
||||
status,
|
||||
name: this.errorNames[status] || 'An error occurred',
|
||||
description: this.errorDescriptions[status] || '',
|
||||
name: this.errorNames[status] || "An error occurred",
|
||||
description: this.errorDescriptions[status] || "",
|
||||
reqId: req.id,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as fs from 'fs';
|
||||
import * as fs from "fs";
|
||||
const fsp = fs.promises;
|
||||
|
||||
import * as winston from 'winston';
|
||||
import * as winston from "winston";
|
||||
|
||||
export interface IDatabaseConfig {
|
||||
host: string;
|
||||
|
|
@ -35,12 +35,12 @@ export class Config {
|
|||
public worldDatabase: IDatabaseConfig;
|
||||
public dbQueryTimeout: number;
|
||||
|
||||
private static envPrefix: string = 'ACORE_ARMORY';
|
||||
private static envPrefix: string = "ACORE_ARMORY";
|
||||
private static checkedMissingField: boolean = false;
|
||||
|
||||
public static async load(logger: winston.Logger): Promise<Config> {
|
||||
try {
|
||||
await fsp.access('config.json');
|
||||
await fsp.access("config.json");
|
||||
return await Config.loadFromFile(logger);
|
||||
} catch (err) {
|
||||
return await Config.loadFromEnv(logger);
|
||||
|
|
@ -48,11 +48,11 @@ export class Config {
|
|||
}
|
||||
|
||||
private static async loadFromFile(logger: winston.Logger): Promise<Config> {
|
||||
const json: Buffer = await fsp.readFile('config.json');
|
||||
const json: Buffer = await fsp.readFile("config.json");
|
||||
const config = JSON.parse(json.toString()) as Config;
|
||||
|
||||
if (!Config.checkedMissingField) {
|
||||
const defaultConfigJson = await fsp.readFile('config.default.json');
|
||||
const defaultConfigJson = await fsp.readFile("config.default.json");
|
||||
const defaultConfig = JSON.parse(defaultConfigJson.toString());
|
||||
Config.checkAllMissingFields(logger, config, defaultConfig);
|
||||
Config.checkedMissingField = true;
|
||||
|
|
@ -63,16 +63,16 @@ export class Config {
|
|||
|
||||
private static async loadFromEnv(logger: winston.Logger): Promise<Config> {
|
||||
const config = {};
|
||||
const json = await fsp.readFile('config.default.json');
|
||||
const json = await fsp.readFile("config.default.json");
|
||||
const defaultConfig = JSON.parse(json.toString());
|
||||
Config.loadObjFromEnv(logger, config, defaultConfig);
|
||||
Config.checkedMissingField = true;
|
||||
return config as Config;
|
||||
}
|
||||
|
||||
private static loadObjFromEnv(logger: winston.Logger, obj: object, model: object, parentName: string = '') {
|
||||
if (parentName !== '') {
|
||||
parentName += '.';
|
||||
private static loadObjFromEnv(logger: winston.Logger, obj: object, model: object, parentName: string = "") {
|
||||
if (parentName !== "") {
|
||||
parentName += ".";
|
||||
}
|
||||
|
||||
for (const field in model) {
|
||||
|
|
@ -82,7 +82,7 @@ export class Config {
|
|||
|
||||
if (Array.isArray(model[field])) {
|
||||
obj[field] = Config.loadArrayFromEnv(logger, model[field][0], parentName + field);
|
||||
} else if (typeof model[field] === 'object') {
|
||||
} else if (typeof model[field] === "object") {
|
||||
obj[field] = {};
|
||||
Config.loadObjFromEnv(logger, obj[field], model[field], parentName + field);
|
||||
} else if (!obj.hasOwnProperty(field)) {
|
||||
|
|
@ -96,9 +96,9 @@ export class Config {
|
|||
}
|
||||
}
|
||||
|
||||
private static loadArrayFromEnv(logger: winston.Logger, model: any, parentName: string = ''): any[] {
|
||||
if (parentName !== '') {
|
||||
parentName += '.';
|
||||
private static loadArrayFromEnv(logger: winston.Logger, model: any, parentName: string = ""): any[] {
|
||||
if (parentName !== "") {
|
||||
parentName += ".";
|
||||
}
|
||||
|
||||
const arr = [];
|
||||
|
|
@ -112,7 +112,7 @@ export class Config {
|
|||
|
||||
if (Array.isArray(model)) {
|
||||
arr.push(Config.loadArrayFromEnv(logger, model[0], parentName + i));
|
||||
} else if (typeof model === 'object') {
|
||||
} else if (typeof model === "object") {
|
||||
const obj = {};
|
||||
Config.loadObjFromEnv(logger, obj, model, parentName + i);
|
||||
if (Object.keys(obj).length > 0) {
|
||||
|
|
@ -133,9 +133,9 @@ export class Config {
|
|||
private static getEnvKey(key: string): string {
|
||||
return (
|
||||
Config.envPrefix +
|
||||
'_' +
|
||||
"_" +
|
||||
key
|
||||
.replace(/\./g, '__')
|
||||
.replace(/\./g, "__")
|
||||
.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
|
||||
.toUpperCase()
|
||||
);
|
||||
|
|
@ -144,25 +144,25 @@ export class Config {
|
|||
private static parseEnvValue(value: string, model: any): any {
|
||||
const type = typeof model;
|
||||
const lower = value.toLowerCase();
|
||||
if (type === 'boolean') {
|
||||
return lower === 'true' || value === '1';
|
||||
if (type === "boolean") {
|
||||
return lower === "true" || value === "1";
|
||||
}
|
||||
if (type === 'number') {
|
||||
if (type === "number") {
|
||||
return parseFloat(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static checkAllMissingFields(logger: winston.Logger, obj: object, model: object, parentName: string = '') {
|
||||
private static checkAllMissingFields(logger: winston.Logger, obj: object, model: object, parentName: string = "") {
|
||||
const missing = Config.hasMissingFields(obj, model);
|
||||
if (parentName !== '') {
|
||||
parentName += '.';
|
||||
if (parentName !== "") {
|
||||
parentName += ".";
|
||||
}
|
||||
for (const field of missing) {
|
||||
logger.warn(`Field ${parentName}${field} is missing from config.json!`);
|
||||
}
|
||||
for (const key in model) {
|
||||
if (typeof model[key] === 'object' && obj.hasOwnProperty(key)) {
|
||||
if (typeof model[key] === "object" && obj.hasOwnProperty(key)) {
|
||||
Config.checkAllMissingFields(logger, obj[key], model[key], parentName + key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Pool } from 'mysql2/promise';
|
||||
import { Query } from 'express-serve-static-core';
|
||||
import { Pool } from "mysql2/promise";
|
||||
import { Query } from "express-serve-static-core";
|
||||
|
||||
export interface IResult {
|
||||
recordsTotal: number;
|
||||
|
|
@ -22,7 +22,7 @@ export interface IColumnJoin {
|
|||
table2: string;
|
||||
column2: string;
|
||||
database2?: string;
|
||||
kind: 'INNER' | 'FULL OUTER' | 'LEFT' | 'RIGHT';
|
||||
kind: "INNER" | "FULL OUTER" | "LEFT" | "RIGHT";
|
||||
}
|
||||
|
||||
export class DataTablesSsp {
|
||||
|
|
@ -59,11 +59,11 @@ export class DataTablesSsp {
|
|||
private wheres: string[] = [];
|
||||
private filterBindings: (string | number)[] = [];
|
||||
private customBindings: (string | number)[] = [];
|
||||
private filterWhereSql: string = '1';
|
||||
private customWhereSql: string = '1';
|
||||
private limitSql: string = '';
|
||||
private orderSql: string = '';
|
||||
private joinSql: string = '';
|
||||
private filterWhereSql: string = "1";
|
||||
private customWhereSql: string = "1";
|
||||
private limitSql: string = "";
|
||||
private orderSql: string = "";
|
||||
private joinSql: string = "";
|
||||
|
||||
public constructor(query: Query, db: Pool, table: string, primaryKey: string, columnSettings: IColumnSettings[]) {
|
||||
this.start = parseInt(query.start as string, 10);
|
||||
|
|
@ -76,14 +76,14 @@ export class DataTablesSsp {
|
|||
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' },
|
||||
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',
|
||||
regex: (query.search as any).regex === "true",
|
||||
};
|
||||
|
||||
this.db = db;
|
||||
|
|
@ -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}\``;
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ export class DataTablesSsp {
|
|||
orderBy.push(`\`${this.table}\`.\`${this.primaryKey}\``);
|
||||
|
||||
if (orderBy.length > 0) {
|
||||
this.orderSql = 'ORDER BY ' + orderBy.join(', ');
|
||||
this.orderSql = "ORDER BY " + orderBy.join(", ");
|
||||
}
|
||||
|
||||
return this;
|
||||
|
|
@ -130,7 +130,7 @@ export class DataTablesSsp {
|
|||
|
||||
private join() {
|
||||
for (const join of this.joins) {
|
||||
const db2 = join.database2 ? '`' + join.database2 + '`.' : '';
|
||||
const db2 = join.database2 ? "`" + join.database2 + "`." : "";
|
||||
this.joinSql += `${join.kind} JOIN ${db2}\`${join.table2}\` ON ${db2}\`${join.table2}\`.\`${join.column2}\` = \`${join.table1}\`.\`${join.column1}\`\n`;
|
||||
}
|
||||
|
||||
|
|
@ -148,23 +148,23 @@ export class DataTablesSsp {
|
|||
}
|
||||
|
||||
const colSettings = this.columnSettings[col.data];
|
||||
const collate = colSettings.collation !== undefined ? `COLLATE ${colSettings.collation} ` : '';
|
||||
const collate = colSettings.collation !== undefined ? `COLLATE ${colSettings.collation} ` : "";
|
||||
filterWheres.push(`${this.colSettingsToStr(colSettings)} ${collate}LIKE ?`);
|
||||
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];
|
||||
return `
|
||||
SELECT ${columns.join(', ')}
|
||||
SELECT ${columns.join(", ")}
|
||||
FROM ${this.table}
|
||||
${this.joinSql}
|
||||
WHERE
|
||||
|
|
|
|||
|
|
@ -13,28 +13,28 @@ export interface IEmblem {
|
|||
|
||||
export class Utils {
|
||||
public static raceNames = {
|
||||
1: 'human',
|
||||
2: 'orc',
|
||||
3: 'dwarf',
|
||||
4: 'nightelf',
|
||||
5: 'scourge',
|
||||
6: 'tauren',
|
||||
7: 'gnome',
|
||||
8: 'troll',
|
||||
10: 'bloodelf',
|
||||
11: 'draenei',
|
||||
1: "human",
|
||||
2: "orc",
|
||||
3: "dwarf",
|
||||
4: "nightelf",
|
||||
5: "scourge",
|
||||
6: "tauren",
|
||||
7: "gnome",
|
||||
8: "troll",
|
||||
10: "bloodelf",
|
||||
11: "draenei",
|
||||
};
|
||||
public static classNames = {
|
||||
1: 'warrior',
|
||||
2: 'paladin',
|
||||
3: 'hunter',
|
||||
4: 'rogue',
|
||||
5: 'priest',
|
||||
6: 'deathknight',
|
||||
7: 'shaman',
|
||||
8: 'mage',
|
||||
9: 'warlock',
|
||||
11: 'druid',
|
||||
1: "warrior",
|
||||
2: "paladin",
|
||||
3: "hunter",
|
||||
4: "rogue",
|
||||
5: "priest",
|
||||
6: "deathknight",
|
||||
7: "shaman",
|
||||
8: "mage",
|
||||
9: "warlock",
|
||||
11: "druid",
|
||||
};
|
||||
|
||||
public static getFactionFromRaceId(race: number): EFaction {
|
||||
|
|
@ -44,11 +44,11 @@ export class Utils {
|
|||
public static makeEmblemObject(obj: any, padWithZeroes: boolean = true): IEmblem {
|
||||
const padLength = padWithZeroes ? 2 : 0;
|
||||
return {
|
||||
icon: obj.emblemStyle.toString().padStart(padLength, '0'),
|
||||
iconColor: obj.emblemColor.toString().padStart(padLength, '0'),
|
||||
border: obj.borderStyle.toString().padStart(padLength, '0'),
|
||||
borderColor: obj.borderColor.toString().padStart(padLength, '0'),
|
||||
background: obj.background.toString().padStart(padLength, '0'),
|
||||
icon: obj.emblemStyle.toString().padStart(padLength, "0"),
|
||||
iconColor: obj.emblemColor.toString().padStart(padLength, "0"),
|
||||
border: obj.borderStyle.toString().padStart(padLength, "0"),
|
||||
borderColor: obj.borderColor.toString().padStart(padLength, "0"),
|
||||
background: obj.background.toString().padStart(padLength, "0"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import * as express from 'express';
|
||||
import { RowDataPacket } from 'mysql2/promise';
|
||||
import * as express from "express";
|
||||
import { RowDataPacket } from "mysql2/promise";
|
||||
|
||||
import { Utils } from '../Utils';
|
||||
import { Armory } from '../Armory';
|
||||
import { IRealmConfig } from '../Config';
|
||||
import { IAchievement } from '../data/DbcReader';
|
||||
import { Utils } from "../Utils";
|
||||
import { Armory } from "../Armory";
|
||||
import { IRealmConfig } from "../Config";
|
||||
import { IAchievement } from "../data/DbcReader";
|
||||
|
||||
interface ICharacterData {
|
||||
guid: number;
|
||||
|
|
@ -47,28 +47,28 @@ interface IMount {
|
|||
const ItemClassGem = 3;
|
||||
const SpellMechanicMounted = 21;
|
||||
const RaceDisplayName = {
|
||||
1: 'Human',
|
||||
2: 'Orc',
|
||||
3: 'Dwarf',
|
||||
4: 'Night Elf',
|
||||
5: 'Undead',
|
||||
6: 'Tauren',
|
||||
7: 'Gnome',
|
||||
8: 'Troll',
|
||||
10: 'Blood Elf',
|
||||
11: 'Draenei',
|
||||
1: "Human",
|
||||
2: "Orc",
|
||||
3: "Dwarf",
|
||||
4: "Night Elf",
|
||||
5: "Undead",
|
||||
6: "Tauren",
|
||||
7: "Gnome",
|
||||
8: "Troll",
|
||||
10: "Blood Elf",
|
||||
11: "Draenei",
|
||||
};
|
||||
const ClassDisplayName = {
|
||||
1: 'Warrior',
|
||||
2: 'Paladin',
|
||||
3: 'Hunter',
|
||||
4: 'Rogue',
|
||||
5: 'Priest',
|
||||
6: 'Death Knight',
|
||||
7: 'Shaman',
|
||||
8: 'Mage',
|
||||
9: 'Warlock',
|
||||
11: 'Druid',
|
||||
1: "Warrior",
|
||||
2: "Paladin",
|
||||
3: "Hunter",
|
||||
4: "Rogue",
|
||||
5: "Priest",
|
||||
6: "Death Knight",
|
||||
7: "Shaman",
|
||||
8: "Mage",
|
||||
9: "Warlock",
|
||||
11: "Druid",
|
||||
};
|
||||
|
||||
export class CharacterController {
|
||||
|
|
@ -120,7 +120,7 @@ export class CharacterController {
|
|||
|
||||
this.itemSocketBonuses = {};
|
||||
let [rows, fields] = await this.armory.worldDb.query({
|
||||
sql: 'SELECT entry, socketBonus FROM item_template WHERE socketBonus <> 0',
|
||||
sql: "SELECT entry, socketBonus FROM item_template WHERE socketBonus <> 0",
|
||||
timeout: this.armory.config.dbQueryTimeout,
|
||||
});
|
||||
for (const row of rows as RowDataPacket[]) {
|
||||
|
|
@ -142,7 +142,7 @@ export class CharacterController {
|
|||
this.mountBySpellId[spell.id] = {
|
||||
creatureDisplayId: display.creatureDisplayInfoId,
|
||||
spell: spell.id,
|
||||
icon: this.processSpellIconTexture(icon?.textureFilename ?? ''),
|
||||
icon: this.processSpellIconTexture(icon?.textureFilename ?? ""),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ export class CharacterController {
|
|||
});
|
||||
const mounts = await this.getMounts(realmName, charData.guid);
|
||||
|
||||
res.render('character.hbs', {
|
||||
res.render("character.hbs", {
|
||||
title: `Armory - ${charData.name}`,
|
||||
...this.makeSharedDataObject(realm, charData),
|
||||
data: {
|
||||
|
|
@ -214,7 +214,7 @@ export class CharacterController {
|
|||
return next(404);
|
||||
}
|
||||
|
||||
res.render('character-talents.hbs', {
|
||||
res.render("character-talents.hbs", {
|
||||
title: `Armory - ${charData.name} - Talents`,
|
||||
...this.makeSharedDataObject(realm, charData),
|
||||
data: {
|
||||
|
|
@ -241,7 +241,7 @@ export class CharacterController {
|
|||
return next(404);
|
||||
}
|
||||
|
||||
res.render('character-achievements.hbs', {
|
||||
res.render("character-achievements.hbs", {
|
||||
title: `Armory - ${charData.name} - Achievements`,
|
||||
...this.makeSharedDataObject(realm, charData),
|
||||
});
|
||||
|
|
@ -285,7 +285,7 @@ export class CharacterController {
|
|||
return next(404);
|
||||
}
|
||||
|
||||
res.render('character-pvp.hbs', {
|
||||
res.render("character-pvp.hbs", {
|
||||
title: `Armory - ${charData.name} - PvP`,
|
||||
...this.makeSharedDataObject(realm, charData),
|
||||
faction: Utils.getFactionFromRaceId(charData.race),
|
||||
|
|
@ -308,7 +308,7 @@ export class CharacterController {
|
|||
}
|
||||
|
||||
private async getCharacterData(realm: IRealmConfig, character: string | number): Promise<ICharacterData> {
|
||||
const where = typeof character === 'string' ? 'LOWER(`characters`.`name`) = LOWER(?)' : '`characters`.`guid` = ?';
|
||||
const where = typeof character === "string" ? "LOWER(`characters`.`name`) = LOWER(?)" : "`characters`.`guid` = ?";
|
||||
const [rows, fields] = await this.armory.getCharactersDb(realm.name).query({
|
||||
sql: `
|
||||
SELECT \`characters\`.\`guid\`, \`characters\`.\`name\`, \`race\`, \`class\`, \`gender\`, \`level\`, \`skin\`, \`face\`, \`hairStyle\`, \`hairColor\`, \`facialStyle\`, \`playerFlags\`, \`online\`, \`guild\`.\`name\` AS \`guild\`
|
||||
|
|
@ -398,7 +398,7 @@ export class CharacterController {
|
|||
private parseEnchantmentsString(enchantments: string): number[] {
|
||||
return enchantments
|
||||
.trim()
|
||||
.split(' ')
|
||||
.split(" ")
|
||||
.map((enchant) => parseInt(enchant))
|
||||
.filter((enchant) => enchant !== 0);
|
||||
}
|
||||
|
|
@ -446,9 +446,9 @@ export class CharacterController {
|
|||
|
||||
const optionMapping = {
|
||||
Face: charData.face,
|
||||
'Skin Color': charData.skin,
|
||||
'Hair Style': charData.hairStyle,
|
||||
'Hair Color': charData.hairColor,
|
||||
"Skin Color": charData.skin,
|
||||
"Hair Style": charData.hairStyle,
|
||||
"Hair Color": charData.hairColor,
|
||||
};
|
||||
for (const optionName in optionMapping) {
|
||||
setOptionByChoiceIndex(optionName, optionMapping[optionName]);
|
||||
|
|
@ -459,35 +459,35 @@ export class CharacterController {
|
|||
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' }[
|
||||
"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' }[
|
||||
"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],
|
||||
"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');
|
||||
setOptionByChoiceName("Eyebrows", "Natural");
|
||||
setOptionByChoiceName("Face Shape", "Narrow");
|
||||
setOptionByChoiceId(
|
||||
'Eye Color',
|
||||
"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');
|
||||
setOptionByChoiceIndex("Piercings", charData.facialStyle);
|
||||
setOptionByChoiceName("Eyebrows", "Natural");
|
||||
setOptionByChoiceName("Face Shape", "Narrow");
|
||||
setOptionByChoiceName("Makeup", "None");
|
||||
setOptionByChoiceName("Necklace", "None");
|
||||
setOptionByChoiceId(
|
||||
'Eye Color',
|
||||
"Eye Color",
|
||||
{
|
||||
0: 4162,
|
||||
1: 4153,
|
||||
|
|
@ -509,203 +509,203 @@ export class CharacterController {
|
|||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 4534 : 4535);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 4534 : 4535);
|
||||
}
|
||||
break;
|
||||
case 3: // Dwarf
|
||||
setOptionByChoiceName('Tattoo', 'None');
|
||||
setOptionByChoiceIndex('Tattoo Color', 0);
|
||||
setOptionByChoiceIndex('Eyebrows', 0);
|
||||
setOptionByChoiceName("Tattoo", "None");
|
||||
setOptionByChoiceIndex("Tattoo Color", 0);
|
||||
setOptionByChoiceIndex("Eyebrows", 0);
|
||||
if (charData.gender === 0) {
|
||||
setOptionByChoiceName(
|
||||
'Mustache',
|
||||
"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',
|
||||
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
|
||||
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]);
|
||||
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],
|
||||
"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) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 5559 : 5587);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 5559 : 5587);
|
||||
}
|
||||
break;
|
||||
case 7: // Gnome
|
||||
if (charData.gender === 0) {
|
||||
setOptionByChoiceIndex('Mustache', charData.facialStyle > 1 ? charData.facialStyle - 1 : 0);
|
||||
setOptionByChoiceIndex('Beard', charData.facialStyle < 7 ? charData.facialStyle : 0);
|
||||
setOptionByChoiceIndex('Eyebrows', charData.facialStyle < 6 ? charData.facialStyle : 1);
|
||||
setOptionByChoiceIndex('Eye Color', 0); // TODO
|
||||
setOptionByChoiceIndex("Mustache", charData.facialStyle > 1 ? charData.facialStyle - 1 : 0);
|
||||
setOptionByChoiceIndex("Beard", charData.facialStyle < 7 ? charData.facialStyle : 0);
|
||||
setOptionByChoiceIndex("Eyebrows", charData.facialStyle < 6 ? charData.facialStyle : 1);
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
} else {
|
||||
setOptionByChoiceIndex('Earrings', charData.facialStyle);
|
||||
setOptionByChoiceId('Earring Color', 8796);
|
||||
setOptionByChoiceIndex('Eye Color', 0); // TODO
|
||||
setOptionByChoiceIndex("Earrings", charData.facialStyle);
|
||||
setOptionByChoiceId("Earring Color", 8796);
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 5629 : 5643);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 5629 : 5643);
|
||||
}
|
||||
break;
|
||||
case 4: // Night Elf
|
||||
setOptionByChoiceName('Vines', 'None');
|
||||
setOptionByChoiceIndex('Vine Color', 0);
|
||||
setOptionByChoiceName('Ears', 'Thin');
|
||||
setOptionByChoiceName('Scars', 'None');
|
||||
setOptionByChoiceName("Vines", "None");
|
||||
setOptionByChoiceIndex("Vine Color", 0);
|
||||
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],
|
||||
"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]);
|
||||
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]);
|
||||
} else {
|
||||
setOptionByChoiceName('Eyebrows', 'Long');
|
||||
setOptionByChoiceIndex('Markings', charData.facialStyle + 1);
|
||||
setOptionByChoiceIndex('Markings Color', { 0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 3, 6: 6, 7: 7 }[charData.hairColor]);
|
||||
setOptionByChoiceName("Eyebrows", "Long");
|
||||
setOptionByChoiceIndex("Markings", charData.facialStyle + 1);
|
||||
setOptionByChoiceIndex("Markings Color", { 0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 3, 6: 6, 7: 7 }[charData.hairColor]);
|
||||
}
|
||||
setOptionByChoiceName('Blindfold', '');
|
||||
setOptionByChoiceName('Headdress', 'None');
|
||||
setOptionByChoiceName('Earrings', 'None');
|
||||
setOptionByChoiceName('Nose Ring', 'None');
|
||||
setOptionByChoiceName('Necklace', 'None');
|
||||
setOptionByChoiceName('Horns', 'None');
|
||||
setOptionByChoiceName('Tattoo', 'None');
|
||||
setOptionByChoiceName('Tattoo Color', 'None');
|
||||
setOptionByChoiceName("Blindfold", "");
|
||||
setOptionByChoiceName("Headdress", "None");
|
||||
setOptionByChoiceName("Earrings", "None");
|
||||
setOptionByChoiceName("Nose Ring", "None");
|
||||
setOptionByChoiceName("Necklace", "None");
|
||||
setOptionByChoiceName("Horns", "None");
|
||||
setOptionByChoiceName("Tattoo", "None");
|
||||
setOptionByChoiceName("Tattoo Color", "None");
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 7618 : 7634);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 7618 : 7634);
|
||||
} else {
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 7610 : 7619);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 7610 : 7619);
|
||||
}
|
||||
break;
|
||||
case 11: // Draenei
|
||||
setOptionByChoiceName('Circlet', 'None');
|
||||
setOptionByChoiceId('Jewelry Color', charData.gender === 0 ? 8707 : 8646);
|
||||
setOptionByChoiceName('Horn Decoration', 'None');
|
||||
setOptionByChoiceName('Tail', charData.gender === 0 ? 'Long' : 'Short');
|
||||
setOptionByChoiceName("Circlet", "None");
|
||||
setOptionByChoiceId("Jewelry Color", charData.gender === 0 ? 8707 : 8646);
|
||||
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' }[
|
||||
"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],
|
||||
"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],
|
||||
"Horns",
|
||||
{ 0: "Sweeping", 1: "Curled", 2: "Curved", 3: "Thick", 4: "Wide", 5: "Grand", 6: "Short" }[charData.facialStyle],
|
||||
);
|
||||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 6977 : 6979);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 6977 : 6979);
|
||||
} else {
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 6976 : 6978);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 6976 : 6978);
|
||||
}
|
||||
break;
|
||||
case 2: // Orc
|
||||
setOptionByChoiceName('Scars', 'None');
|
||||
setOptionByChoiceName('Grime', 'None');
|
||||
setOptionByChoiceName('Tattoo', 'None');
|
||||
setOptionByChoiceName('War Paint', 'None');
|
||||
setOptionByChoiceName('War Paint Color', 'None');
|
||||
setOptionByChoiceName("Scars", "None");
|
||||
setOptionByChoiceName("Grime", "None");
|
||||
setOptionByChoiceName("Tattoo", "None");
|
||||
setOptionByChoiceName("War Paint", "None");
|
||||
setOptionByChoiceName("War Paint Color", "None");
|
||||
if (charData.gender === 0) {
|
||||
setOptionByChoiceName(
|
||||
'Beard',
|
||||
"Beard",
|
||||
{
|
||||
0: 'None',
|
||||
1: 'Stubble',
|
||||
2: 'Thick',
|
||||
3: 'Full',
|
||||
4: 'Tied',
|
||||
5: 'Braid',
|
||||
6: 'Twin Braids',
|
||||
7: 'None',
|
||||
8: 'Ringed',
|
||||
9: 'Split',
|
||||
10: 'Goatee',
|
||||
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' }[
|
||||
"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');
|
||||
setOptionByChoiceName('Upright', 'Hunched');
|
||||
setOptionByChoiceIndex('Eye Color', 0); // TODO
|
||||
setOptionByChoiceName("Earrings", "None");
|
||||
setOptionByChoiceName("Nose Ring", "None");
|
||||
setOptionByChoiceName("Tusks", "Natural");
|
||||
setOptionByChoiceName("Upright", "Hunched");
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
} else {
|
||||
setOptionByChoiceIndex('Earrings', { 0: 0, 1: 1, 2: 2, 3: 0, 4: 1, 5: 2, 6: 4 }[charData.facialStyle]);
|
||||
setOptionByChoiceIndex('Nose Ring', { 0: 0, 1: 0, 2: 0, 3: 1, 4: 1, 5: 1, 6: 0 }[charData.facialStyle]);
|
||||
setOptionByChoiceName('Necklace', 'None');
|
||||
setOptionByChoiceIndex('Eye Color', 0); // TODO
|
||||
setOptionByChoiceIndex("Earrings", { 0: 0, 1: 1, 2: 2, 3: 0, 4: 1, 5: 2, 6: 4 }[charData.facialStyle]);
|
||||
setOptionByChoiceIndex("Nose Ring", { 0: 0, 1: 0, 2: 0, 3: 1, 4: 1, 5: 1, 6: 0 }[charData.facialStyle]);
|
||||
setOptionByChoiceName("Necklace", "None");
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 9289 : 9313);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 9289 : 9313);
|
||||
}
|
||||
break;
|
||||
case 5: // Undead
|
||||
setOptionByChoiceName('Skin Type', 'Bony');
|
||||
setOptionByChoiceName("Skin Type", "Bony");
|
||||
if (charData.gender === 0) {
|
||||
setOptionByChoiceName(
|
||||
'Jaw Features',
|
||||
"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',
|
||||
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',
|
||||
"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',
|
||||
"Eye Color",
|
||||
{
|
||||
0: 5330,
|
||||
1: 5330,
|
||||
|
|
@ -728,144 +728,144 @@ export class CharacterController {
|
|||
);
|
||||
} else {
|
||||
setOptionByChoiceName(
|
||||
'Face Features',
|
||||
{ 0: 'None', 1: 'None', 2: 'Strapped', 3: 'Rotting', 4: 'None', 5: 'None', 6: 'None', 7: 'Putrid' }[charData.facialStyle],
|
||||
"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' }[
|
||||
"Jaw Features",
|
||||
{ 0: "Intact", 1: "Stitched", 2: "Intact", 3: "Intact", 4: "Bonejawed", 5: "Toothy", 6: "Cheeky", 7: "Intact" }[
|
||||
charData.facialStyle
|
||||
],
|
||||
);
|
||||
setOptionByChoiceId(
|
||||
'Eye Color',
|
||||
"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
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 5344 : 5345);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 5344 : 5345);
|
||||
}
|
||||
break;
|
||||
case 6: // Tauren
|
||||
setOptionByChoiceIndex('Horn Style', charData.hairStyle);
|
||||
setOptionByChoiceIndex('Horn Color', charData.hairColor);
|
||||
setOptionByChoiceName('Foremane', 'Short');
|
||||
setOptionByChoiceName('Face Paint', 'None');
|
||||
setOptionByChoiceName('Headdress', 'None');
|
||||
setOptionByChoiceName('Necklace', 'None');
|
||||
setOptionByChoiceIndex('Jewelry Color', 0);
|
||||
setOptionByChoiceName('Flower', 'None');
|
||||
setOptionByChoiceName('Body Paint', 'None');
|
||||
setOptionByChoiceIndex('Paint Color', 0);
|
||||
setOptionByChoiceIndex("Horn Style", charData.hairStyle);
|
||||
setOptionByChoiceIndex("Horn Color", charData.hairColor);
|
||||
setOptionByChoiceName("Foremane", "Short");
|
||||
setOptionByChoiceName("Face Paint", "None");
|
||||
setOptionByChoiceName("Headdress", "None");
|
||||
setOptionByChoiceName("Necklace", "None");
|
||||
setOptionByChoiceIndex("Jewelry Color", 0);
|
||||
setOptionByChoiceName("Flower", "None");
|
||||
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],
|
||||
"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],
|
||||
"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],
|
||||
"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 {
|
||||
setOptionByChoiceIndex('Hair', charData.facialStyle);
|
||||
setOptionByChoiceName('Earrings', 'None');
|
||||
setOptionByChoiceName('Nose Ring', 'None');
|
||||
setOptionByChoiceIndex('Eye Color', 0); // TODO
|
||||
setOptionByChoiceIndex("Hair", charData.facialStyle);
|
||||
setOptionByChoiceName("Earrings", "None");
|
||||
setOptionByChoiceName("Nose Ring", "None");
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 7281 : 7289);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 7281 : 7289);
|
||||
}
|
||||
break;
|
||||
case 8: // Troll
|
||||
setOptionByChoiceName('Body Paint', 'None');
|
||||
setOptionByChoiceName('Body Paint Color', 'None');
|
||||
setOptionByChoiceName('Piercing', 'None');
|
||||
setOptionByChoiceName("Body Paint", "None");
|
||||
setOptionByChoiceName("Body Paint Color", "None");
|
||||
setOptionByChoiceName("Piercing", "None");
|
||||
if (charData.gender === 0) {
|
||||
setOptionByChoiceName(
|
||||
'Tusks',
|
||||
"Tusks",
|
||||
{
|
||||
0: 'Tusked',
|
||||
1: 'Gougers',
|
||||
2: 'Mammoth',
|
||||
3: 'Spears',
|
||||
4: 'Bridle',
|
||||
5: 'Tusked',
|
||||
6: 'Gougers',
|
||||
7: 'Mammoth',
|
||||
8: 'Spears',
|
||||
9: 'Bridle',
|
||||
10: 'Gougers',
|
||||
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',
|
||||
"Face Paint",
|
||||
{
|
||||
0: 'None',
|
||||
1: 'None',
|
||||
2: 'None',
|
||||
3: 'None',
|
||||
4: 'None',
|
||||
5: 'Berserker',
|
||||
6: 'Fangs',
|
||||
7: 'Mask',
|
||||
8: 'Oni',
|
||||
9: 'Prophet',
|
||||
10: 'War',
|
||||
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
|
||||
setOptionByChoiceIndex("Face Paint Color", charData.hairColor + 1);
|
||||
setOptionByChoiceName("Earrings", "None");
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
} else {
|
||||
setOptionByChoiceIndex('Tusks', charData.facialStyle);
|
||||
setOptionByChoiceName('Face Paint', 'None');
|
||||
setOptionByChoiceIndex('Face Paint Color', 0);
|
||||
setOptionByChoiceName('Earrings', 'Hoops');
|
||||
setOptionByChoiceIndex('Eye Color', 0); // TODO
|
||||
setOptionByChoiceIndex("Tusks", charData.facialStyle);
|
||||
setOptionByChoiceName("Face Paint", "None");
|
||||
setOptionByChoiceIndex("Face Paint Color", 0);
|
||||
setOptionByChoiceName("Earrings", "Hoops");
|
||||
setOptionByChoiceIndex("Eye Color", 0); // TODO
|
||||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 8451 : 8468);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 8451 : 8468);
|
||||
}
|
||||
break;
|
||||
case 10: // Blood Elf
|
||||
setOptionByChoiceName('Ears', 'Long');
|
||||
setOptionByChoiceName('Horns', 'None');
|
||||
setOptionByChoiceName('Blindfold', 'None');
|
||||
setOptionByChoiceName('Tattoo', 'None');
|
||||
setOptionByChoiceIndex('Tattoo Color', 0);
|
||||
setOptionByChoiceName("Ears", "Long");
|
||||
setOptionByChoiceName("Horns", "None");
|
||||
setOptionByChoiceName("Blindfold", "None");
|
||||
setOptionByChoiceName("Tattoo", "None");
|
||||
setOptionByChoiceIndex("Tattoo Color", 0);
|
||||
if (charData.gender === 0) {
|
||||
setOptionByChoiceIndex('Facial Hair', charData.facialStyle);
|
||||
setOptionByChoiceIndex("Facial Hair", charData.facialStyle);
|
||||
} else {
|
||||
setOptionByChoiceIndex('Earrings', charData.facialStyle);
|
||||
setOptionByChoiceIndex('Jewelry Color', 0);
|
||||
setOptionByChoiceName('Necklace', 'None');
|
||||
setOptionByChoiceName('Armbands', 'None');
|
||||
setOptionByChoiceName('Bracelets', 'None');
|
||||
setOptionByChoiceIndex("Earrings", charData.facialStyle);
|
||||
setOptionByChoiceIndex("Jewelry Color", 0);
|
||||
setOptionByChoiceName("Necklace", "None");
|
||||
setOptionByChoiceName("Armbands", "None");
|
||||
setOptionByChoiceName("Bracelets", "None");
|
||||
}
|
||||
if (charData.class === 6) {
|
||||
// Death Knight
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 6586 : 6605);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 6586 : 6605);
|
||||
} else {
|
||||
setOptionByChoiceId('Eye Color', charData.gender === 0 ? 6570 : 6589);
|
||||
setOptionByChoiceId("Eye Color", charData.gender === 0 ? 6570 : 6589);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ([4, 6].includes(charData.race)) {
|
||||
// Races that can choose the druid class
|
||||
setOptionByChoiceIndex('Bear Form', 0);
|
||||
setOptionByChoiceIndex('Cat Form', 0);
|
||||
setOptionByChoiceIndex('Aquatic Form', 0);
|
||||
setOptionByChoiceIndex('Travel Form', 0);
|
||||
setOptionByChoiceIndex('Flight Form', 0);
|
||||
setOptionByChoiceIndex('Moonkin Form', 0);
|
||||
setOptionByChoiceIndex("Bear Form", 0);
|
||||
setOptionByChoiceIndex("Cat Form", 0);
|
||||
setOptionByChoiceIndex("Aquatic Form", 0);
|
||||
setOptionByChoiceIndex("Travel Form", 0);
|
||||
setOptionByChoiceIndex("Flight Form", 0);
|
||||
setOptionByChoiceIndex("Moonkin Form", 0);
|
||||
}
|
||||
|
||||
return options;
|
||||
|
|
@ -907,7 +907,7 @@ export class CharacterController {
|
|||
.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 ?? '') };
|
||||
return { ...row, icon: this.processSpellIconTexture(icon?.textureFilename ?? "") };
|
||||
})
|
||||
.toArray();
|
||||
return {
|
||||
|
|
@ -921,7 +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<any[][]> {
|
||||
|
|
@ -962,7 +962,7 @@ export class CharacterController {
|
|||
title: ach.titleLang0,
|
||||
description: ach.descriptionLang0,
|
||||
points: ach.points,
|
||||
icon: this.processSpellIconTexture(icon?.textureFilename ?? ''),
|
||||
icon: this.processSpellIconTexture(icon?.textureFilename ?? ""),
|
||||
};
|
||||
})
|
||||
.toArray();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import * as express from 'express';
|
||||
import { encode } from 'html-entities';
|
||||
import { RowDataPacket } from 'mysql2/promise';
|
||||
import * as express from "express";
|
||||
import { encode } from "html-entities";
|
||||
import { RowDataPacket } from "mysql2/promise";
|
||||
|
||||
import { Utils } from '../Utils';
|
||||
import { Armory } from '../Armory';
|
||||
import { IRealmConfig } from '../Config';
|
||||
import { DataTablesSsp } from '../DataTablesSsp';
|
||||
import { Utils } from "../Utils";
|
||||
import { Armory } from "../Armory";
|
||||
import { IRealmConfig } from "../Config";
|
||||
import { DataTablesSsp } from "../DataTablesSsp";
|
||||
|
||||
interface IGuildRank {
|
||||
id: number;
|
||||
|
|
@ -35,7 +35,7 @@ export class GuildController {
|
|||
return next(404);
|
||||
}
|
||||
|
||||
res.render('guild.hbs', {
|
||||
res.render("guild.hbs", {
|
||||
title: `Armory - ${guildName}`,
|
||||
realm: realm.name,
|
||||
...guildData,
|
||||
|
|
@ -60,32 +60,32 @@ export class GuildController {
|
|||
const db = this.armory.getCharactersDb(realm.name);
|
||||
const charSet = await this.armory.getDatabaseCharset(realm.name);
|
||||
|
||||
let ssp = new DataTablesSsp(req.query, db, 'guild_member', 'guid', [
|
||||
{ name: 'name', table: 'characters', collation: `${charSet}_general_ci` },
|
||||
{ name: 'rank' },
|
||||
{ name: 'level', table: 'characters' },
|
||||
{ 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 },
|
||||
let ssp = new DataTablesSsp(req.query, db, "guild_member", "guid", [
|
||||
{ name: "name", table: "characters", collation: `${charSet}_general_ci` },
|
||||
{ name: "rank" },
|
||||
{ name: "level", table: "characters" },
|
||||
{ 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 },
|
||||
]);
|
||||
ssp.joins = [{ table1: 'guild_member', column1: 'guid', table2: 'characters', column2: 'guid', kind: 'LEFT' }];
|
||||
ssp.extraDataColumns = ['`characters`.`gender`'];
|
||||
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',
|
||||
table1: "characters",
|
||||
column1: "account",
|
||||
table2: "account_access",
|
||||
column2: "id",
|
||||
database2: realm.authDatabase,
|
||||
kind: 'LEFT',
|
||||
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 = {};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as express from 'express';
|
||||
import * as express from "express";
|
||||
|
||||
import { Utils } from '../Utils';
|
||||
import { Armory } from '../Armory';
|
||||
import { DataTablesSsp } from '../DataTablesSsp';
|
||||
import { Utils } from "../Utils";
|
||||
import { Armory } from "../Armory";
|
||||
import { DataTablesSsp } from "../DataTablesSsp";
|
||||
|
||||
export class IndexController {
|
||||
private armory: Armory;
|
||||
|
|
@ -12,8 +12,8 @@ export class IndexController {
|
|||
}
|
||||
|
||||
public async index(req: express.Request, res: express.Response): Promise<void> {
|
||||
res.render('index.hbs', {
|
||||
title: 'Armory',
|
||||
res.render("index.hbs", {
|
||||
title: "Armory",
|
||||
realms: this.armory.config.realms.map((r) => r.name),
|
||||
});
|
||||
}
|
||||
|
|
@ -28,35 +28,35 @@ export class IndexController {
|
|||
const db = this.armory.getCharactersDb(realm.name);
|
||||
const charSet = await this.armory.getDatabaseCharset(realm.name);
|
||||
|
||||
let ssp = new DataTablesSsp(req.query, db, 'characters', 'guid', [
|
||||
{ name: 'name', collation: `${charSet}_general_ci` },
|
||||
{ table: 'guild', name: 'name' },
|
||||
{ name: 'level' },
|
||||
{ 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 },
|
||||
let ssp = new DataTablesSsp(req.query, db, "characters", "guid", [
|
||||
{ name: "name", collation: `${charSet}_general_ci` },
|
||||
{ table: "guild", name: "name" },
|
||||
{ name: "level" },
|
||||
{ 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 },
|
||||
]);
|
||||
ssp.joins = [
|
||||
{ table1: 'characters', column1: 'guid', table2: 'guild_member', column2: 'guid', kind: 'LEFT' },
|
||||
{ table1: 'guild_member', column1: 'guildid', table2: 'guild', column2: 'guildid', kind: 'LEFT' },
|
||||
{ table1: "characters", column1: "guid", table2: "guild_member", column2: "guid", kind: "LEFT" },
|
||||
{ table1: "guild_member", column1: "guildid", table2: "guild", column2: "guildid", kind: "LEFT" },
|
||||
];
|
||||
ssp.extraDataColumns = ['`characters`.`gender`'];
|
||||
ssp.extraDataColumns = ["`characters`.`gender`"];
|
||||
|
||||
if (this.armory.config.hideGameMasters) {
|
||||
ssp.joins.push({
|
||||
table1: 'characters',
|
||||
column1: 'account',
|
||||
table2: 'account_access',
|
||||
column2: 'id',
|
||||
table1: "characters",
|
||||
column1: "account",
|
||||
table2: "account_access",
|
||||
column2: "id",
|
||||
database2: realm.authDatabase,
|
||||
kind: 'LEFT',
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'dotenv/config';
|
||||
import { Armory } from './Armory';
|
||||
import "dotenv/config";
|
||||
import { Armory } from "./Armory";
|
||||
|
||||
async function main(): Promise<void> {
|
||||
require('source-map-support').install();
|
||||
require("source-map-support").install();
|
||||
|
||||
const armory = new Armory();
|
||||
await armory.start();
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
import * as fs from 'fs';
|
||||
import * as fs from "fs";
|
||||
const fsp = fs.promises;
|
||||
import * as path from 'path';
|
||||
import * as path from "path";
|
||||
|
||||
import * as pako from 'pako';
|
||||
import fetch from 'node-fetch';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import * as glob from 'glob-promise';
|
||||
import { Response } from 'node-fetch';
|
||||
import * as prettyMs from 'pretty-ms';
|
||||
import * as cliProgress from 'cli-progress';
|
||||
import promisepool = require('@supercharge/promise-pool');
|
||||
import * as pako from "pako";
|
||||
import fetch from "node-fetch";
|
||||
import * as mkdirp from "mkdirp";
|
||||
import * as glob from "glob-promise";
|
||||
import { Response } from "node-fetch";
|
||||
import * as prettyMs from "pretty-ms";
|
||||
import * as cliProgress from "cli-progress";
|
||||
import promisepool = require("@supercharge/promise-pool");
|
||||
|
||||
import { DbcManager, IItemAppearanceDbc, IItemModifiedAppearanceDbc, IMountDbc, IMountXDisplayDbc } from '../armory/data/DbcReader';
|
||||
import { DbcManager, IItemAppearanceDbc, IItemModifiedAppearanceDbc, IMountDbc, IMountXDisplayDbc } from "../armory/data/DbcReader";
|
||||
|
||||
require('source-map-support').install();
|
||||
require("source-map-support").install();
|
||||
|
||||
const baseUrl = 'https://wow.zamimg.com/modelviewer/live';
|
||||
const baseUrl = "https://wow.zamimg.com/modelviewer/live";
|
||||
|
||||
class Stopwatch {
|
||||
private startTime: number;
|
||||
|
|
@ -30,8 +30,8 @@ class Stopwatch {
|
|||
|
||||
public stop(text?: string): void {
|
||||
const dt = Date.now() - this.startTime;
|
||||
const txt = text ?? 'Done in {time}';
|
||||
console.log(txt.replace('{time}', prettyMs(dt)));
|
||||
const txt = text ?? "Done in {time}";
|
||||
console.log(txt.replace("{time}", prettyMs(dt)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ class HttpRequestError extends Error {
|
|||
|
||||
public constructor(response: Response) {
|
||||
super(`Could not download ${response.url} (${response.status})`);
|
||||
this.name = 'HttpRequestError';
|
||||
this.name = "HttpRequestError";
|
||||
this.response = response;
|
||||
Object.setPrototypeOf(this, HttpRequestError.prototype);
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ const texturesDownloadQueue = new Set<number>();
|
|||
const bonesDownloadQueue = new Set<number>();
|
||||
|
||||
async function download(dir: string, file: string): Promise<string | any> {
|
||||
const dataDir = path.join(process.cwd(), 'data');
|
||||
const dataDir = path.join(process.cwd(), "data");
|
||||
const fullPath = `${dir}/${file}`;
|
||||
|
||||
try {
|
||||
|
|
@ -104,7 +104,7 @@ async function download(dir: string, file: string): Promise<string | any> {
|
|||
|
||||
await mkdirp(path.join(dataDir, dir));
|
||||
|
||||
if (res.headers.get('Content-Type') === 'application/json') {
|
||||
if (res.headers.get("Content-Type") === "application/json") {
|
||||
const json = await res.json();
|
||||
fsp.writeFile(path.join(dataDir, fullPath), JSON.stringify(json));
|
||||
return json;
|
||||
|
|
@ -112,8 +112,8 @@ async function download(dir: string, file: string): Promise<string | any> {
|
|||
const fileStream = fs.createWriteStream(path.join(dataDir, fullPath));
|
||||
await new Promise((resolve, rej) => {
|
||||
res.body.pipe(fileStream);
|
||||
res.body.on('error', rej);
|
||||
fileStream.on('finish', resolve);
|
||||
res.body.on("error", rej);
|
||||
fileStream.on("finish", resolve);
|
||||
});
|
||||
|
||||
return fileStream.path.toString();
|
||||
|
|
@ -144,7 +144,7 @@ function queueTexturesAndModels(item: any): void {
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof item.Model === 'number' && item.Model !== 0) {
|
||||
if (typeof item.Model === "number" && item.Model !== 0) {
|
||||
modelsDownloadQueue.add(item.Model);
|
||||
}
|
||||
|
||||
|
|
@ -166,30 +166,30 @@ function queueTexturesAndModels(item: any): void {
|
|||
}
|
||||
|
||||
async function downloadRaces(): Promise<void> {
|
||||
const races = ['human', 'nightelf', 'dwarf', 'gnome', 'draenei', 'orc', 'troll', 'tauren', 'bloodelf', 'scourge'];
|
||||
const genders = ['male', 'female'];
|
||||
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);
|
||||
const progress = new Progress("Downloading races data...", raceGenderCombo.length);
|
||||
|
||||
await promisepool.PromisePool.for(raceGenderCombo)
|
||||
.withConcurrency(4)
|
||||
.process(async (race) => {
|
||||
const characterJson = await download('meta/character', `${race}.json`);
|
||||
const characterJson = await download("meta/character", `${race}.json`);
|
||||
modelsDownloadQueue.add(characterJson.Model);
|
||||
|
||||
const customizationJson = await download('meta/charactercustomization2', `${characterJson.Race}_${characterJson.Gender}.json`);
|
||||
const customizationJson = await download("meta/charactercustomization2", `${characterJson.Race}_${characterJson.Gender}.json`);
|
||||
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' &&
|
||||
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) {
|
||||
if (element.BoneSet !== null && typeof element.BoneSet.BoneFileDataID === "number" && element.BoneSet.BoneFileDataID !== 0) {
|
||||
bonesDownloadQueue.add(element.BoneSet.BoneFileDataID);
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +215,7 @@ async function downloadArmors(): Promise<void> {
|
|||
.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.for(rows)
|
||||
.withConcurrency(50)
|
||||
|
|
@ -226,7 +226,7 @@ async function downloadArmors(): Promise<void> {
|
|||
return;
|
||||
}
|
||||
const appearance = dbcItemAppearanceById[modifiedAppearance.itemAppearanceId];
|
||||
const metaPath = [invTypeShield, invTypeOffHand].includes(row.inventoryType) ? 'item' : `armor/${row.inventoryType}`;
|
||||
const metaPath = [invTypeShield, invTypeOffHand].includes(row.inventoryType) ? "item" : `armor/${row.inventoryType}`;
|
||||
try {
|
||||
const itemJson = await download(`meta/${metaPath}`, `${appearance.itemDisplayInfoId}.json`);
|
||||
queueTexturesAndModels(itemJson);
|
||||
|
|
@ -249,7 +249,7 @@ async function downloadWeapons(): Promise<void> {
|
|||
.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.for(rows)
|
||||
.withConcurrency(50)
|
||||
|
|
@ -277,7 +277,7 @@ async function downloadWeapons(): Promise<void> {
|
|||
}
|
||||
|
||||
async function readDbcData(): Promise<void> {
|
||||
console.log('Reading DBC data...');
|
||||
console.log("Reading DBC data...");
|
||||
|
||||
dbc = new DbcManager();
|
||||
await dbc.loadAllFiles();
|
||||
|
|
@ -310,7 +310,7 @@ async function downloadMounts(): Promise<void> {
|
|||
.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.for(mountSpells)
|
||||
.withConcurrency(50)
|
||||
|
|
@ -322,7 +322,7 @@ async function downloadMounts(): Promise<void> {
|
|||
}
|
||||
|
||||
const display = dbcMountDisplayByMountId[mount.id];
|
||||
const json = await download('meta/npc', `${display.creatureDisplayInfoId}.json`);
|
||||
const json = await download("meta/npc", `${display.creatureDisplayInfoId}.json`);
|
||||
queueTexturesAndModels(json);
|
||||
|
||||
progress.increment();
|
||||
|
|
@ -332,12 +332,12 @@ async function downloadMounts(): 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.for(Array.from(texturesDownloadQueue))
|
||||
.withConcurrency(25)
|
||||
.process(async (fileDataId) => {
|
||||
await download('textures', `${fileDataId}.png`);
|
||||
await download("textures", `${fileDataId}.png`);
|
||||
progress.increment();
|
||||
});
|
||||
|
||||
|
|
@ -345,12 +345,12 @@ async function downloadTextures(): 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.for(Array.from(modelsDownloadQueue))
|
||||
.withConcurrency(25)
|
||||
.process(async (fileDataId) => {
|
||||
await download('mo3', `${fileDataId}.mo3`);
|
||||
await download("mo3", `${fileDataId}.mo3`);
|
||||
progress.increment();
|
||||
});
|
||||
|
||||
|
|
@ -358,13 +358,13 @@ async function downloadModels(): 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.for(Array.from(bonesDownloadQueue))
|
||||
.withConcurrency(25)
|
||||
.process(async (fileDataId) => {
|
||||
try {
|
||||
await download('bone', `${fileDataId}.bone`);
|
||||
await download("bone", `${fileDataId}.bone`);
|
||||
progress.increment();
|
||||
} catch (err) {
|
||||
if (err instanceof HttpRequestError && err.response.status === 404) {
|
||||
|
|
@ -379,8 +379,8 @@ async function downloadBones(): Promise<void> {
|
|||
}
|
||||
|
||||
async function parseModels(): Promise<void> {
|
||||
const files = await glob('data/mo3/*.mo3');
|
||||
const progress = new Progress('Reading model files for texture references...', files.length);
|
||||
const files = await glob("data/mo3/*.mo3");
|
||||
const progress = new Progress("Reading model files for texture references...", files.length);
|
||||
|
||||
await promisepool.PromisePool.for(files)
|
||||
.withConcurrency(20)
|
||||
|
|
@ -425,7 +425,7 @@ async function main(): Promise<void> {
|
|||
await downloadTextures(); // Download all queued textures
|
||||
await downloadBones(); // Download all queued bones
|
||||
|
||||
sw.stop('Everything done in {time}');
|
||||
sw.stop("Everything done in {time}");
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
function waitForEmblemImages($emblem) {
|
||||
return Promise.all(
|
||||
$emblem.find('.images img').map((idx, img) => {
|
||||
$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);
|
||||
img.addEventListener("load", res);
|
||||
img.addEventListener("error", rej);
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
|
@ -15,19 +15,19 @@ function waitForEmblemImages($emblem) {
|
|||
|
||||
function createGuildEmblem(emblem, el) {
|
||||
const $emblem = $(el);
|
||||
const canvas = $emblem.find('canvas')[0];
|
||||
const ctx = canvas.getContext('2d');
|
||||
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`;
|
||||
`${handlebarsData.websiteRoot}/img/guild-emblems/${type}_${value}${value2 ? "_" + value2 : ""}_T${section}_U.PNG`;
|
||||
|
||||
const $images = $('<div>').addClass('images').appendTo($emblem);
|
||||
const bgUpper = $('<img>').attr('src', imgUrl('Background', 'U', emblem.background)).appendTo($images)[0];
|
||||
const bgLower = $('<img>').attr('src', imgUrl('Background', 'L', emblem.background)).appendTo($images)[0];
|
||||
const iconUpper = $('<img>').attr('src', imgUrl('Emblem', 'U', emblem.icon, emblem.iconColor)).appendTo($images)[0];
|
||||
const iconLower = $('<img>').attr('src', imgUrl('Emblem', 'L', emblem.icon, emblem.iconColor)).appendTo($images)[0];
|
||||
const borderUpper = $('<img>').attr('src', imgUrl('Border', 'U', emblem.border, emblem.borderColor)).appendTo($images)[0];
|
||||
const borderLower = $('<img>').attr('src', imgUrl('Border', 'L', emblem.border, emblem.borderColor)).appendTo($images)[0];
|
||||
const $images = $("<div>").addClass("images").appendTo($emblem);
|
||||
const bgUpper = $("<img>").attr("src", imgUrl("Background", "U", emblem.background)).appendTo($images)[0];
|
||||
const bgLower = $("<img>").attr("src", imgUrl("Background", "L", emblem.background)).appendTo($images)[0];
|
||||
const iconUpper = $("<img>").attr("src", imgUrl("Emblem", "U", emblem.icon, emblem.iconColor)).appendTo($images)[0];
|
||||
const iconLower = $("<img>").attr("src", imgUrl("Emblem", "L", emblem.icon, emblem.iconColor)).appendTo($images)[0];
|
||||
const borderUpper = $("<img>").attr("src", imgUrl("Border", "U", emblem.border, emblem.borderColor)).appendTo($images)[0];
|
||||
const borderLower = $("<img>").attr("src", imgUrl("Border", "L", emblem.border, emblem.borderColor)).appendTo($images)[0];
|
||||
|
||||
const drawEmblemLayer = (ctx, layer) => {
|
||||
const [upper, lower] = layer;
|
||||
|
|
@ -64,21 +64,21 @@ function createGuildEmblem(emblem, el) {
|
|||
|
||||
function createArenaEmblem(teamSize, emblem, el) {
|
||||
const $emblem = $(el);
|
||||
const canvas = $emblem.find('canvas')[0];
|
||||
const ctx = canvas.getContext('2d');
|
||||
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 : ''
|
||||
`${handlebarsData.websiteRoot}/img/arena-banners/PVP-Banner${teamSize ? "-" + teamSize : ""}${type ? "-" + type : ""}${
|
||||
value ? "-" + value : ""
|
||||
}.PNG`;
|
||||
|
||||
const $images = $('<div>').addClass('images').appendTo($emblem);
|
||||
const banner = $('<img>').attr('src', imgUrl(teamSize)).appendTo($images)[0];
|
||||
const bannerCrop = $('<img>').attr('src', imgUrl(teamSize, 'Crop')).appendTo($images)[0];
|
||||
const border = $('<img>').attr('src', imgUrl(teamSize, 'Border', emblem.border)).appendTo($images)[0];
|
||||
const icon = $('<img>').attr('src', imgUrl(undefined, 'Emblem', emblem.icon)).appendTo($images)[0];
|
||||
const $images = $("<div>").addClass("images").appendTo($emblem);
|
||||
const banner = $("<img>").attr("src", imgUrl(teamSize)).appendTo($images)[0];
|
||||
const bannerCrop = $("<img>").attr("src", imgUrl(teamSize, "Crop")).appendTo($images)[0];
|
||||
const border = $("<img>").attr("src", imgUrl(teamSize, "Border", emblem.border)).appendTo($images)[0];
|
||||
const icon = $("<img>").attr("src", imgUrl(undefined, "Emblem", emblem.icon)).appendTo($images)[0];
|
||||
|
||||
const colorToHex = (color) => '#' + parseInt(color).toString(16).substring(2);
|
||||
const colorToHex = (color) => "#" + parseInt(color).toString(16).substring(2);
|
||||
|
||||
waitForEmblemImages($emblem).then(() => {
|
||||
const srcH = 224;
|
||||
|
|
@ -93,8 +93,8 @@ function createArenaEmblem(teamSize, emblem, el) {
|
|||
});
|
||||
}
|
||||
|
||||
const tintCanvas = document.createElement('canvas');
|
||||
const tintContext = tintCanvas.getContext('2d');
|
||||
const tintCanvas = document.createElement("canvas");
|
||||
const tintContext = tintCanvas.getContext("2d");
|
||||
function tintImage(image, color, opacity = 1.0) {
|
||||
const ctx = tintContext;
|
||||
|
||||
|
|
@ -106,12 +106,12 @@ function tintImage(image, color, opacity = 1.0) {
|
|||
|
||||
// Multiply with a rectangle of the specified color
|
||||
ctx.fillStyle = color;
|
||||
ctx.globalCompositeOperation = 'multiply';
|
||||
ctx.globalCompositeOperation = "multiply";
|
||||
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
|
||||
// Finally, fix masking issues and globalAlpha
|
||||
ctx.globalAlpha = opacity;
|
||||
ctx.globalCompositeOperation = 'destination-in';
|
||||
ctx.globalCompositeOperation = "destination-in";
|
||||
ctx.drawImage(image, 0, 0);
|
||||
|
||||
return ctx.canvas;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
window.parent.postMessage(
|
||||
{
|
||||
url: window.location.pathname.replace(handlebarsData.websiteRoot, ''),
|
||||
url: window.location.pathname.replace(handlebarsData.websiteRoot, ""),
|
||||
},
|
||||
'*',
|
||||
"*",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
"outDir": "build",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue