Skip to content
This repository has been archived by the owner on Oct 16, 2024. It is now read-only.

Commit

Permalink
Pull the comedic engine ver thing
Browse files Browse the repository at this point in the history
Signed-off-by: Mary <[email protected]>
  • Loading branch information
misandrie committed Mar 11, 2024
1 parent ad09ab5 commit 5f4d11a
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 108 deletions.
2 changes: 1 addition & 1 deletion Launcher.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
3. Local dev SS14.Loader launching code.
-->
<TargetFramework>net8.0</TargetFramework>
<Version>0.25.1</Version>
<Version>0.26.0</Version>
</PropertyGroup>
</Project>
4 changes: 4 additions & 0 deletions SS14.Launcher/ConfigConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public static class ConfigConstants
public const string RobustBuildsManifest = "https://central.spacestation14.io/builds/robust/manifest.json";
public const string RobustModulesManifest = "https://central.spacestation14.io/builds/robust/modules.json";

// How long to keep cached copies of Robust manifests.
// TODO: Take this from Cache-Control header responses instead.
public static readonly TimeSpan RobustManifestCacheTime = TimeSpan.FromMinutes(15);

public const string UrlOverrideAssets = "https://central.spacestation14.io/launcher/override_assets.json";
public const string UrlAssetsBase = "https://central.spacestation14.io/launcher/assets/";

Expand Down
16 changes: 16 additions & 0 deletions SS14.Launcher/Models/Data/CVars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ public static readonly CVarDef<bool> HasDismissedEarlyAccessWarning
/// <seealso cref="ServerFilter.PlayerCountMax"/>
public static readonly CVarDef<int> FilterPlayerCountMaxValue = CVarDef.Create("FilterPlayerCountMaxValue", 0);

/// <summary>
/// Enable local overriding of engine versions.
/// </summary>
/// <remarks>
/// If enabled and on a development build,
/// the launcher will pull all engine versions and modules from <see cref="EngineOverridePath"/>.
/// This can be set to <c>RobustToolbox/release/</c> to instantly pull in packaged engine builds.
/// </remarks>
public static readonly CVarDef<bool> EngineOverrideEnabled = CVarDef.Create("EngineOverrideEnabled", false);

/// <summary>
/// Path to load engines from when using <see cref="EngineOverrideEnabled"/>.
/// </summary>
public static readonly CVarDef<string> EngineOverridePath = CVarDef.Create("EngineOverridePath", "");


// MarseyCVars start here

// Stealthsey
Expand Down
117 changes: 117 additions & 0 deletions SS14.Launcher/Models/EngineManager/EngineManagerDynamic.Manifest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Serilog;

namespace SS14.Launcher.Models.EngineManager;

public sealed partial class EngineManagerDynamic
{
// This part of the code is responsible for downloading and caching the Robust build manifest.

private readonly SemaphoreSlim _manifestSemaphore = new(1);
private readonly Stopwatch _manifestStopwatch = Stopwatch.StartNew();

private Dictionary<string, VersionInfo>? _cachedRobustVersionInfo;
private TimeSpan _robustCacheValidUntil;

/// <summary>
/// Look up information about an engine version.
/// </summary>
/// <param name="version">The version number to look up.</param>
/// <param name="followRedirects">Follow redirections in version info.</param>
/// <param name="cancel">Cancellation token.</param>
/// <returns>
/// Information about the version, or null if it could not be found.
/// The returned version may be different than what was requested if redirects were followed.
/// </returns>
private async ValueTask<FoundVersionInfo?> GetVersionInfo(
string version,
bool followRedirects = true,
CancellationToken cancel = default)
{
await _manifestSemaphore.WaitAsync(cancel);
try
{
return await GetVersionInfoCore(version, followRedirects, cancel);
}
finally
{
_manifestSemaphore.Release();
}
}

private async ValueTask<FoundVersionInfo?> GetVersionInfoCore(
string version,
bool followRedirects,
CancellationToken cancel)
{
// If we have a cached copy, and it's not expired, we check it.
if (_cachedRobustVersionInfo != null && _robustCacheValidUntil > _manifestStopwatch.Elapsed)
{
// Check the version. If this fails, we immediately re-request the manifest as it may have changed.
// (Connecting to a freshly-updated server with a new Robust version, within the cache window.)
if (FindVersionInfoInCached(version, followRedirects) is { } foundVersionInfo)
return foundVersionInfo;
}

await UpdateBuildManifest(cancel);

return FindVersionInfoInCached(version, followRedirects);
}

private async Task UpdateBuildManifest(CancellationToken cancel)
{
// TODO: If-Modified-Since and If-None-Match request conditions.

Log.Debug("Loading manifest from {manifestUrl}...", ConfigConstants.RobustBuildsManifest);
_cachedRobustVersionInfo =
await _http.GetFromJsonAsync<Dictionary<string, VersionInfo>>(
ConfigConstants.RobustBuildsManifest, cancellationToken: cancel);

_robustCacheValidUntil = _manifestStopwatch.Elapsed + ConfigConstants.RobustManifestCacheTime;
}

private FoundVersionInfo? FindVersionInfoInCached(string version, bool followRedirects)
{
Debug.Assert(_cachedRobustVersionInfo != null);

if (!_cachedRobustVersionInfo.TryGetValue(version, out var versionInfo))
return null;

if (followRedirects)
{
while (versionInfo.RedirectVersion != null)
{
version = versionInfo.RedirectVersion;
versionInfo = _cachedRobustVersionInfo[versionInfo.RedirectVersion];
}
}

return new FoundVersionInfo(version, versionInfo);
}

private sealed record FoundVersionInfo(string Version, VersionInfo Info);

private sealed record VersionInfo(
bool Insecure,
[property: JsonPropertyName("redirect")]
string? RedirectVersion,
Dictionary<string, BuildInfo> Platforms);

private sealed class BuildInfo
{
[JsonInclude] [JsonPropertyName("url")]
public string Url = default!;

[JsonInclude] [JsonPropertyName("sha256")]
public string Sha256 = default!;

[JsonInclude] [JsonPropertyName("sig")]
public string Signature = default!;
}
}
Loading

0 comments on commit 5f4d11a

Please sign in to comment.