namespace DorkNet.Server.Compat;
/// Resolves a client-build key (e.g. december_2020_12_18)
/// to its . Built once at startup from all
/// registered instances.
///
/// Singleton — the version-key → generation mapping is fixed at
/// boot time, and the registry is read on every request by the
/// version-detection middleware.
///
public sealed class VersionRegistry
{
private readonly Dictionary _byKey;
/// The set of version keys this deployment is willing to
/// serve. Comes from DorkNet:SupportedVersions in config.
/// Anything else gets a 426 from the middleware.
public IReadOnlySet SupportedVersionKeys { get; }
/// Falls back to this when a request arrives without an
/// X-DorkNet-Version header — set via
/// DorkNet:DefaultClientVersion in config. Empty/null means
/// "no fallback; reject headerless requests". Set during the
/// transition window where the old client mod doesn't yet stamp
/// the header.
public string? DefaultVersionKey { get; }
public VersionRegistry(
IEnumerable plugins,
IReadOnlySet supportedVersionKeys,
string? defaultVersionKey)
{
_byKey = new Dictionary(StringComparer.OrdinalIgnoreCase);
foreach (var plugin in plugins)
{
foreach (var key in plugin.VersionKeys)
{
if (_byKey.ContainsKey(key))
throw new InvalidOperationException(
$"VersionPlugin collision: '{key}' is claimed by more than one IVersionPlugin. " +
$"Each version key maps to exactly one plugin.");
_byKey[key] = new ClientVersion(key, plugin.Generation);
}
}
SupportedVersionKeys = supportedVersionKeys;
DefaultVersionKey = defaultVersionKey;
}
/// Resolve a version key (case-insensitive) to its
/// , or
/// if no plugin claims it. The middleware decides whether unknown
/// → reject or → fall back to .
public ClientVersion Resolve(string? key)
{
if (string.IsNullOrWhiteSpace(key)) return ClientVersion.Unknown;
return _byKey.TryGetValue(key, out var v) ? v : ClientVersion.Unknown;
}
/// True when the given version key is in
/// . Used by the middleware to
/// 426 cross-version connection attempts (e.g. a March client
/// hitting a server configured for December only).
public bool IsSupported(string key)
=> SupportedVersionKeys.Contains(key);
/// Every known plugin-registered version key, for
/// diagnostic responses and admin tooling.
public IEnumerable AllKnown => _byKey.Values;
}