Make Scenery a domain aggregate with no I/O

Parsing and loading move to Infrastructure/Sceneries. Weather becomes a value
object owning the "does this differ from the file" rule.
This commit is contained in:
maj00r
2026-09-04 20:53:50 +02:00
parent a3137a27c4
commit 789f0dd1c9
25 changed files with 1465 additions and 624 deletions

View File

@@ -0,0 +1,15 @@
namespace StarterNG.Application.Abstractions;
/// <summary>
/// Port over randomness. Scenery weather deliberately varies between runs (fog
/// distance, overcast presets, texture randomiser); routing it through a port
/// keeps those rules assertable instead of flaky.
/// </summary>
public interface IRandomSource
{
/// <summary>Inclusive lower bound, exclusive upper bound.</summary>
int Next(int minInclusive, int maxExclusive);
/// <summary>Uniform value in [0, 1).</summary>
double NextDouble();
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using StarterNG.Domain.Sceneries;
namespace StarterNG.Application.Abstractions;
/// <summary>How far a scenery sweep has got, for the splash screen.</summary>
public readonly record struct SceneryLoadProgress(int Loaded, int Total, string FileName);
/// <summary>
/// Reads the scenarios of an installation. The only route from a .scn on disk to
/// a <see cref="Scenery"/>; nothing else constructs one from a path.
/// </summary>
public interface ISceneryRepository
{
/// <summary>
/// Every scenario in the installation, in no particular order. Files that
/// fail to parse are logged and skipped rather than failing the load.
/// </summary>
IReadOnlyList<Scenery> LoadAll(IProgress<SceneryLoadProgress>? progress = null);
/// <summary>Reloads a single scenario; null when it is gone or unreadable.</summary>
Scenery? Load(string path);
}