diff --git a/scripts/verify-battle-save-normalization.mjs b/scripts/verify-battle-save-normalization.mjs index 9224d91..e7a2b44 100644 --- a/scripts/verify-battle-save-normalization.mjs +++ b/scripts/verify-battle-save-normalization.mjs @@ -71,6 +71,9 @@ try { ['unknown unit id', { units: patchUnit(0, { id: 'ghost-unit' }) }], ['duplicate unit id', { units: [validState.units[0], { ...validState.units[0], x: 2 }, validState.units[2]] }], ['invalid bonds', { bonds: [{ ...validState.bonds[0], unitIds: ['liu-bei'] }] }], + ['empty bond id', { bonds: [{ ...validState.bonds[0], id: '' }] }], + ['duplicate bond id', { bonds: [validState.bonds[0], { ...validState.bonds[0], unitIds: ['guan-yu', 'liu-bei'] }] }], + ['too many bonds', { bonds: Array.from({ length: 129 }, (_, index) => ({ ...validState.bonds[0], id: `bond-${index}` })) }], ['unknown bond unit id', { bonds: [{ ...validState.bonds[0], unitIds: ['liu-bei', 'ghost-unit'] }] }], ['invalid bond level', { bonds: [{ ...validState.bonds[0], level: 0 }] }], ['too high bond level', { bonds: [{ ...validState.bonds[0], level: 101 }] }], diff --git a/src/game/state/battleSaveState.ts b/src/game/state/battleSaveState.ts index e784af1..e1a1732 100644 --- a/src/game/state/battleSaveState.ts +++ b/src/game/state/battleSaveState.ts @@ -83,6 +83,7 @@ type BattleSaveValidationOptions = { const unitDirections = new Set(['south', 'east', 'north', 'west']); const maxBattleLogEntries = 10; const maxBattleLogEntryLength = 96; +const maxBattleBondEntries = 128; const maxTriggeredBattleEventLength = 96; const defaultBattleSaveArrayLimit = 128; const maxStatusKindsPerUnit = 2; @@ -310,10 +311,13 @@ function isValidEquipmentProgress(level: unknown, exp: unknown) { function isBondArray(value: unknown, options: BattleSaveValidationOptions) { return ( Array.isArray(value) && + value.length <= maxBattleBondEntries && + hasUniqueRecordStrings(value, 'id') && value.every( (bond) => isRecord(bond) && typeof bond.id === 'string' && + bond.id.length > 0 && Array.isArray(bond.unitIds) && bond.unitIds.length === 2 && bond.unitIds.every((unitId) => typeof unitId === 'string' && isKnownUnitId(unitId, options)) &&