Validate camp campaign step references
This commit is contained in:
@@ -13,6 +13,7 @@ const server = await createServer({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const { battleScenarios, defaultBattleScenario } = await server.ssrLoadModule('/src/game/data/battles.ts');
|
const { battleScenarios, defaultBattleScenario } = await server.ssrLoadModule('/src/game/data/battles.ts');
|
||||||
|
const { isCampaignStep } = await server.ssrLoadModule('/src/game/state/campaignState.ts');
|
||||||
const itemRewardArrays = collectItemRewardArrays(source);
|
const itemRewardArrays = collectItemRewardArrays(source);
|
||||||
itemRewardArrays.forEach(({ body, index, offset }) => validateItemRewards(body, index, offset));
|
itemRewardArrays.forEach(({ body, index, offset }) => validateItemRewards(body, index, offset));
|
||||||
const campBattleIdEntries = collectCampBattleIdEntries(source, defaultBattleScenario.id);
|
const campBattleIdEntries = collectCampBattleIdEntries(source, defaultBattleScenario.id);
|
||||||
@@ -20,8 +21,9 @@ try {
|
|||||||
validateCampBattleIdEntries(campBattleIdEntries, battleScenarios);
|
validateCampBattleIdEntries(campBattleIdEntries, battleScenarios);
|
||||||
const dialogueEvents = collectCampEvents(source, 'campDialogues');
|
const dialogueEvents = collectCampEvents(source, 'campDialogues');
|
||||||
const visitEvents = collectCampEvents(source, 'campVisits');
|
const visitEvents = collectCampEvents(source, 'campVisits');
|
||||||
validateCampEventCollection(dialogueEvents, 'campDialogues', campBattleIdKeys);
|
const campaignStepReferences =
|
||||||
validateCampEventCollection(visitEvents, 'campVisits', campBattleIdKeys);
|
validateCampEventCollection(dialogueEvents, 'campDialogues', campBattleIdKeys, isCampaignStep) +
|
||||||
|
validateCampEventCollection(visitEvents, 'campVisits', campBattleIdKeys, isCampaignStep);
|
||||||
validateNumericProperties('gold', { min: 1, max: 20000 });
|
validateNumericProperties('gold', { min: 1, max: 20000 });
|
||||||
validateNumericProperties('bondExp', { min: 0, max: 200 });
|
validateNumericProperties('bondExp', { min: 0, max: 200 });
|
||||||
validateNumericProperties('rewardExp', { min: 1, max: 200 });
|
validateNumericProperties('rewardExp', { min: 1, max: 200 });
|
||||||
@@ -31,7 +33,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Verified ${dialogueEvents.length} camp dialogues, ${visitEvents.length} camp visits, ${campBattleIdEntries.length} camp battle ids, ${itemRewardArrays.length} camp item reward lists, and camp reward numeric fields.`
|
`Verified ${dialogueEvents.length} camp dialogues, ${visitEvents.length} camp visits, ${campBattleIdEntries.length} camp battle ids, ${campaignStepReferences} campaign-step references, ${itemRewardArrays.length} camp item reward lists, and camp reward numeric fields.`
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
await server.close();
|
await server.close();
|
||||||
@@ -133,8 +135,9 @@ function collectCampEvents(text, arrayName) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateCampEventCollection(events, collectionName, campBattleIdKeys) {
|
function validateCampEventCollection(events, collectionName, campBattleIdKeys, isCampaignStep) {
|
||||||
const seenIds = new Map();
|
const seenIds = new Map();
|
||||||
|
let campaignStepReferenceCount = 0;
|
||||||
if (events.length === 0) {
|
if (events.length === 0) {
|
||||||
errors.push(`${sourcePath}: ${collectionName} has no entries`);
|
errors.push(`${sourcePath}: ${collectionName} has no entries`);
|
||||||
}
|
}
|
||||||
@@ -176,7 +179,29 @@ function validateCampEventCollection(events, collectionName, campBattleIdKeys) {
|
|||||||
errors.push(`${sourcePath}:${lineNumber(event.offset)} ${context} references unknown campBattleIds.${reference[1]}`);
|
errors.push(`${sourcePath}:${lineNumber(event.offset)} ${context} references unknown campBattleIds.${reference[1]}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
campaignStepReferenceCount += validateAvailableDuringSteps(event, context, isCampaignStep);
|
||||||
});
|
});
|
||||||
|
return campaignStepReferenceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAvailableDuringSteps(event, context, isCampaignStep) {
|
||||||
|
const availableDuringMatch = /availableDuringSteps:\s*\[([\s\S]*?)\]/.exec(event.body);
|
||||||
|
if (!availableDuringMatch) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = availableDuringMatch[1];
|
||||||
|
const bodyOffset = event.offset + (availableDuringMatch.index ?? 0) + availableDuringMatch[0].indexOf(body);
|
||||||
|
const steps = collectStringLiterals(body, bodyOffset);
|
||||||
|
if (steps.length === 0) {
|
||||||
|
errors.push(`${sourcePath}:${lineNumber(bodyOffset)} ${context} has an empty availableDuringSteps list`);
|
||||||
|
}
|
||||||
|
steps.forEach((step) => {
|
||||||
|
if (!isCampaignStep(step.value)) {
|
||||||
|
errors.push(`${sourcePath}:${lineNumber(step.offset)} ${context} references unknown campaign step "${step.value}"`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return steps.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectStringProperties(text, propertyName) {
|
function collectStringProperties(text, propertyName) {
|
||||||
@@ -187,6 +212,13 @@ function collectStringProperties(text, propertyName) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function collectStringLiterals(text, offset = 0) {
|
||||||
|
return [...text.matchAll(/'((?:\\'|[^'])*)'/g)].map((match) => ({
|
||||||
|
value: match[1].replace(/\\'/g, "'"),
|
||||||
|
offset: offset + (match.index ?? 0)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
function parseRewardLabel(reward) {
|
function parseRewardLabel(reward) {
|
||||||
const normalized = String(reward).replace(/\s+/g, ' ').trim();
|
const normalized = String(reward).replace(/\s+/g, ' ').trim();
|
||||||
const match = normalized.match(/^(.*?)(?:\s*[+xX]?\s*(\d+))$/);
|
const match = normalized.match(/^(.*?)(?:\s*[+xX]?\s*(\d+))$/);
|
||||||
|
|||||||
Reference in New Issue
Block a user