Faction Test 100.6.0.0
This commit is contained in:
+14
-24
@@ -67,10 +67,10 @@ namespace Barotrauma
|
||||
.ToImmutableHashSet();
|
||||
}
|
||||
|
||||
public static Result<ContentFile, LoadError> CreateFromXElement(ContentPackage contentPackage, XElement element)
|
||||
public static Result<ContentFile, ContentPackage.LoadError> CreateFromXElement(ContentPackage contentPackage, XElement element)
|
||||
{
|
||||
static Result<ContentFile, LoadError> fail(string error, Exception? exception = null)
|
||||
=> Result<ContentFile, LoadError>.Failure(new LoadError(error, exception));
|
||||
static Result<ContentFile, ContentPackage.LoadError> fail(string error, Exception? exception = null)
|
||||
=> Result<ContentFile, ContentPackage.LoadError>.Failure(new ContentPackage.LoadError(error, exception));
|
||||
|
||||
Identifier elemName = element.NameAsIdentifier();
|
||||
var type = Types.FirstOrDefault(t => t.Names.Contains(elemName));
|
||||
@@ -83,6 +83,8 @@ namespace Barotrauma
|
||||
{
|
||||
return fail($"No content path defined for file of type \"{elemName}\"");
|
||||
}
|
||||
|
||||
using var errorCatcher = DebugConsole.ErrorCatcher.Create();
|
||||
try
|
||||
{
|
||||
filePath = type.MutateContentPath(filePath);
|
||||
@@ -90,10 +92,16 @@ namespace Barotrauma
|
||||
{
|
||||
return fail($"Failed to load file \"{filePath}\" of type \"{elemName}\": file not found.");
|
||||
}
|
||||
|
||||
var file = type.CreateInstance(contentPackage, filePath);
|
||||
return file is null
|
||||
? throw new Exception($"Content type is not implemented correctly")
|
||||
: Result<ContentFile, LoadError>.Success(file);
|
||||
if (file is null) { return fail($"Content type {type.Type.Name} is not implemented correctly"); }
|
||||
|
||||
if (errorCatcher.Errors.Any())
|
||||
{
|
||||
return fail(
|
||||
$"Errors were issued to the debug console when loading \"{filePath}\" of type \"{elemName}\"");
|
||||
}
|
||||
return Result<ContentFile, ContentPackage.LoadError>.Success(file);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -123,23 +131,5 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public bool NotSyncedInMultiplayer => Types.Any(t => t.Type == GetType() && t.NotSyncedInMultiplayer);
|
||||
|
||||
public readonly struct LoadError
|
||||
{
|
||||
public readonly string Message;
|
||||
public readonly Exception? Exception;
|
||||
|
||||
public LoadError(string message, Exception? exception)
|
||||
{
|
||||
Message = message;
|
||||
Exception = exception;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> Message
|
||||
+ (Exception is { StackTrace: var stackTrace }
|
||||
? '\n' + stackTrace.CleanupStackTrace()
|
||||
: string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
+99
-51
@@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -14,6 +13,15 @@ namespace Barotrauma
|
||||
{
|
||||
public abstract class ContentPackage
|
||||
{
|
||||
public readonly record struct LoadError(string Message, Exception? Exception)
|
||||
{
|
||||
public override string ToString()
|
||||
=> Message
|
||||
+ (Exception is { StackTrace: var stackTrace }
|
||||
? '\n' + stackTrace.CleanupStackTrace()
|
||||
: string.Empty);
|
||||
}
|
||||
|
||||
public static readonly Version MinimumHashCompatibleVersion = new Version(0, 18, 13, 0);
|
||||
|
||||
public const string LocalModsDir = "LocalMods";
|
||||
@@ -37,12 +45,30 @@ namespace Barotrauma
|
||||
public readonly Option<DateTime> InstallTime;
|
||||
|
||||
public ImmutableArray<ContentFile> Files { get; private set; }
|
||||
public ImmutableArray<ContentFile.LoadError> Errors { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Errors that occurred when loading this content package.
|
||||
/// Currently, all errors are considered fatal and the game
|
||||
/// will refuse to load a content package that has any errors.
|
||||
/// </summary>
|
||||
public ImmutableArray<LoadError> FatalLoadErrors { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// An error that occurred when trying to enable this mod.
|
||||
/// This field doesn't directly affect whether or not this mod
|
||||
/// can be enabled, but if it's been set to anything other than
|
||||
/// Option.None then the game has already refused to enable it
|
||||
/// at least once.
|
||||
/// </summary>
|
||||
public Option<ContentPackageManager.LoadProgress.Error> EnableError { get; private set; }
|
||||
= Option.None;
|
||||
|
||||
public bool HasAnyErrors => FatalLoadErrors.Length > 0 || EnableError.IsSome();
|
||||
|
||||
public async Task<bool> IsUpToDate()
|
||||
{
|
||||
if (!UgcId.TryUnwrap(out var ugcId)) { return true; }
|
||||
if (!(ugcId is SteamWorkshopId steamWorkshopId)) { return true; }
|
||||
if (ugcId is not SteamWorkshopId steamWorkshopId) { return true; }
|
||||
if (!InstallTime.TryUnwrap(out var installTime)) { return true; }
|
||||
|
||||
Steamworks.Ugc.Item? item = await SteamManager.Workshop.GetItem(steamWorkshopId.Value);
|
||||
@@ -55,20 +81,25 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Does the content package include some content that needs to match between all players in multiplayer.
|
||||
/// </summary>
|
||||
public bool HasMultiplayerSyncedContent { get; private set; }
|
||||
public bool HasMultiplayerSyncedContent { get; }
|
||||
|
||||
protected ContentPackage(XDocument doc, string path)
|
||||
{
|
||||
using var errorCatcher = DebugConsole.ErrorCatcher.Create();
|
||||
|
||||
Path = path.CleanUpPathCrossPlatform();
|
||||
XElement rootElement = doc.Root ?? throw new NullReferenceException("XML document is invalid: root element is null.");
|
||||
|
||||
Name = rootElement.GetAttributeString("name", "").Trim();
|
||||
AltNames = rootElement.GetAttributeStringArray("altnames", Array.Empty<string>())
|
||||
.Select(n => n.Trim()).ToImmutableArray();
|
||||
AssertCondition(!string.IsNullOrEmpty(Name), "Name is null or empty");
|
||||
|
||||
UInt64 steamWorkshopId = rootElement.GetAttributeUInt64("steamworkshopid", 0);
|
||||
|
||||
|
||||
if (Name.IsNullOrWhiteSpace() && AltNames.Any())
|
||||
{
|
||||
Name = AltNames.First();
|
||||
}
|
||||
|
||||
UgcId = steamWorkshopId != 0
|
||||
? Option<ContentPackageId>.Some(new SteamWorkshopId(steamWorkshopId))
|
||||
: Option<ContentPackageId>.None();
|
||||
@@ -85,23 +116,31 @@ namespace Barotrauma
|
||||
.ToArray();
|
||||
|
||||
Files = fileResults
|
||||
.OfType<Success<ContentFile, ContentFile.LoadError>>()
|
||||
.Select(f => f.Value)
|
||||
.Successes()
|
||||
.ToImmutableArray();
|
||||
|
||||
Errors = fileResults
|
||||
.OfType<Failure<ContentFile, ContentFile.LoadError>>()
|
||||
.Select(f => f.Error)
|
||||
FatalLoadErrors = fileResults
|
||||
.Failures()
|
||||
.ToImmutableArray();
|
||||
|
||||
AssertCondition(!string.IsNullOrEmpty(Name), $"{nameof(Name)} is null or empty");
|
||||
|
||||
HasMultiplayerSyncedContent = Files.Any(f => !f.NotSyncedInMultiplayer);
|
||||
|
||||
Hash = CalculateHash();
|
||||
var expectedHash = rootElement.GetAttributeString("expectedhash", "");
|
||||
if (HashMismatches(expectedHash))
|
||||
{
|
||||
DebugConsole.ThrowError($"Hash calculation for content package \"{Name}\" didn't match expected hash ({Hash.StringRepresentation} != {expectedHash})");
|
||||
FatalLoadErrors = FatalLoadErrors.Add(
|
||||
new LoadError(
|
||||
Message: $"Hash calculation returned {Hash.StringRepresentation}, expected {expectedHash}",
|
||||
Exception: null
|
||||
));
|
||||
}
|
||||
|
||||
FatalLoadErrors = FatalLoadErrors
|
||||
.Concat(errorCatcher.Errors.Select(err => new LoadError(err.Text, null)))
|
||||
.ToImmutableArray();
|
||||
}
|
||||
|
||||
public bool HashMismatches(string expectedHash)
|
||||
@@ -122,21 +161,21 @@ namespace Barotrauma
|
||||
public bool NameMatches(string name)
|
||||
=> NameMatches(name.ToIdentifier());
|
||||
|
||||
public static ContentPackage? TryLoad(string path)
|
||||
public static Result<ContentPackage, Exception> TryLoad(string path)
|
||||
{
|
||||
var (success, failure) = Result<ContentPackage, Exception>.GetFactoryMethods();
|
||||
|
||||
XDocument doc = XMLExtensions.TryLoadXml(path);
|
||||
|
||||
try
|
||||
{
|
||||
return doc.Root.GetAttributeBool("corepackage", false)
|
||||
? (ContentPackage)new CorePackage(doc, path)
|
||||
: new RegularPackage(doc, path);
|
||||
return success(doc.Root.GetAttributeBool("corepackage", false)
|
||||
? new CorePackage(doc, path)
|
||||
: new RegularPackage(doc, path));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e = e.GetInnermost();
|
||||
DebugConsole.ThrowError($"{e.Message}: {e.StackTrace}");
|
||||
return null;
|
||||
return failure(e.GetInnermost());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +220,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to load \"{Name}\" at {Path}: {errorMsg}");
|
||||
FatalLoadErrors = FatalLoadErrors.Add(new LoadError(errorMsg, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,17 +240,19 @@ namespace Barotrauma
|
||||
Failure
|
||||
}
|
||||
|
||||
public LoadResult LoadPackage()
|
||||
public LoadResult LoadContent()
|
||||
{
|
||||
foreach (var p in LoadPackageEnumerable())
|
||||
foreach (var p in LoadContentEnumerable())
|
||||
{
|
||||
if (p.Exception != null) { return LoadResult.Failure; }
|
||||
if (p.Result.IsFailure) { return LoadResult.Failure; }
|
||||
}
|
||||
return LoadResult.Success;
|
||||
}
|
||||
|
||||
public IEnumerable<ContentPackageManager.LoadProgress> LoadPackageEnumerable()
|
||||
public IEnumerable<ContentPackageManager.LoadProgress> LoadContentEnumerable()
|
||||
{
|
||||
using var errorCatcher = DebugConsole.ErrorCatcher.Create();
|
||||
|
||||
ContentFile[] getFilesToLoad(Predicate<ContentFile> predicate)
|
||||
=> Files.Where(predicate.Invoke).ToArray()
|
||||
#if DEBUG
|
||||
@@ -227,6 +268,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < filesToLoad.Length; i++)
|
||||
{
|
||||
Exception? exception = null;
|
||||
|
||||
try
|
||||
{
|
||||
//do not allow exceptions thrown here to crash the game
|
||||
@@ -234,42 +276,53 @@ namespace Barotrauma
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var innermost = e.GetInnermost();
|
||||
DebugConsole.LogError($"Failed to load \"{filesToLoad[i].Path}\": {innermost.Message}\n{innermost.StackTrace}");
|
||||
exception = e;
|
||||
}
|
||||
if (exception != null)
|
||||
{
|
||||
yield return ContentPackageManager.LoadProgress.Failure(exception);
|
||||
break;
|
||||
yield break;
|
||||
}
|
||||
yield return new ContentPackageManager.LoadProgress((i + indexOffset) / (float)Files.Length);
|
||||
|
||||
if (errorCatcher.Errors.Any())
|
||||
{
|
||||
yield return ContentPackageManager.LoadProgress.Failure(
|
||||
ContentPackageManager.LoadProgress.Error
|
||||
.Reason.ConsoleErrorsThrown);
|
||||
yield break;
|
||||
}
|
||||
yield return ContentPackageManager.LoadProgress.Progress((i + indexOffset) / (float)Files.Length);
|
||||
}
|
||||
}
|
||||
|
||||
//Load the UI and text files first. This is to allow the game
|
||||
//to render the text in the loading screen as soon as possible.
|
||||
var priorityFiles = getFilesToLoad(f => f is UIStyleFile || f is TextFile);
|
||||
var priorityFiles = getFilesToLoad(f => f is UIStyleFile or TextFile);
|
||||
|
||||
var remainder = getFilesToLoad(f => !priorityFiles.Contains(f));
|
||||
|
||||
var loadEnumerable =
|
||||
loadFiles(priorityFiles, 0)
|
||||
.Concat(loadFiles(remainder, priorityFiles.Length));
|
||||
|
||||
|
||||
foreach (var p in loadEnumerable)
|
||||
{
|
||||
if (p.Exception != null)
|
||||
if (p.Result.TryUnwrapFailure(out var failure))
|
||||
{
|
||||
HandleLoadException(p.Exception);
|
||||
errorCatcher.Dispose();
|
||||
UnloadContent();
|
||||
EnableError = Option.Some(failure);
|
||||
yield return p;
|
||||
break;
|
||||
yield break;
|
||||
}
|
||||
yield return p;
|
||||
}
|
||||
errorCatcher.Dispose();
|
||||
}
|
||||
|
||||
protected abstract void HandleLoadException(Exception e);
|
||||
|
||||
public void UnloadPackage()
|
||||
public void UnloadContent()
|
||||
{
|
||||
Files.ForEach(f => f.UnloadFile());
|
||||
}
|
||||
@@ -284,21 +337,16 @@ namespace Barotrauma
|
||||
.Select(e => ContentFile.CreateFromXElement(this, e))
|
||||
.ToArray();
|
||||
|
||||
foreach (var result in fileResults)
|
||||
foreach (var file in fileResults.Successes())
|
||||
{
|
||||
switch (result)
|
||||
if (file is BaseSubFile or ItemAssemblyFile)
|
||||
{
|
||||
case Success<ContentFile, ContentFile.LoadError> { Value: var file }:
|
||||
if (file is BaseSubFile || file is ItemAssemblyFile)
|
||||
{
|
||||
newFileList.Add(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
var existingFile = Files.FirstOrDefault(f => f.Path == file.Path);
|
||||
newFileList.Add(existingFile ?? file);
|
||||
}
|
||||
break;
|
||||
newFileList.Add(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
var existingFile = Files.FirstOrDefault(f => f.Path == file.Path);
|
||||
newFileList.Add(existingFile ?? file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,16 +379,16 @@ namespace Barotrauma
|
||||
|
||||
public void LogErrors()
|
||||
{
|
||||
if (!Errors.Any())
|
||||
if (!FatalLoadErrors.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DebugConsole.AddWarning(
|
||||
$"The following errors occurred while loading the content package \"{Name}\". The package might not work correctly.\n" +
|
||||
string.Join('\n', Errors.Select(errorToStr)));
|
||||
string.Join('\n', FatalLoadErrors.Select(errorToStr)));
|
||||
|
||||
static string errorToStr(ContentFile.LoadError error)
|
||||
static string errorToStr(LoadError error)
|
||||
=> error.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -43,10 +43,5 @@ namespace Barotrauma
|
||||
"Core package requires at least one of the following content types: " +
|
||||
string.Join(", ", missingFileTypes.Select(t => t.Type.Name)));
|
||||
}
|
||||
|
||||
protected override void HandleLoadException(Exception e)
|
||||
{
|
||||
throw new Exception($"An exception was thrown while loading \"{Name}\"", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
-7
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -9,11 +8,5 @@ namespace Barotrauma
|
||||
{
|
||||
AssertCondition(!doc.Root.GetAttributeBool("corepackage", false), "Expected a regular package, got a core package");
|
||||
}
|
||||
|
||||
protected override void HandleLoadException(Exception e)
|
||||
{
|
||||
UnloadPackage();
|
||||
DebugConsole.ThrowError($"Failed to load package \"{Name}\"", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+106
-66
@@ -47,18 +47,19 @@ namespace Barotrauma
|
||||
{
|
||||
var oldCore = Core;
|
||||
if (newCore == oldCore) { yield break; }
|
||||
Core?.UnloadPackage();
|
||||
if (newCore.FatalLoadErrors.Any()) { yield break; }
|
||||
Core?.UnloadContent();
|
||||
Core = newCore;
|
||||
foreach (var p in newCore.LoadPackageEnumerable()) { yield return p; }
|
||||
foreach (var p in newCore.LoadContentEnumerable()) { yield return p; }
|
||||
SortContent();
|
||||
yield return new LoadProgress(1.0f);
|
||||
yield return LoadProgress.Progress(1.0f);
|
||||
}
|
||||
|
||||
public static void ReloadCore()
|
||||
{
|
||||
if (Core == null) { return; }
|
||||
Core.UnloadPackage();
|
||||
Core.LoadPackage();
|
||||
Core.UnloadContent();
|
||||
Core.LoadContent();
|
||||
SortContent();
|
||||
}
|
||||
|
||||
@@ -79,10 +80,14 @@ namespace Barotrauma
|
||||
if (ReferenceEquals(inNewRegular, regular)) { yield break; }
|
||||
if (inNewRegular.SequenceEqual(regular)) { yield break; }
|
||||
ThrowIfDuplicates(inNewRegular);
|
||||
var newRegular = inNewRegular.ToList();
|
||||
var newRegular = inNewRegular
|
||||
// Refuse to enable packages with load errors
|
||||
// so people are forced away from broken mods
|
||||
.Where(r => !r.FatalLoadErrors.Any())
|
||||
.ToList();
|
||||
IEnumerable<RegularPackage> toUnload = regular.Where(r => !newRegular.Contains(r));
|
||||
RegularPackage[] toLoad = newRegular.Where(r => !regular.Contains(r)).ToArray();
|
||||
toUnload.ForEach(r => r.UnloadPackage());
|
||||
toUnload.ForEach(r => r.UnloadContent());
|
||||
|
||||
Range<float> loadingRange = new Range<float>(0.0f, 1.0f);
|
||||
|
||||
@@ -90,9 +95,9 @@ namespace Barotrauma
|
||||
{
|
||||
var package = toLoad[i];
|
||||
loadingRange = new Range<float>(i / (float)toLoad.Length, (i + 1) / (float)toLoad.Length);
|
||||
foreach (var progress in package.LoadPackageEnumerable())
|
||||
foreach (var progress in package.LoadContentEnumerable())
|
||||
{
|
||||
if (progress.Exception != null)
|
||||
if (progress.Result.IsFailure)
|
||||
{
|
||||
//If an exception was thrown while loading this package, refuse to add it to the list of enabled packages
|
||||
newRegular.Remove(package);
|
||||
@@ -103,7 +108,7 @@ namespace Barotrauma
|
||||
}
|
||||
regular.Clear(); regular.AddRange(newRegular);
|
||||
SortContent();
|
||||
yield return new LoadProgress(1.0f);
|
||||
yield return LoadProgress.Progress(1.0f);
|
||||
}
|
||||
|
||||
public static void ThrowIfDuplicates(IEnumerable<ContentPackage> pkgs)
|
||||
@@ -231,10 +236,12 @@ namespace Barotrauma
|
||||
public sealed partial class PackageSource : ICollection<ContentPackage>
|
||||
{
|
||||
private readonly Predicate<string>? skipPredicate;
|
||||
private readonly Action<string, Exception>? onLoadFail;
|
||||
|
||||
public PackageSource(string dir, Predicate<string>? skipPredicate)
|
||||
public PackageSource(string dir, Predicate<string>? skipPredicate, Action<string, Exception>? onLoadFail)
|
||||
{
|
||||
this.skipPredicate = skipPredicate;
|
||||
this.onLoadFail = onLoadFail;
|
||||
directory = dir;
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
@@ -278,25 +285,30 @@ namespace Barotrauma
|
||||
{
|
||||
var fileListPath = Path.Combine(subDir, ContentPackage.FileListFileName).CleanUpPathCrossPlatform();
|
||||
if (this.Any(p => p.Path.Equals(fileListPath, StringComparison.OrdinalIgnoreCase))) { continue; }
|
||||
if (File.Exists(fileListPath))
|
||||
{
|
||||
if (skipPredicate?.Invoke(fileListPath) is true) { continue; }
|
||||
|
||||
ContentPackage? newPackage = ContentPackage.TryLoad(fileListPath);
|
||||
if (newPackage is CorePackage corePackage)
|
||||
{
|
||||
corePackages.Add(corePackage);
|
||||
}
|
||||
else if (newPackage is RegularPackage regularPackage)
|
||||
{
|
||||
regularPackages.Add(regularPackage);
|
||||
}
|
||||
|
||||
if (!(newPackage is null))
|
||||
{
|
||||
Debug.WriteLine($"Loaded \"{newPackage.Name}\"");
|
||||
}
|
||||
if (!File.Exists(fileListPath)) { continue; }
|
||||
if (skipPredicate?.Invoke(fileListPath) is true) { continue; }
|
||||
|
||||
var result = ContentPackage.TryLoad(fileListPath);
|
||||
if (!result.TryUnwrapSuccess(out var newPackage))
|
||||
{
|
||||
onLoadFail?.Invoke(
|
||||
fileListPath,
|
||||
result.TryUnwrapFailure(out var exception) ? exception : throw new Exception("unreachable"));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (newPackage)
|
||||
{
|
||||
case CorePackage corePackage:
|
||||
corePackages.Add(corePackage);
|
||||
break;
|
||||
case RegularPackage regularPackage:
|
||||
regularPackages.Add(regularPackage);
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.WriteLine($"Loaded \"{newPackage.Name}\"");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,8 +360,20 @@ namespace Barotrauma
|
||||
public bool IsReadOnly => true;
|
||||
}
|
||||
|
||||
public static readonly PackageSource LocalPackages = new PackageSource(ContentPackage.LocalModsDir, skipPredicate: null);
|
||||
public static readonly PackageSource WorkshopPackages = new PackageSource(ContentPackage.WorkshopModsDir, skipPredicate: SteamManager.Workshop.IsInstallingToPath);
|
||||
public static readonly PackageSource LocalPackages
|
||||
= new PackageSource(
|
||||
ContentPackage.LocalModsDir,
|
||||
skipPredicate: null,
|
||||
onLoadFail: null);
|
||||
public static readonly PackageSource WorkshopPackages = new PackageSource(
|
||||
ContentPackage.WorkshopModsDir,
|
||||
skipPredicate: SteamManager.Workshop.IsInstallingToPath,
|
||||
onLoadFail: (fileListPath, exception) =>
|
||||
{
|
||||
// Delete Workshop mods that fail to load to
|
||||
// force a reinstall on next launch if necessary
|
||||
Directory.TryDelete(Path.GetDirectoryName(fileListPath)!);
|
||||
});
|
||||
|
||||
public static CorePackage? VanillaCorePackage { get; private set; } = null;
|
||||
|
||||
@@ -373,63 +397,77 @@ namespace Barotrauma
|
||||
EnabledPackages.DisableRemovedMods();
|
||||
}
|
||||
|
||||
public static ContentPackage? ReloadContentPackage(ContentPackage p)
|
||||
public static Result<ContentPackage, Exception> ReloadContentPackage(ContentPackage p)
|
||||
{
|
||||
ContentPackage? newPackage = ContentPackage.TryLoad(p.Path);
|
||||
if (newPackage is CorePackage core)
|
||||
{
|
||||
if (EnabledPackages.Core == p) { EnabledPackages.SetCore(core); }
|
||||
}
|
||||
else if (newPackage is RegularPackage regular)
|
||||
{
|
||||
int index = EnabledPackages.Regular.IndexOf(p);
|
||||
if (index >= 0)
|
||||
{
|
||||
var newRegular = EnabledPackages.Regular.ToArray();
|
||||
newRegular[index] = regular;
|
||||
EnabledPackages.SetRegular(newRegular);
|
||||
}
|
||||
}
|
||||
var result = ContentPackage.TryLoad(p.Path);
|
||||
|
||||
if (newPackage != null)
|
||||
if (result.TryUnwrapSuccess(out var newPackage))
|
||||
{
|
||||
switch (newPackage)
|
||||
{
|
||||
case CorePackage core:
|
||||
{
|
||||
if (EnabledPackages.Core == p) { EnabledPackages.SetCore(core); }
|
||||
|
||||
break;
|
||||
}
|
||||
case RegularPackage regular:
|
||||
{
|
||||
int index = EnabledPackages.Regular.IndexOf(p);
|
||||
if (index >= 0)
|
||||
{
|
||||
var newRegular = EnabledPackages.Regular.ToArray();
|
||||
newRegular[index] = regular;
|
||||
EnabledPackages.SetRegular(newRegular);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LocalPackages.SwapPackage(p, newPackage);
|
||||
WorkshopPackages.SwapPackage(p, newPackage);
|
||||
}
|
||||
EnabledPackages.DisableRemovedMods();
|
||||
return newPackage;
|
||||
return result;
|
||||
}
|
||||
|
||||
public readonly struct LoadProgress
|
||||
public readonly record struct LoadProgress(Result<float, LoadProgress.Error> Result)
|
||||
{
|
||||
public readonly float Value;
|
||||
public readonly Exception? Exception;
|
||||
|
||||
public LoadProgress(float value)
|
||||
public readonly record struct Error(
|
||||
Error.Reason ErrorReason,
|
||||
Option<Exception> Exception)
|
||||
{
|
||||
Value = value;
|
||||
Exception = null;
|
||||
}
|
||||
public enum Reason { Exception, ConsoleErrorsThrown }
|
||||
|
||||
private LoadProgress(Exception exception)
|
||||
{
|
||||
Value = -1f;
|
||||
Exception = exception;
|
||||
public Error(Reason reason) : this(reason, Option.None) { }
|
||||
public Error(Exception exception) : this(Reason.Exception, Option.Some(exception)) { }
|
||||
}
|
||||
|
||||
public static LoadProgress Failure(Exception exception)
|
||||
=> new LoadProgress(exception);
|
||||
=> new LoadProgress(
|
||||
Result<float, Error>.Failure(new Error(exception)));
|
||||
|
||||
public static LoadProgress Failure(Error.Reason reason)
|
||||
=> new LoadProgress(
|
||||
Result<float, Error>.Failure(new Error(reason)));
|
||||
|
||||
public static LoadProgress Progress(float value)
|
||||
=> new LoadProgress(
|
||||
Result<float, Error>.Success(value));
|
||||
|
||||
public LoadProgress Transform(Range<float> range)
|
||||
=> Exception != null
|
||||
? this
|
||||
: new LoadProgress(MathHelper.Lerp(range.Start, range.End, Value));
|
||||
=> Result.TryUnwrapSuccess(out var value)
|
||||
? new LoadProgress(
|
||||
Result<float, Error>.Success(
|
||||
MathHelper.Lerp(range.Start, range.End, value)))
|
||||
: this;
|
||||
}
|
||||
|
||||
public static void LoadVanillaFileList()
|
||||
{
|
||||
VanillaCorePackage = new CorePackage(XDocument.Load(VanillaFileList), VanillaFileList);
|
||||
foreach (ContentFile.LoadError error in VanillaCorePackage.Errors)
|
||||
foreach (ContentPackage.LoadError error in VanillaCorePackage.FatalLoadErrors)
|
||||
{
|
||||
DebugConsole.ThrowError(error.ToString());
|
||||
}
|
||||
@@ -444,6 +482,8 @@ namespace Barotrauma
|
||||
|
||||
if (VanillaCorePackage is null) { LoadVanillaFileList(); }
|
||||
|
||||
SteamManager.Workshop.DeleteUnsubscribedMods();
|
||||
|
||||
CorePackage enabledCorePackage = VanillaCorePackage!;
|
||||
List<RegularPackage> enabledRegularPackages = new List<RegularPackage>();
|
||||
|
||||
@@ -512,7 +552,7 @@ namespace Barotrauma
|
||||
yield return p.Transform(loadingRange);
|
||||
}
|
||||
|
||||
yield return new LoadProgress(1.0f);
|
||||
yield return LoadProgress.Progress(1.0f);
|
||||
}
|
||||
|
||||
public static void LogEnabledRegularPackageErrors()
|
||||
|
||||
Reference in New Issue
Block a user