Validate battle save unit references
This commit is contained in:
@@ -116,20 +116,20 @@ export function isValidBattleSaveState(state: unknown, options: BattleSaveValida
|
||||
}
|
||||
|
||||
if (
|
||||
!isStringArray(state.actedUnitIds) ||
|
||||
!isUnitIdArray(state.actedUnitIds, options) ||
|
||||
!isBattleLog(state.battleLog) ||
|
||||
!isAttackIntentArray(state.attackIntents) ||
|
||||
!isAttackIntentArray(state.attackIntents, options) ||
|
||||
!areSavedBattleUnitsValid(state.units, options) ||
|
||||
!isBondArray(state.bonds)
|
||||
!isBondArray(state.bonds, options)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!isOptionalNestedCountRecord(state.itemStocks) ||
|
||||
!isOptionalBuffArray(state.battleBuffs) ||
|
||||
!isOptionalStatusArray(state.battleStatuses) ||
|
||||
!isOptionalStatsRecord(state.battleStats) ||
|
||||
!isOptionalNestedCountRecord(state.itemStocks, options) ||
|
||||
!isOptionalBuffArray(state.battleBuffs, options) ||
|
||||
!isOptionalStatusArray(state.battleStatuses, options) ||
|
||||
!isOptionalStatsRecord(state.battleStats, options) ||
|
||||
!isOptionalStringArray(state.enemyUsableUseKeys) ||
|
||||
!isOptionalStringArray(state.triggeredBattleEvents)
|
||||
) {
|
||||
@@ -171,6 +171,10 @@ function isStringArray(value: unknown) {
|
||||
return Array.isArray(value) && value.every((entry) => typeof entry === 'string');
|
||||
}
|
||||
|
||||
function isUnitIdArray(value: unknown, options: BattleSaveValidationOptions) {
|
||||
return Array.isArray(value) && value.every((entry) => typeof entry === 'string' && isKnownUnitId(entry, options));
|
||||
}
|
||||
|
||||
function isOptionalStringArray(value: unknown) {
|
||||
return value === undefined || isStringArray(value);
|
||||
}
|
||||
@@ -179,10 +183,17 @@ function isBattleLog(value: unknown) {
|
||||
return Array.isArray(value) && value.every((entry) => typeof entry === 'string');
|
||||
}
|
||||
|
||||
function isAttackIntentArray(value: unknown) {
|
||||
function isAttackIntentArray(value: unknown, options: BattleSaveValidationOptions) {
|
||||
return (
|
||||
Array.isArray(value) &&
|
||||
value.every((intent) => isRecord(intent) && typeof intent.attackerId === 'string' && typeof intent.targetId === 'string')
|
||||
value.every(
|
||||
(intent) =>
|
||||
isRecord(intent) &&
|
||||
typeof intent.attackerId === 'string' &&
|
||||
typeof intent.targetId === 'string' &&
|
||||
isKnownUnitId(intent.attackerId, options) &&
|
||||
isKnownUnitId(intent.targetId, options)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -238,7 +249,7 @@ function isSavedBattleUnitState(value: unknown, options: BattleSaveValidationOpt
|
||||
return value.direction === undefined || unitDirections.has(value.direction as UnitDirection);
|
||||
}
|
||||
|
||||
function isBondArray(value: unknown) {
|
||||
function isBondArray(value: unknown, options: BattleSaveValidationOptions) {
|
||||
return (
|
||||
Array.isArray(value) &&
|
||||
value.every(
|
||||
@@ -247,7 +258,7 @@ function isBondArray(value: unknown) {
|
||||
typeof bond.id === 'string' &&
|
||||
Array.isArray(bond.unitIds) &&
|
||||
bond.unitIds.length === 2 &&
|
||||
bond.unitIds.every((unitId) => typeof unitId === 'string') &&
|
||||
bond.unitIds.every((unitId) => typeof unitId === 'string' && isKnownUnitId(unitId, options)) &&
|
||||
isPositiveInteger(bond.level) &&
|
||||
isNonNegativeFiniteNumber(bond.exp) &&
|
||||
isNonNegativeFiniteNumber(bond.battleExp)
|
||||
@@ -255,7 +266,7 @@ function isBondArray(value: unknown) {
|
||||
);
|
||||
}
|
||||
|
||||
function isOptionalNestedCountRecord(value: unknown) {
|
||||
function isOptionalNestedCountRecord(value: unknown, options: BattleSaveValidationOptions) {
|
||||
if (value === undefined) {
|
||||
return true;
|
||||
}
|
||||
@@ -264,12 +275,15 @@ function isOptionalNestedCountRecord(value: unknown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Object.values(value).every(
|
||||
(stocks) => isRecord(stocks) && Object.values(stocks).every((count) => Number.isInteger(count) && Number(count) >= 0)
|
||||
return Object.entries(value).every(
|
||||
([unitId, stocks]) =>
|
||||
isKnownUnitId(unitId, options) &&
|
||||
isRecord(stocks) &&
|
||||
Object.values(stocks).every((count) => Number.isInteger(count) && Number(count) >= 0)
|
||||
);
|
||||
}
|
||||
|
||||
function isOptionalBuffArray(value: unknown) {
|
||||
function isOptionalBuffArray(value: unknown, options: BattleSaveValidationOptions) {
|
||||
return (
|
||||
value === undefined ||
|
||||
(Array.isArray(value) &&
|
||||
@@ -277,6 +291,7 @@ function isOptionalBuffArray(value: unknown) {
|
||||
(buff) =>
|
||||
isRecord(buff) &&
|
||||
typeof buff.unitId === 'string' &&
|
||||
isKnownUnitId(buff.unitId, options) &&
|
||||
typeof buff.label === 'string' &&
|
||||
isPositiveInteger(buff.turns) &&
|
||||
isFiniteNumber(buff.attackBonus) &&
|
||||
@@ -286,7 +301,7 @@ function isOptionalBuffArray(value: unknown) {
|
||||
);
|
||||
}
|
||||
|
||||
function isOptionalStatusArray(value: unknown) {
|
||||
function isOptionalStatusArray(value: unknown, options: BattleSaveValidationOptions) {
|
||||
return (
|
||||
value === undefined ||
|
||||
(Array.isArray(value) &&
|
||||
@@ -294,6 +309,7 @@ function isOptionalStatusArray(value: unknown) {
|
||||
(status) =>
|
||||
isRecord(status) &&
|
||||
typeof status.unitId === 'string' &&
|
||||
isKnownUnitId(status.unitId, options) &&
|
||||
isBattleStatusKind(status.kind) &&
|
||||
typeof status.label === 'string' &&
|
||||
isPositiveInteger(status.turns) &&
|
||||
@@ -302,7 +318,7 @@ function isOptionalStatusArray(value: unknown) {
|
||||
);
|
||||
}
|
||||
|
||||
function isOptionalStatsRecord(value: unknown) {
|
||||
function isOptionalStatsRecord(value: unknown, options: BattleSaveValidationOptions) {
|
||||
if (value === undefined) {
|
||||
return true;
|
||||
}
|
||||
@@ -311,8 +327,9 @@ function isOptionalStatsRecord(value: unknown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Object.values(value).every(
|
||||
(stats) =>
|
||||
return Object.entries(value).every(
|
||||
([unitId, stats]) =>
|
||||
isKnownUnitId(unitId, options) &&
|
||||
isRecord(stats) &&
|
||||
isNonNegativeFiniteNumber(stats.damageDealt) &&
|
||||
isNonNegativeFiniteNumber(stats.damageTaken) &&
|
||||
@@ -321,3 +338,7 @@ function isOptionalStatsRecord(value: unknown) {
|
||||
isNonNegativeFiniteNumber(stats.support)
|
||||
);
|
||||
}
|
||||
|
||||
function isKnownUnitId(unitId: string, options: BattleSaveValidationOptions) {
|
||||
return !options.validUnitIds || options.validUnitIds.has(unitId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user