Reject stale battle save attack intents
This commit is contained in:
@@ -54,6 +54,8 @@ try {
|
||||
['unknown attack intent unit id', { attackIntents: [{ attackerId: 'liu-bei', targetId: 'ghost-unit' }] }],
|
||||
['self-targeting attack intent', { attackIntents: [{ attackerId: 'liu-bei', targetId: 'liu-bei' }] }],
|
||||
['duplicate attack intent attacker id', { attackIntents: [{ attackerId: 'liu-bei', targetId: 'rebel-1' }, { attackerId: 'liu-bei', targetId: 'rebel-1' }] }],
|
||||
['defeated attack intent attacker', { units: patchUnit(0, { hp: 0 }) }],
|
||||
['defeated attack intent target', { units: patchUnit(2, { hp: 0 }) }],
|
||||
['invalid units array', { units: {} }],
|
||||
['too high unit level', { units: patchUnit(0, { level: 100, exp: 0 }) }],
|
||||
['invalid unit exp threshold', { units: patchUnit(0, { exp: 100 }) }],
|
||||
|
||||
@@ -142,16 +142,23 @@ export function isValidBattleSaveState(state: unknown, options: BattleSaveValida
|
||||
return false;
|
||||
}
|
||||
|
||||
const attackIntents = state.attackIntents;
|
||||
const units = state.units;
|
||||
|
||||
if (
|
||||
!isUnitIdArray(state.actedUnitIds, options) ||
|
||||
!isBattleLog(state.battleLog) ||
|
||||
!isAttackIntentArray(state.attackIntents, options) ||
|
||||
!areSavedBattleUnitsValid(state.units, options) ||
|
||||
!isAttackIntentArray(attackIntents, options) ||
|
||||
!areSavedBattleUnitsValid(units, options) ||
|
||||
!isBondArray(state.bonds, options)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!areAttackIntentsTargetingLiveUnits(attackIntents, units)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!isOptionalItemStockRecord(state.itemStocks, options) ||
|
||||
!isOptionalBuffArray(state.battleBuffs, options) ||
|
||||
@@ -219,7 +226,7 @@ function isBattleLog(value: unknown) {
|
||||
);
|
||||
}
|
||||
|
||||
function isAttackIntentArray(value: unknown, options: BattleSaveValidationOptions) {
|
||||
function isAttackIntentArray(value: unknown, options: BattleSaveValidationOptions): value is BattleSaveAttackIntent[] {
|
||||
return (
|
||||
Array.isArray(value) &&
|
||||
value.length <= unitReferenceLimit(options) &&
|
||||
@@ -236,7 +243,7 @@ function isAttackIntentArray(value: unknown, options: BattleSaveValidationOption
|
||||
);
|
||||
}
|
||||
|
||||
function areSavedBattleUnitsValid(units: unknown[], options: BattleSaveValidationOptions) {
|
||||
function areSavedBattleUnitsValid(units: unknown[], options: BattleSaveValidationOptions): units is SavedBattleUnitState[] {
|
||||
const seenUnitIds = new Set<string>();
|
||||
const seenLiveTileKeys = new Set<string>();
|
||||
|
||||
@@ -266,6 +273,11 @@ function areSavedBattleUnitsValid(units: unknown[], options: BattleSaveValidatio
|
||||
return [...seenUnitIds].every((unitId) => options.validUnitIds?.has(unitId));
|
||||
}
|
||||
|
||||
function areAttackIntentsTargetingLiveUnits(attackIntents: BattleSaveAttackIntent[], units: SavedBattleUnitState[]) {
|
||||
const liveUnitIds = new Set(units.filter((unit) => unit.hp > 0).map((unit) => unit.id));
|
||||
return attackIntents.every((intent) => liveUnitIds.has(intent.attackerId) && liveUnitIds.has(intent.targetId));
|
||||
}
|
||||
|
||||
function isSavedBattleUnitState(value: unknown, options: BattleSaveValidationOptions): value is SavedBattleUnitState {
|
||||
if (!isRecord(value) || typeof value.id !== 'string' || value.id.length === 0 || !isEquipmentSet(value.equipment, options)) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user