Skip to content

The Validation System ensures that game installations, content packages, and assembled workspaces are complete and safe to use. It employs a multi-level integrity check strategy, distinguishing between critical failures (missing files) and non-critical warnings (extraneous files).

Architecture ​

The validation system is built on a specific Result Pattern that allows for granular issue tracking rather than simple boolean pass/fail.

Core Components ​

ComponentInterfaceResponsibility
ContentValidatorIContentValidatorValidates a folder against a ContentManifest. Checks file existence, hashes, and extra files.
GameInstallationValidatorIGameInstallationValidatorSpecialized wrapper for base games. Orchestrates manifest retrieval and directory validation.
FileSystemValidatorBase ClassProvides shared logic for file existence and hash verification.
ValidationResultModelAggregates a list of ValidationIssue objects and determines overall success.

The Validation Logic ​

1. Structure Validation ​

Checks if the ContentManifest itself is valid.

  • Critical Errors: Missing Id, Files list is null/empty.
  • Rules: IDs must match the Manifest ID Schema (e.g., 1.87.swr.mod.rotr).

2. Content Integrity ​

Verifies that the files on disk match the manifest.

  • Existence: Every file listed in Files must exist. (Error)
  • Content Addressable Storage (CAS): If source type is ContentAddressable, verifies the hash exists in the CAS index.
  • Hash Verification:
    • Calculates SHA256 hash of on-disk files.
    • Compares against manifest.Files[i].Hash.
    • Behavior: Currently, hash mismatches are treated as Warnings rather than Errors in some contexts to allow for minor user modifications (like config tweaks) without breaking the game.

3. Extraneous File Detection ​

Scans the target directory for files not in the manifest.

  • Purpose: Essential for keeping game folders clean, especially when using symbolic links.
  • Behavior:
    • Creates a HashSet of all expected file paths.
    • Recursively scans the directory.
    • Any file not in the set is flagged.
    • Severity: Warning. Use these warnings to suggest a "Cleanup" action to the user.

The Result Pattern ​

Validation does not throw exceptions for validity failures; it returns a structured result object.

csharp
public class ValidationResult : ResultBase
{
    public bool IsValid => !Issues.Any(i => i.Severity == ValidationSeverity.Error);
    public IReadOnlyList<ValidationIssue> Issues { get; }
}

public class ValidationIssue
{
    public ValidationSeverity Severity { get; } // Info, Warning, Error, Critical
    public string Message { get; }
    public string Path { get; }
}

Success Logic ​

The DetermineSuccess method defines that a result is Success (Valid) if there are zero issues with Severity >= Error.

  • Success: 0 Issues.
  • Success: 5 Warnings (e.g., "Extraneous file: dirty_map.map").
  • Failure: 1 Error (e.g., "Missing file: Data/generals.ctr").

Usage Flow ​

Automatic Validation ​

Validation is triggered automatically in these key workflows:

  1. Import: When adding new content, it is fully validated before being registered in the pool.
  2. Game Detection: When a new game installation is detected, GameInstallationValidator ensures it isn't corrupted.
  3. Pre-Launch: A "Flight Check" runs quickly before launching to ensure no files were deleted since the last play session.

Performance ​

To handle large mods (GBs of data):

  • Parallel Processing: ValidateContentIntegrityAsync uses SemaphoreSlim to hash files in parallel (up to logical processor count).
  • Progress Reporting: All methods accept IProgress<ValidationProgress> to drive UI progress bars.

GeneralsHub Docs