Initial import
This commit is contained in:
commit
ab891a315c
773 changed files with 257255 additions and 0 deletions
108
src/workers/validationWorker.ts
Normal file
108
src/workers/validationWorker.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
|
||||
type JsonObject = { [key: string]: JsonValue };
|
||||
|
||||
type ValidationRequest = {
|
||||
requestId: number;
|
||||
activeType: string;
|
||||
rootKey: string;
|
||||
parsedPayload: JsonObject | null;
|
||||
records: JsonObject[];
|
||||
};
|
||||
|
||||
type ValidationResponse = {
|
||||
requestId: number;
|
||||
issues: string[];
|
||||
};
|
||||
|
||||
function isPlainObject(value: JsonValue | undefined): value is JsonObject {
|
||||
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function getDialogueNodes(record: JsonObject): JsonObject[] {
|
||||
const raw = record.dialogueNodes;
|
||||
if (!Array.isArray(raw)) {
|
||||
return [];
|
||||
}
|
||||
return raw.filter((entry) => isPlainObject(entry));
|
||||
}
|
||||
|
||||
function computeValidationIssues(input: Omit<ValidationRequest, "requestId">): string[] {
|
||||
const { activeType, rootKey, parsedPayload, records } = input;
|
||||
const issues: string[] = [];
|
||||
|
||||
if (!parsedPayload || !rootKey) {
|
||||
return issues;
|
||||
}
|
||||
|
||||
const rawList = parsedPayload[rootKey];
|
||||
if (!Array.isArray(rawList)) {
|
||||
issues.push(`Expected ${rootKey} to be an array.`);
|
||||
return issues;
|
||||
}
|
||||
|
||||
const seen = new Set<string | number>();
|
||||
|
||||
records.forEach((record, index) => {
|
||||
if (activeType === "quests") {
|
||||
const questId = Number(record.questId);
|
||||
if (!Number.isInteger(questId) || questId < 1) {
|
||||
issues.push(`Record ${index + 1}: questId must be an integer >= 1.`);
|
||||
} else if (seen.has(questId)) {
|
||||
issues.push(`Duplicate questId found: ${questId}.`);
|
||||
} else {
|
||||
seen.add(questId);
|
||||
}
|
||||
} else {
|
||||
const id = String(record.id || "").trim();
|
||||
if (!id) {
|
||||
issues.push(`Record ${index + 1}: id is required.`);
|
||||
} else if (seen.has(id)) {
|
||||
issues.push(`Duplicate id found: ${id}.`);
|
||||
} else {
|
||||
seen.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
const name = String(record.name || "").trim();
|
||||
if (activeType !== "npcs" && !name) {
|
||||
issues.push(`Record ${index + 1}: name is required.`);
|
||||
}
|
||||
|
||||
if (activeType === "npcs") {
|
||||
const templateId = String(record.templateId || "").trim();
|
||||
const mapId = String(record.mapId || "").trim();
|
||||
if (templateId) {
|
||||
issues.push(`NPC instance ${record.id || index + 1}: templateId is no longer stored on disk.`);
|
||||
}
|
||||
if (mapId) {
|
||||
issues.push(`NPC instance ${record.id || index + 1}: mapId is no longer stored on disk.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (activeType === "dialogues") {
|
||||
const npcNodes = getDialogueNodes(record);
|
||||
const seenNodeIds = new Set<string>();
|
||||
npcNodes.forEach((node, nodeIndex) => {
|
||||
const nodeId = String(node.id || "").trim();
|
||||
if (!nodeId) {
|
||||
issues.push(`Dialogue ${record.id || index + 1} node ${nodeIndex + 1}: id is required.`);
|
||||
return;
|
||||
}
|
||||
if (seenNodeIds.has(nodeId)) {
|
||||
issues.push(`Dialogue ${record.id || index + 1}: duplicate node id ${nodeId}.`);
|
||||
return;
|
||||
}
|
||||
seenNodeIds.add(nodeId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
self.onmessage = (event: MessageEvent<ValidationRequest>) => {
|
||||
const { requestId, activeType, rootKey, parsedPayload, records } = event.data;
|
||||
const issues = computeValidationIssues({ activeType, rootKey, parsedPayload, records });
|
||||
const response: ValidationResponse = { requestId, issues };
|
||||
self.postMessage(response);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue