forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
39458d5de6
commit
6cc1b9217f
203 files changed
+133929
-31271
No files matched your search
@@ -41,6 +41,20 @@ const epochDungeonSourceFile = path.join(
|
||||
*/
|
||||
export const DEFAULT_AZEROTHCORE_COMMIT = "4d9d1d4b5723e819c5c390f6ca1177283dbfb8e3";
|
||||
|
||||
export const PINNED_CREATURE_IMMUNITIES_SOURCE = Object.freeze({
|
||||
repository: "https://github.com/azerothcore/azerothcore-wotlk",
|
||||
commit: DEFAULT_AZEROTHCORE_COMMIT,
|
||||
path: "data/sql/base/db_world/creature_immunities.sql",
|
||||
url: `https://raw.githubusercontent.com/azerothcore/azerothcore-wotlk/${DEFAULT_AZEROTHCORE_COMMIT}/data/sql/base/db_world/creature_immunities.sql`,
|
||||
sha256: "aee81a1d8b99986f8498a2b4c51b64eaf4b9095a0d1a12bbf3705d9588a90a13",
|
||||
fixtureRoot: path.join(
|
||||
projectRoot,
|
||||
"dungeon-pipeline",
|
||||
"source-fixtures",
|
||||
`azerothcore-${DEFAULT_AZEROTHCORE_COMMIT}`,
|
||||
),
|
||||
});
|
||||
|
||||
const SOURCE_TABLES = Object.freeze([
|
||||
"creature",
|
||||
"creature_template",
|
||||
@@ -303,16 +317,37 @@ function bitMaskNames(maskValue, names, bitOffset = 0) {
|
||||
));
|
||||
}
|
||||
|
||||
function creatureTemplateReference(row) {
|
||||
export function creatureTemplateReference(row, creatureImmunitiesById = new Map()) {
|
||||
const entry = numeric(firstValue(row, ["entry", "CreatureID", "creatureId"]));
|
||||
const mechanicImmuneMask = numeric(firstValue(
|
||||
row,
|
||||
["mechanic_immune_mask", "mechanicImmuneMask", "CreatureImmunitiesId"],
|
||||
));
|
||||
const spellSchoolImmuneMask = numeric(firstValue(
|
||||
const legacyMechanicImmuneMask = firstValue(row, ["mechanic_immune_mask", "mechanicImmuneMask"]);
|
||||
const creatureImmunitiesId = firstValue(row, ["CreatureImmunitiesId", "creatureImmunitiesId"]);
|
||||
let mechanicImmuneMask = numeric(legacyMechanicImmuneMask);
|
||||
let spellSchoolImmuneMask = numeric(firstValue(
|
||||
row,
|
||||
["spell_school_immune_mask", "spellSchoolImmuneMask"],
|
||||
));
|
||||
if (legacyMechanicImmuneMask === undefined && creatureImmunitiesId !== undefined) {
|
||||
const immunityId = numeric(creatureImmunitiesId);
|
||||
if (immunityId !== 0) {
|
||||
const immunity = creatureImmunitiesById.get(immunityId);
|
||||
if (!immunity) {
|
||||
throw new Error(
|
||||
`Creature ${entry} references missing creature_immunities.ID ${immunityId}.`,
|
||||
);
|
||||
}
|
||||
const sourceMechanicsMask = numeric(firstValue(immunity, ["MechanicsMask", "mechanicsMask"]));
|
||||
if (!Number.isSafeInteger(sourceMechanicsMask) || sourceMechanicsMask < 0) {
|
||||
throw new Error(
|
||||
`creature_immunities.ID ${immunityId} has an unsupported MechanicsMask ${sourceMechanicsMask}.`,
|
||||
);
|
||||
}
|
||||
// CreatureImmunities.Mechanic stores bit N at the mechanic enum value N.
|
||||
// The legacy creature_template mask stores bit N-1. Normalize back to
|
||||
// that established runtime representation before decoding names below.
|
||||
mechanicImmuneMask = Math.floor(sourceMechanicsMask / 2);
|
||||
spellSchoolImmuneMask = numeric(firstValue(immunity, ["SchoolMask", "schoolMask"]));
|
||||
}
|
||||
}
|
||||
return {
|
||||
entry,
|
||||
name: String(firstValue(row, ["name", "Name"]) ?? `Creature ${entry}`),
|
||||
@@ -589,7 +624,13 @@ function parseColumns(sql, tableName) {
|
||||
return columns;
|
||||
}
|
||||
|
||||
async function parseTable(sourceRoot, tableName, visitor) {
|
||||
export function creatureTemplateUsesImmunitiesReference(sql) {
|
||||
return parseColumns(sql, "creature_template").some((column) => (
|
||||
column === "CreatureImmunitiesId" || column === "creatureImmunitiesId"
|
||||
));
|
||||
}
|
||||
|
||||
export async function parseTable(sourceRoot, tableName, visitor) {
|
||||
const file = path.join(sourceRoot, `${tableName}.sql`);
|
||||
const buffer = await readFile(file);
|
||||
const sql = buffer.toString("utf8");
|
||||
@@ -627,6 +668,27 @@ async function fetchSources(sourceRoot, commit) {
|
||||
sha256: sha256(buffer),
|
||||
});
|
||||
}
|
||||
const creatureTemplateSql = (await readFile(path.join(sourceRoot, "creature_template.sql"))).toString("utf8");
|
||||
if (creatureTemplateUsesImmunitiesReference(creatureTemplateSql)) {
|
||||
const tableName = "creature_immunities";
|
||||
const url = `${base}/${tableName}.sql`;
|
||||
const response = await fetch(url, {
|
||||
headers: { "User-Agent": "healer-man-dungeon-pipeline" },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`${tableName}: ${response.status} ${response.statusText} while fetching ${url}`);
|
||||
}
|
||||
const buffer = Buffer.from(await response.arrayBuffer());
|
||||
const file = path.join(sourceRoot, `${tableName}.sql`);
|
||||
await writeFile(file, buffer);
|
||||
reports.push({
|
||||
table: tableName,
|
||||
url,
|
||||
file: path.relative(projectRoot, file).replace(/\\/g, "/"),
|
||||
byteLength: buffer.length,
|
||||
sha256: sha256(buffer),
|
||||
});
|
||||
}
|
||||
await writeJson(path.join(sourceRoot, "source.lock.json"), {
|
||||
schemaVersion: 1,
|
||||
repository: "https://github.com/azerothcore/azerothcore-wotlk",
|
||||
@@ -857,6 +919,42 @@ export async function importAzerothCoreWorld({
|
||||
}
|
||||
}));
|
||||
|
||||
const creatureImmunitiesById = new Map();
|
||||
const creatureTemplateSql = (await readFile(
|
||||
path.join(resolvedSourceRoot, "creature_template.sql"),
|
||||
)).toString("utf8");
|
||||
if (creatureTemplateUsesImmunitiesReference(creatureTemplateSql)) {
|
||||
let creatureImmunitiesSourceRoot = resolvedSourceRoot;
|
||||
try {
|
||||
await readFile(path.join(creatureImmunitiesSourceRoot, "creature_immunities.sql"));
|
||||
} catch (error) {
|
||||
if (error?.code !== "ENOENT" || commit !== PINNED_CREATURE_IMMUNITIES_SOURCE.commit) throw error;
|
||||
creatureImmunitiesSourceRoot = PINNED_CREATURE_IMMUNITIES_SOURCE.fixtureRoot;
|
||||
}
|
||||
const creatureImmunitiesReport = await parseTable(
|
||||
creatureImmunitiesSourceRoot,
|
||||
"creature_immunities",
|
||||
(row) => {
|
||||
const id = numeric(firstValue(row, ["ID", "id"]));
|
||||
if (creatureImmunitiesById.has(id)) {
|
||||
throw new Error(`creature_immunities contains duplicate ID ${id}.`);
|
||||
}
|
||||
creatureImmunitiesById.set(id, row);
|
||||
},
|
||||
);
|
||||
if (commit === PINNED_CREATURE_IMMUNITIES_SOURCE.commit
|
||||
&& creatureImmunitiesReport.sha256 !== PINNED_CREATURE_IMMUNITIES_SOURCE.sha256) {
|
||||
throw new Error(
|
||||
`creature_immunities.sql does not match pinned ${commit} SHA-256 `
|
||||
+ `${PINNED_CREATURE_IMMUNITIES_SOURCE.sha256}.`,
|
||||
);
|
||||
}
|
||||
tableReports.push({
|
||||
...creatureImmunitiesReport,
|
||||
url: `https://raw.githubusercontent.com/azerothcore/azerothcore-wotlk/${commit}/data/sql/base/db_world/creature_immunities.sql`,
|
||||
});
|
||||
}
|
||||
|
||||
const templateByEntry = new Map();
|
||||
tableReports.push(await parseTable(resolvedSourceRoot, "creature_template", (row) => {
|
||||
const entry = numeric(firstValue(row, ["entry", "CreatureID", "creatureId"]));
|
||||
@@ -1137,7 +1235,7 @@ export async function importAzerothCoreWorld({
|
||||
const normalizedTemplates = Object.fromEntries(
|
||||
[...templateByEntry.entries()]
|
||||
.sort(([left], [right]) => left - right)
|
||||
.map(([entry, row]) => [entry, creatureTemplateReference(row)]),
|
||||
.map(([entry, row]) => [entry, creatureTemplateReference(row, creatureImmunitiesById)]),
|
||||
);
|
||||
const normalizedCreatureClassStats = Object.fromEntries(
|
||||
creatureClassLevelStats
|
||||
@@ -1170,9 +1268,10 @@ export async function importAzerothCoreWorld({
|
||||
}
|
||||
}
|
||||
|
||||
const sourceFiles = tableReports.map(({ file, columns, rows, byteLength, sha256: hash }) => ({
|
||||
const sourceFiles = tableReports.map(({ file, columns, rows, byteLength, sha256: hash, url }) => ({
|
||||
table: path.basename(file, ".sql"),
|
||||
file: path.basename(file),
|
||||
...(url ? { url } : {}),
|
||||
columns,
|
||||
rows,
|
||||
byteLength,
|
||||
|
||||
Reference in new issue
Block a user