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' }] }],
|
['unknown attack intent unit id', { attackIntents: [{ attackerId: 'liu-bei', targetId: 'ghost-unit' }] }],
|
||||||
['self-targeting attack intent', { attackIntents: [{ attackerId: 'liu-bei', targetId: 'liu-bei' }] }],
|
['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' }] }],
|
['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: {} }],
|
['invalid units array', { units: {} }],
|
||||||
['too high unit level', { units: patchUnit(0, { level: 100, exp: 0 }) }],
|
['too high unit level', { units: patchUnit(0, { level: 100, exp: 0 }) }],
|
||||||
['invalid unit exp threshold', { units: patchUnit(0, { exp: 100 }) }],
|
['invalid unit exp threshold', { units: patchUnit(0, { exp: 100 }) }],
|
||||||
|
|||||||
@@ -142,16 +142,23 @@ export function isValidBattleSaveState(state: unknown, options: BattleSaveValida
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const attackIntents = state.attackIntents;
|
||||||
|
const units = state.units;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isUnitIdArray(state.actedUnitIds, options) ||
|
!isUnitIdArray(state.actedUnitIds, options) ||
|
||||||
!isBattleLog(state.battleLog) ||
|
!isBattleLog(state.battleLog) ||
|
||||||
!isAttackIntentArray(state.attackIntents, options) ||
|
!isAttackIntentArray(attackIntents, options) ||
|
||||||
!areSavedBattleUnitsValid(state.units, options) ||
|
!areSavedBattleUnitsValid(units, options) ||
|
||||||
!isBondArray(state.bonds, options)
|
!isBondArray(state.bonds, options)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!areAttackIntentsTargetingLiveUnits(attackIntents, units)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isOptionalItemStockRecord(state.itemStocks, options) ||
|
!isOptionalItemStockRecord(state.itemStocks, options) ||
|
||||||
!isOptionalBuffArray(state.battleBuffs, 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 (
|
return (
|
||||||
Array.isArray(value) &&
|
Array.isArray(value) &&
|
||||||
value.length <= unitReferenceLimit(options) &&
|
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 seenUnitIds = new Set<string>();
|
||||||
const seenLiveTileKeys = 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));
|
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 {
|
function isSavedBattleUnitState(value: unknown, options: BattleSaveValidationOptions): value is SavedBattleUnitState {
|
||||||
if (!isRecord(value) || typeof value.id !== 'string' || value.id.length === 0 || !isEquipmentSet(value.equipment, options)) {
|
if (!isRecord(value) || typeof value.id !== 'string' || value.id.length === 0 || !isEquipmentSet(value.equipment, options)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user