mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge pull request #674 from Noggog/Nullability-Flavor-Bootcamp
Nullability flavor bootcamp
This commit is contained in:
commit
1b7cb772d2
@ -121,4 +121,67 @@ csharp_preserve_single_line_blocks = true
|
||||
# CS4014: Task not awaited
|
||||
dotnet_diagnostic.CS4014.severity = error
|
||||
# CS1998: Async function does not contain await
|
||||
dotnet_diagnostic.CS1998.severity = silent
|
||||
dotnet_diagnostic.CS1998.severity = silent
|
||||
|
||||
###############################
|
||||
# C# Nullability #
|
||||
###############################
|
||||
# CS8602: Dereference of a possibly null reference.
|
||||
dotnet_diagnostic.CS8602.severity = error
|
||||
|
||||
# CS8600: Converting null literal or possible null value to non-nullable type.
|
||||
dotnet_diagnostic.CS8600.severity = error
|
||||
|
||||
# CS8619: Nullability of reference types in value doesn't match target type.
|
||||
dotnet_diagnostic.CS8619.severity = error
|
||||
|
||||
# CS8603: Possible null reference return.
|
||||
dotnet_diagnostic.CS8603.severity = error
|
||||
|
||||
# CS8625: Cannot convert null literal to non-nullable reference type.
|
||||
dotnet_diagnostic.CS8625.severity = error
|
||||
|
||||
# CS8653: A default expression introduces a null value for a type parameter.
|
||||
dotnet_diagnostic.CS8653.severity = silent
|
||||
|
||||
# CS8601: Possible null reference assignment.
|
||||
dotnet_diagnostic.CS8601.severity = error
|
||||
|
||||
# CS8604: Possible null reference argument.
|
||||
dotnet_diagnostic.CS8604.severity = error
|
||||
|
||||
# CS8622: Nullability of reference types in type of parameter doesn't match the target delegate.
|
||||
dotnet_diagnostic.CS8622.severity = error
|
||||
|
||||
# CS8610: Nullability of reference types in type of parameter doesn't match overridden member.
|
||||
dotnet_diagnostic.CS8610.severity = error
|
||||
|
||||
# CS8618: Non-nullable field is uninitialized. Consider declaring as nullable.
|
||||
dotnet_diagnostic.CS8618.severity = error
|
||||
|
||||
# CS8629: Nullable value type may be null.
|
||||
dotnet_diagnostic.CS8629.severity = error
|
||||
|
||||
# CS8620: Argument cannot be used for parameter due to differences in the nullability of reference types.
|
||||
dotnet_diagnostic.CS8620.severity = error
|
||||
|
||||
# CS8614: Nullability of reference types in type of parameter doesn't match implicitly implemented member.
|
||||
dotnet_diagnostic.CS8614.severity = error
|
||||
|
||||
# CS8617: Nullability of reference types in type of parameter doesn't match implemented member.
|
||||
dotnet_diagnostic.CS8617.severity = error
|
||||
|
||||
# CS8611: Nullability of reference types in type of parameter doesn't match partial method declaration.
|
||||
dotnet_diagnostic.CS8611.severity = error
|
||||
|
||||
# CS8597: Thrown value may be null.
|
||||
dotnet_diagnostic.CS8597.severity = error
|
||||
|
||||
# CS8609: Nullability of reference types in return type doesn't match overridden member.
|
||||
dotnet_diagnostic.CS8609.severity = error
|
||||
|
||||
# CS8714: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint.
|
||||
dotnet_diagnostic.CS8714.severity = error
|
||||
|
||||
# CS8605: Unboxing a possibly null value.
|
||||
dotnet_diagnostic.CS8605.severity = error
|
@ -9,13 +9,8 @@ namespace Wabbajack.Common
|
||||
{
|
||||
public class AsyncBlockingCollection<T> : IDisposable
|
||||
{
|
||||
private readonly ConcurrentQueue<T> _collection;
|
||||
private readonly ConcurrentQueue<T> _collection = new ConcurrentQueue<T>();
|
||||
private bool isDisposed = false;
|
||||
|
||||
public AsyncBlockingCollection()
|
||||
{
|
||||
_collection = new ConcurrentQueue<T>();
|
||||
}
|
||||
|
||||
public void Add(T val)
|
||||
{
|
||||
|
@ -10,10 +10,10 @@ namespace Wabbajack.Common
|
||||
public static bool NoSettings { get; set; }
|
||||
|
||||
[CLIOptions("apikey", HelpText = "Manually input an Nexus api key")]
|
||||
public static string ApiKey { get; set; }
|
||||
public static string? ApiKey { get; set; }
|
||||
|
||||
[CLIOptions("install", ShortOption = 'i', HelpText = "Install a ModList via CLI")]
|
||||
public static string InstallPath { get; set; }
|
||||
public static string? InstallPath { get; set; }
|
||||
|
||||
[CLIOptions("help", ShortOption = 'h', HelpText = "Display this message")]
|
||||
public static bool Help { get; set; }
|
||||
@ -94,7 +94,7 @@ namespace Wabbajack.Common
|
||||
// -shortOption, short name of the option. Eg: -o
|
||||
public char ShortOption;
|
||||
// text to be displayed when --help is called
|
||||
public string HelpText;
|
||||
public string HelpText = string.Empty;
|
||||
|
||||
public CLIOptions(string option)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Dynamic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -35,7 +36,7 @@ namespace Wabbajack.Common
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
|
||||
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, [MaybeNullWhen(false)] out object result)
|
||||
{
|
||||
if (indexes.Length > 1)
|
||||
{
|
||||
@ -114,7 +115,7 @@ namespace Wabbajack.Common
|
||||
return Encoding.UTF8.GetString(acc.ToArray());
|
||||
}
|
||||
|
||||
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
|
||||
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, [MaybeNullWhen(false)] out object result)
|
||||
{
|
||||
if (indexes.Length > 1)
|
||||
{
|
||||
|
@ -1,14 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
public static partial class Utils
|
||||
{
|
||||
public static IEnumerable<T> Cons<T>(this IEnumerable<T> coll, T next)
|
||||
{
|
||||
yield return next;
|
||||
foreach (var itm in coll) yield return itm;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ namespace Wabbajack
|
||||
public readonly static ErrorResponse Failure = new ErrorResponse();
|
||||
|
||||
public bool Succeeded { get; }
|
||||
public Exception Exception { get; }
|
||||
public Exception? Exception { get; }
|
||||
private readonly string _reason;
|
||||
|
||||
public bool Failed => !Succeeded;
|
||||
@ -32,15 +32,15 @@ namespace Wabbajack
|
||||
}
|
||||
|
||||
bool IErrorResponse.Succeeded => Succeeded;
|
||||
Exception IErrorResponse.Exception => Exception;
|
||||
Exception? IErrorResponse.Exception => Exception;
|
||||
|
||||
private ErrorResponse(
|
||||
bool succeeded,
|
||||
string reason = null,
|
||||
Exception ex = null)
|
||||
string? reason = null,
|
||||
Exception? ex = null)
|
||||
{
|
||||
Succeeded = succeeded;
|
||||
_reason = reason;
|
||||
_reason = reason ?? string.Empty;
|
||||
Exception = ex;
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ namespace Wabbajack
|
||||
return new ErrorResponse(true, reason);
|
||||
}
|
||||
|
||||
public static ErrorResponse Fail(string reason, Exception ex = null)
|
||||
public static ErrorResponse Fail(string reason, Exception? ex = null)
|
||||
{
|
||||
return new ErrorResponse(false, reason: reason, ex: ex);
|
||||
}
|
||||
@ -75,7 +75,7 @@ namespace Wabbajack
|
||||
return new ErrorResponse(false);
|
||||
}
|
||||
|
||||
public static ErrorResponse Create(bool successful, string reason = null)
|
||||
public static ErrorResponse Create(bool successful, string? reason = null)
|
||||
{
|
||||
return new ErrorResponse(successful, reason);
|
||||
}
|
||||
@ -91,7 +91,7 @@ namespace Wabbajack
|
||||
public interface IErrorResponse
|
||||
{
|
||||
bool Succeeded { get; }
|
||||
Exception Exception { get; }
|
||||
Exception? Exception { get; }
|
||||
string Reason { get; }
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace Wabbajack
|
||||
|
||||
public readonly T Value;
|
||||
public readonly bool Succeeded;
|
||||
public readonly Exception Exception;
|
||||
public readonly Exception? Exception;
|
||||
private readonly string _reason;
|
||||
|
||||
public bool Failed => !Succeeded;
|
||||
@ -25,17 +25,17 @@ namespace Wabbajack
|
||||
}
|
||||
|
||||
bool IErrorResponse.Succeeded => Succeeded;
|
||||
Exception IErrorResponse.Exception => Exception;
|
||||
Exception? IErrorResponse.Exception => Exception;
|
||||
|
||||
private GetResponse(
|
||||
bool succeeded,
|
||||
T val = default(T),
|
||||
string reason = null,
|
||||
Exception ex = null)
|
||||
T val = default,
|
||||
string? reason = null,
|
||||
Exception? ex = null)
|
||||
{
|
||||
Value = val;
|
||||
Succeeded = succeeded;
|
||||
_reason = reason;
|
||||
_reason = reason ?? string.Empty;
|
||||
Exception = ex;
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ namespace Wabbajack
|
||||
&& Equals(Value, other.Value);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (!(obj is GetResponse<T> rhs)) return false;
|
||||
return Equals(rhs);
|
||||
@ -53,8 +53,10 @@ namespace Wabbajack
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashHelper.GetHashCode(Value)
|
||||
.CombineHashCode(Succeeded.GetHashCode());
|
||||
System.HashCode hash = new HashCode();
|
||||
hash.Add(Value);
|
||||
hash.Add(Succeeded);
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@ -124,7 +126,7 @@ namespace Wabbajack
|
||||
return new GetResponse<T>(false, val);
|
||||
}
|
||||
|
||||
public static GetResponse<T> Create(bool successful, T val = default(T), string reason = null)
|
||||
public static GetResponse<T> Create(bool successful, T val = default(T), string? reason = null)
|
||||
{
|
||||
return new GetResponse<T>(successful, val, reason);
|
||||
}
|
||||
|
@ -6,17 +6,37 @@ namespace Wabbajack
|
||||
public static class DictionaryExt
|
||||
{
|
||||
public static V TryCreate<K, V>(this IDictionary<K, V> dict, K key)
|
||||
where K : notnull
|
||||
where V : new()
|
||||
{
|
||||
return dict.TryCreate(key, () => new V());
|
||||
}
|
||||
|
||||
public static V TryCreate<K, V>(this IDictionary<K, V> dict, K key, Func<V> create)
|
||||
where K : notnull
|
||||
{
|
||||
if (dict.TryGetValue(key, out var val)) return val;
|
||||
var ret = create();
|
||||
dict[key] = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void Add<K, V>(this IDictionary<K, V> dict, IEnumerable<KeyValuePair<K, V>> vals)
|
||||
where K : notnull
|
||||
{
|
||||
foreach (var val in vals)
|
||||
{
|
||||
dict.Add(val);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Set<K, V>(this IDictionary<K, V> dict, IEnumerable<KeyValuePair<K, V>> vals)
|
||||
where K : notnull
|
||||
{
|
||||
foreach (var val in vals)
|
||||
{
|
||||
dict[val.Key] = val.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ namespace Wabbajack.Common
|
||||
throw new ArgumentException("T must be an Enum");
|
||||
}
|
||||
|
||||
var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
return attributes.Length > 0 ? attributes[0].Description : val.ToString();
|
||||
var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()!)!.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
return attributes.Length > 0 ? attributes[0].Description : val.ToString()!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,6 @@ namespace Wabbajack
|
||||
|
||||
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException("source");
|
||||
if (rng == null) throw new ArgumentNullException("rng");
|
||||
|
||||
return source.ShuffleIterator(rng);
|
||||
}
|
||||
|
||||
@ -30,5 +27,11 @@ namespace Wabbajack
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static IEnumerable<T> Cons<T>(this IEnumerable<T> coll, T next)
|
||||
{
|
||||
yield return next;
|
||||
foreach (var itm in coll) yield return itm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Taken from: http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
|
||||
*/
|
||||
namespace Wabbajack
|
||||
{
|
||||
public static class HashHelper
|
||||
{
|
||||
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * (arg1 == null ? 0 : arg1.GetHashCode())
|
||||
+ (arg2 == null ? 0 : arg2.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = (arg1 == null ? 0 : arg1.GetHashCode());
|
||||
hash = 31 * hash + (arg2 == null ? 0 : arg2.GetHashCode());
|
||||
return 31 * hash + (arg3 == null ? 0 : arg3.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = (arg1 == null ? 0 : arg1.GetHashCode());
|
||||
hash = 31 * hash + (arg2 == null ? 0 : arg2.GetHashCode());
|
||||
hash = 31 * hash + (arg3 == null ? 0 : arg3.GetHashCode());
|
||||
return 31 * hash + (arg4 == null ? 0 : arg4.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(params T[] list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
if (list == null) return hash;
|
||||
for (int i = 0; i < list.Length; i++)
|
||||
{
|
||||
hash = 31 * hash + GetHashCode(list[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(ReadOnlySpan<T> span)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
if (span == null) return hash;
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
{
|
||||
hash = 31 * hash + GetHashCode(span[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(T t)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (t == null ? 0 : t.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
hash = 31 * hash + (item == null ? 0 : item.GetHashCode());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hashcode for a collection for that the order of items
|
||||
/// does not matter.
|
||||
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
|
||||
/// </summary>
|
||||
public static int GetHashCode_OrderBlind<T>(
|
||||
IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
int count = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
hash += (item == null ? 0 : item.GetHashCode());
|
||||
count++;
|
||||
}
|
||||
return 31 * hash + count.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alternative way to get a hashcode is to use a fluent
|
||||
/// interface like this:<br />
|
||||
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
|
||||
/// CombineHashCode(field3);
|
||||
/// </summary>
|
||||
public static int CombineHashCode<T>(this int hashCode, T arg)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return CombineHashCode(hashCode, (arg == null ? 0 : arg.GetHashCode()));
|
||||
}
|
||||
}
|
||||
|
||||
public static int CombineHashCode(this int hashCode, int rhsHash)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * hashCode + rhsHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,10 +16,12 @@ namespace Wabbajack
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns>Source events that are not null</returns>
|
||||
public static IObservable<T> NotNull<T>(this IObservable<T> source)
|
||||
public static IObservable<T> NotNull<T>(this IObservable<T?> source)
|
||||
where T : class
|
||||
{
|
||||
return source.Where(u => u != null);
|
||||
return source
|
||||
.Where(u => u != null)
|
||||
.Select(u => u!);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -88,9 +90,9 @@ namespace Wabbajack
|
||||
/// Inspiration:
|
||||
/// http://reactivex.io/documentation/operators/debounce.html
|
||||
/// https://stackoverflow.com/questions/20034476/how-can-i-use-reactive-extensions-to-throttle-events-using-a-max-window-size
|
||||
public static IObservable<T> Debounce<T>(this IObservable<T> source, TimeSpan interval, IScheduler scheduler = null)
|
||||
public static IObservable<T> Debounce<T>(this IObservable<T> source, TimeSpan interval, IScheduler? scheduler = null)
|
||||
{
|
||||
scheduler = scheduler ?? Scheduler.Default;
|
||||
scheduler ??= Scheduler.Default;
|
||||
return Observable.Create<T>(o =>
|
||||
{
|
||||
var hasValue = false;
|
||||
@ -218,8 +220,8 @@ namespace Wabbajack
|
||||
.StartWith(false));
|
||||
}
|
||||
|
||||
public static IObservable<T> DisposeOld<T>(this IObservable<T> source)
|
||||
where T : IDisposable
|
||||
public static IObservable<T?> DisposeOld<T>(this IObservable<T?> source)
|
||||
where T : class, IDisposable
|
||||
{
|
||||
return source
|
||||
.StartWith(default(T))
|
||||
|
@ -5,7 +5,7 @@ namespace Wabbajack
|
||||
{
|
||||
public static class TaskExt
|
||||
{
|
||||
public static async void FireAndForget(this Task task, Action<Exception> onException = null)
|
||||
public static async void FireAndForget(this Task task, Action<Exception>? onException = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -58,45 +58,46 @@ namespace Wabbajack.Common
|
||||
public class GameMetaData
|
||||
{
|
||||
public ModManager SupportedModManager { get; internal set; }
|
||||
public string MO2ArchiveName { get; internal set; }
|
||||
public string? MO2ArchiveName { get; internal set; }
|
||||
public Game Game { get; internal set; }
|
||||
public string NexusName { get; internal set; }
|
||||
public string? NexusName { get; internal set; }
|
||||
// Nexus DB id for the game, used in some specific situations
|
||||
public long NexusGameId { get; internal set; }
|
||||
public string MO2Name { get; internal set; }
|
||||
public string? MO2Name { get; internal set; }
|
||||
|
||||
public string HumanFriendlyGameName => Game.GetDescription();
|
||||
|
||||
public string GameLocationRegistryKey { get; internal set; }
|
||||
public string? GameLocationRegistryKey { get; internal set; }
|
||||
// to get steam ids: https://steamdb.info
|
||||
public List<int> SteamIDs { get; internal set; }
|
||||
public List<int>? SteamIDs { get; internal set; }
|
||||
// to get gog ids: https://www.gogdb.org
|
||||
public List<int> GOGIDs { get; internal set; }
|
||||
public List<int>? GOGIDs { get; internal set; }
|
||||
// these are additional folders when a game installs mods outside the game folder
|
||||
public List<string> AdditionalFolders { get; internal set; }
|
||||
public List<string>? AdditionalFolders { get; internal set; }
|
||||
// file to check if the game is present, useful when steamIds and gogIds dont help
|
||||
public List<string> RequiredFiles { get; internal set; }
|
||||
public List<string>? RequiredFiles { get; internal set; }
|
||||
public bool Disabled { get; internal set; }
|
||||
|
||||
|
||||
// Games that this game are commonly confused with, for example Skyrim SE vs Skyrim LE
|
||||
public Game[] CommonlyConfusedWith { get; set; }
|
||||
public Game[] CommonlyConfusedWith { get; set; } = Array.Empty<Game>();
|
||||
|
||||
public string InstalledVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameLocation() == null)
|
||||
AbsolutePath? gameLoc = GameLocation();
|
||||
if (gameLoc == null)
|
||||
throw new GameNotInstalledException(this);
|
||||
if (MainExecutable == null)
|
||||
throw new NotImplementedException();
|
||||
|
||||
return FileVersionInfo.GetVersionInfo((string)GameLocation()?.Combine(MainExecutable)).ProductVersion;
|
||||
return FileVersionInfo.GetVersionInfo((string)gameLoc.Value.Combine(MainExecutable)).ProductVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsInstalled => GameLocation() != null;
|
||||
|
||||
public string MainExecutable { get; internal set; }
|
||||
public string? MainExecutable { get; internal set; }
|
||||
|
||||
public AbsolutePath? GameLocation()
|
||||
{
|
||||
@ -114,14 +115,14 @@ namespace Wabbajack.Common
|
||||
public static class EnumExtensions
|
||||
{
|
||||
public static string GetDescription<T>(this T enumerationValue)
|
||||
where T : struct
|
||||
where T : Enum
|
||||
{
|
||||
var type = enumerationValue.GetType();
|
||||
if(!type.IsEnum)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(enumerationValue)} must be of Enum type", nameof(enumerationValue));
|
||||
}
|
||||
var memberInfo = type.GetMember(enumerationValue.ToString());
|
||||
var memberInfo = type.GetMember(enumerationValue.ToString()!);
|
||||
if(memberInfo.Length > 0)
|
||||
{
|
||||
var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
@ -131,7 +132,7 @@ namespace Wabbajack.Common
|
||||
return ((DescriptionAttribute)attrs[0]).Description;
|
||||
}
|
||||
}
|
||||
return enumerationValue.ToString();
|
||||
return enumerationValue.ToString()!;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,12 +159,11 @@ namespace Wabbajack.Common
|
||||
/// Tries to parse game data from an arbitrary string. Tries first via parsing as a game Enum, then by Nexus name,
|
||||
/// <param nambe="someName"></param>
|
||||
/// <returns></returns>
|
||||
public static GameMetaData GetByFuzzyName(string someName)
|
||||
public static GameMetaData? GetByFuzzyName(string someName)
|
||||
{
|
||||
if (Enum.TryParse(typeof(Game), someName, true, out var metadata)) return ((Game)metadata!).MetaData();
|
||||
|
||||
if (Enum.TryParse(typeof(Game), someName, true, out var metadata)) return ((Game)metadata).MetaData();
|
||||
|
||||
GameMetaData result = null;
|
||||
GameMetaData? result = null;
|
||||
|
||||
result = GetByNexusName(someName);
|
||||
if (result != null) return result;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.HashFunction.xxHash;
|
||||
using System.IO;
|
||||
|
@ -52,7 +52,7 @@ namespace Wabbajack.Common
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = handling, TypeNameAssemblyFormatHandling = format, Converters = Converters
|
||||
});
|
||||
})!;
|
||||
}
|
||||
|
||||
public static T FromJSONString<T>(this string data,
|
||||
@ -63,7 +63,7 @@ namespace Wabbajack.Common
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = handling, TypeNameAssemblyFormatHandling = format, Converters = Converters
|
||||
});
|
||||
})!;
|
||||
}
|
||||
|
||||
public static T FromJSON<T>(this Stream data)
|
||||
@ -72,7 +72,7 @@ namespace Wabbajack.Common
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(s,
|
||||
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto, Converters = Converters});
|
||||
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto, Converters = Converters})!;
|
||||
}
|
||||
catch (JsonSerializationException)
|
||||
{
|
||||
@ -95,7 +95,7 @@ namespace Wabbajack.Common
|
||||
public override Hash ReadJson(JsonReader reader, Type objectType, Hash existingValue, bool hasExistingValue,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
return Hash.FromBase64((string)reader.Value);
|
||||
return Hash.FromBase64((string)reader.Value!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ namespace Wabbajack.Common
|
||||
bool hasExistingValue,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
return (RelativePath)(string)reader.Value;
|
||||
return (RelativePath)(string)reader.Value!;
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ namespace Wabbajack.Common
|
||||
bool hasExistingValue,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
return (AbsolutePath)(string)reader.Value;
|
||||
return (AbsolutePath)(string)reader.Value!;
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ namespace Wabbajack.Common
|
||||
{
|
||||
public override Percent ReadJson(JsonReader reader, Type objectType, Percent existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
double d = (double)reader.Value;
|
||||
double d = (double)reader.Value!;
|
||||
return Percent.FactoryPutInRange(d);
|
||||
}
|
||||
|
||||
@ -162,13 +162,13 @@ namespace Wabbajack.Common
|
||||
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
||||
reader.Read();
|
||||
|
||||
var hash = Hash.FromBase64((string)reader.Value);
|
||||
var hash = Hash.FromBase64((string)reader.Value!);
|
||||
var paths = new List<RelativePath>();
|
||||
|
||||
reader.Read();
|
||||
while (reader.TokenType != JsonToken.EndArray)
|
||||
{
|
||||
paths.Add((RelativePath)(string)reader.Value);
|
||||
paths.Add((RelativePath)(string)reader.Value!);
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
@ -195,13 +195,13 @@ namespace Wabbajack.Common
|
||||
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
||||
reader.Read();
|
||||
|
||||
var abs = (AbsolutePath)(string)reader.Value;
|
||||
var abs = (AbsolutePath)(string)reader.Value!;
|
||||
var paths = new List<RelativePath>();
|
||||
|
||||
reader.Read();
|
||||
while (reader.TokenType != JsonToken.EndArray)
|
||||
{
|
||||
paths.Add((RelativePath)(string)reader.Value);
|
||||
paths.Add((RelativePath)(string)reader.Value!);
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
@ -228,7 +228,13 @@ namespace Wabbajack.Common
|
||||
return (Game)i;
|
||||
}
|
||||
|
||||
return GameRegistry.GetByFuzzyName(str).Game;
|
||||
GameMetaData? game = GameRegistry.GetByFuzzyName(str);
|
||||
if (game == null)
|
||||
{
|
||||
throw new ArgumentException($"Could not convert {str} to a Game type.");
|
||||
}
|
||||
|
||||
return game.Game;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
#nullable disable
|
||||
|
||||
namespace Wabbajack.Common.IO
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
#nullable disable
|
||||
|
||||
namespace Wabbajack.Common.IO
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
#nullable disable
|
||||
|
||||
namespace Wabbajack.Common.IO
|
||||
{
|
||||
|
@ -11,8 +11,8 @@ namespace Wabbajack.Common
|
||||
{
|
||||
public partial class Utils
|
||||
{
|
||||
private static MessagePackSerializerOptions _messagePackOptions;
|
||||
private static IFormatterResolver _resolver;
|
||||
private static MessagePackSerializerOptions? _messagePackOptions;
|
||||
private static IFormatterResolver? _resolver;
|
||||
|
||||
private static void MessagePackInit()
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace Wabbajack.Common
|
||||
var tempKey = progIDKey?.OpenSubKey("shell\\open\\command");
|
||||
if (progIDKey == null || tempKey == null) return true;
|
||||
var value = tempKey.GetValue("");
|
||||
return value == null || !value.ToString().Equals($"\"{execPath}\" -i=\"%1\"");
|
||||
return value == null || !string.Equals(value.ToString(), $"\"{execPath}\" -i=\"%1\"");
|
||||
}
|
||||
|
||||
public static bool IsAssociated()
|
@ -33,7 +33,7 @@ namespace Wabbajack.Common
|
||||
return string.Equals(_path, other._path, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is AbsolutePath other && Equals(other);
|
||||
}
|
||||
@ -42,7 +42,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _path?.GetHashCode(StringComparison.InvariantCultureIgnoreCase) ?? 0;
|
||||
return _path.GetHashCode(StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@ -50,11 +50,12 @@ namespace Wabbajack.Common
|
||||
return _path;
|
||||
}
|
||||
|
||||
private readonly string _path;
|
||||
private readonly string _nullable_path;
|
||||
private string _path => _nullable_path ?? string.Empty;
|
||||
|
||||
public AbsolutePath(string path, bool skipValidation = false)
|
||||
{
|
||||
_path = path.Replace("/", "\\").TrimEnd('\\');
|
||||
_nullable_path = path.Replace("/", "\\").TrimEnd('\\');
|
||||
if (!skipValidation)
|
||||
{
|
||||
ValidateAbsolutePath();
|
||||
@ -63,7 +64,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public AbsolutePath(AbsolutePath path)
|
||||
{
|
||||
_path = path._path;
|
||||
_nullable_path = path._path;
|
||||
}
|
||||
|
||||
private void ValidateAbsolutePath()
|
||||
@ -150,7 +151,8 @@ namespace Wabbajack.Common
|
||||
var location = Assembly.GetEntryAssembly()?.Location ?? null;
|
||||
if (location == null)
|
||||
location = Assembly.GetExecutingAssembly().Location ?? null;
|
||||
|
||||
if (location == null)
|
||||
throw new ArgumentException("Could not find entry point.");
|
||||
return ((AbsolutePath)location).Parent;
|
||||
}
|
||||
}
|
||||
@ -264,7 +266,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public AbsolutePath Combine(params RelativePath[] paths)
|
||||
{
|
||||
return new AbsolutePath(Path.Combine(paths.Select(s => (string)s).Where(s => s != null).Cons(_path).ToArray()));
|
||||
return new AbsolutePath(Path.Combine(paths.Select(s => (string)s).Cons(_path).ToArray()));
|
||||
}
|
||||
|
||||
public AbsolutePath Combine(params string[] paths)
|
||||
@ -371,23 +373,24 @@ namespace Wabbajack.Common
|
||||
|
||||
public struct RelativePath : IPath, IEquatable<RelativePath>, IComparable<RelativePath>
|
||||
{
|
||||
private readonly string _path;
|
||||
private readonly string? _nullable_path;
|
||||
private string _path => _nullable_path ?? string.Empty;
|
||||
|
||||
public RelativePath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
_path = null;
|
||||
_nullable_path = null;
|
||||
return;
|
||||
}
|
||||
var trimmed = path.Replace("/", "\\").Trim('\\');
|
||||
if (string.IsNullOrEmpty(trimmed))
|
||||
{
|
||||
_path = null;
|
||||
_nullable_path = null;
|
||||
return;
|
||||
}
|
||||
|
||||
_path = trimmed;
|
||||
_nullable_path = trimmed;
|
||||
Validate();
|
||||
}
|
||||
|
||||
@ -400,7 +403,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _path?.GetHashCode(StringComparison.InvariantCultureIgnoreCase) ?? 0;
|
||||
return _path.GetHashCode(StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static RelativePath RandomFileName()
|
||||
@ -418,7 +421,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public AbsolutePath RelativeTo(AbsolutePath abs)
|
||||
{
|
||||
return _path == null ? abs : new AbsolutePath(Path.Combine((string)abs, _path));
|
||||
return new AbsolutePath(Path.Combine((string)abs, _path));
|
||||
}
|
||||
|
||||
public AbsolutePath RelativeToEntryPoint()
|
||||
@ -470,7 +473,7 @@ namespace Wabbajack.Common
|
||||
return string.Equals(_path, other._path, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is RelativePath other && Equals(other);
|
||||
}
|
||||
@ -586,7 +589,7 @@ namespace Wabbajack.Common
|
||||
return string.Equals(_extension, other._extension, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Extension other && Equals(other);
|
||||
}
|
||||
@ -603,23 +606,24 @@ namespace Wabbajack.Common
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly string _extension;
|
||||
private readonly string? _nullable_extension;
|
||||
private string _extension => _nullable_extension ?? string.Empty;
|
||||
|
||||
public Extension(string extension)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(extension))
|
||||
{
|
||||
_extension = None._extension;
|
||||
_nullable_extension = None._extension;
|
||||
return;
|
||||
}
|
||||
|
||||
_extension = string.Intern(extension);
|
||||
_nullable_extension = string.Intern(extension);
|
||||
Validate();
|
||||
}
|
||||
|
||||
private Extension(string extension, bool validate)
|
||||
{
|
||||
_extension = string.Intern(extension);
|
||||
_nullable_extension = string.Intern(extension);
|
||||
if (validate)
|
||||
{
|
||||
Validate();
|
||||
@ -628,7 +632,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public Extension(Extension other)
|
||||
{
|
||||
_extension = other._extension;
|
||||
_nullable_extension = other._extension;
|
||||
}
|
||||
|
||||
private void Validate()
|
||||
@ -652,16 +656,6 @@ namespace Wabbajack.Common
|
||||
public static bool operator ==(Extension a, Extension b)
|
||||
{
|
||||
// Super fast comparison because extensions are interned
|
||||
if ((object)a == null && (object)b == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((object)a == null || (object)b == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ReferenceEquals(a._extension, b._extension);
|
||||
}
|
||||
|
||||
@ -726,7 +720,7 @@ namespace Wabbajack.Common
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is HashRelativePath other && Equals(other);
|
||||
}
|
||||
@ -772,7 +766,6 @@ namespace Wabbajack.Common
|
||||
|
||||
public static bool operator ==(FullPath a, FullPath b)
|
||||
{
|
||||
if (a.Paths == null || b.Paths == null) return false;
|
||||
if (a.Base != b.Base || a.Paths.Length != b.Paths.Length)
|
||||
{
|
||||
return false;
|
||||
@ -799,7 +792,7 @@ namespace Wabbajack.Common
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is FullPath other && Equals(other);
|
||||
}
|
||||
|
@ -15,9 +15,9 @@ namespace Wabbajack.Common
|
||||
Output,
|
||||
Error,
|
||||
}
|
||||
|
||||
public string Path { get; set; }
|
||||
public IEnumerable<object> Arguments { get; set; }
|
||||
|
||||
public string Path { get; set; } = string.Empty;
|
||||
public IEnumerable<object> Arguments { get; set; } = Enumerable.Empty<object>();
|
||||
|
||||
public bool LogError { get; set; } = true;
|
||||
|
||||
|
@ -68,4 +68,4 @@ namespace Wabbajack.Common
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ namespace Wabbajack.Common.StatusFeed.Errors
|
||||
{
|
||||
private string _filename;
|
||||
private string _destination;
|
||||
public override string ShortDescription { get; }
|
||||
public override string ExtendedDescription { get; }
|
||||
public override string ShortDescription { get; } = string.Empty;
|
||||
public override string ExtendedDescription { get; } = string.Empty;
|
||||
|
||||
public FileExtractionError(string filename, string destination)
|
||||
{
|
||||
|
@ -8,19 +8,19 @@ namespace Wabbajack.Common.StatusFeed.Errors
|
||||
{
|
||||
public class GenericException : IException
|
||||
{
|
||||
public string ExtraMessage { get; }
|
||||
public string ExtraMessage { get; } = string.Empty;
|
||||
|
||||
public DateTime Timestamp { get; } = DateTime.Now;
|
||||
|
||||
public string ShortDescription => ExtraMessage == null ? Exception?.Message : $"{ExtraMessage} - {Exception?.Message}";
|
||||
public string ShortDescription => string.IsNullOrWhiteSpace(ExtraMessage) ? Exception?.Message ?? string.Empty : $"{ExtraMessage} - {Exception?.Message}";
|
||||
|
||||
public string ExtendedDescription => ExtraMessage == null ? Exception?.ToString() : $"{ExtraMessage} - {Exception?.ToString()}";
|
||||
public string ExtendedDescription => string.IsNullOrWhiteSpace(ExtraMessage) ? Exception?.ToString() ?? string.Empty : $"{ExtraMessage} - {Exception?.ToString()}";
|
||||
|
||||
public Exception Exception { get; }
|
||||
|
||||
public GenericException(Exception exception, string extraMessage = null)
|
||||
public GenericException(Exception exception, string? extraMessage = null)
|
||||
{
|
||||
ExtraMessage = extraMessage;
|
||||
ExtraMessage = extraMessage ?? string.Empty;
|
||||
Exception = exception;
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ namespace Wabbajack.Common.StatusFeed
|
||||
private readonly string _extendedDescription;
|
||||
public override string ExtendedDescription => _extendedDescription ?? ShortDescription;
|
||||
|
||||
public GenericInfo(string short_description, string long_description = null)
|
||||
public GenericInfo(string short_description, string? long_description = null)
|
||||
{
|
||||
ShortDescription = short_description;
|
||||
_extendedDescription = long_description;
|
||||
_extendedDescription = long_description ?? string.Empty;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@ -6,9 +6,9 @@ namespace Wabbajack.Common
|
||||
{
|
||||
private string _message;
|
||||
private Stream _inner;
|
||||
private WorkQueue _queue;
|
||||
private WorkQueue? _queue;
|
||||
|
||||
public StatusFileStream(Stream fs, string message, WorkQueue queue = null)
|
||||
public StatusFileStream(Stream fs, string message, WorkQueue? queue = null)
|
||||
{
|
||||
_queue = queue;
|
||||
_inner = fs;
|
||||
|
@ -10,21 +10,17 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
public class GOGGame : AStoreGame
|
||||
{
|
||||
public override Game Game { get; internal set; }
|
||||
public override string Name { get; internal set; }
|
||||
public override AbsolutePath Path { get; internal set; }
|
||||
public override int ID { get; internal set; }
|
||||
public override StoreType Type { get; internal set; } = StoreType.GOG;
|
||||
}
|
||||
|
||||
public class GOGHandler : AStoreHandler
|
||||
{
|
||||
public override List<AStoreGame> Games { get; set; }
|
||||
public override StoreType Type { get; internal set; }
|
||||
|
||||
private const string GOGRegKey = @"Software\GOG.com\Games";
|
||||
private const string GOG64RegKey = @"Software\WOW6432Node\GOG.com\Games";
|
||||
|
||||
private RegistryKey GOGKey { get; set; }
|
||||
private RegistryKey? GOGKey { get; set; }
|
||||
|
||||
public override bool Init()
|
||||
{
|
||||
@ -56,9 +52,11 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
|
||||
public override bool LoadAllGames()
|
||||
{
|
||||
if(Games == null)
|
||||
Games = new List<AStoreGame>();
|
||||
|
||||
if (GOGKey == null)
|
||||
{
|
||||
Utils.Error("GOGHandler could not read from registry!");
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
string[] keys = GOGKey.GetSubKeyNames();
|
||||
@ -86,7 +84,7 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
return;
|
||||
}
|
||||
|
||||
var gameName = gameNameValue.ToString();
|
||||
var gameName = gameNameValue.ToString() ?? string.Empty;
|
||||
|
||||
var pathValue = subKey.GetValue("PATH");
|
||||
if (pathValue == null)
|
||||
@ -95,7 +93,7 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
return;
|
||||
}
|
||||
|
||||
var path = pathValue.ToString();
|
||||
var path = pathValue.ToString() ?? string.Empty;
|
||||
|
||||
var game = new GOGGame
|
||||
{
|
||||
|
@ -11,33 +11,29 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
public class SteamGame : AStoreGame
|
||||
{
|
||||
public override Game Game { get; internal set; }
|
||||
public override string Name { get; internal set; }
|
||||
public override AbsolutePath Path { get; internal set; }
|
||||
public override int ID { get; internal set; }
|
||||
public override StoreType Type { get; internal set; } = StoreType.STEAM;
|
||||
|
||||
public string Universe;
|
||||
public string Universe = string.Empty;
|
||||
|
||||
public List<SteamWorkshopItem> WorkshopItems;
|
||||
public int WorkshopItemsSize;
|
||||
public readonly List<SteamWorkshopItem> WorkshopItems = new List<SteamWorkshopItem>();
|
||||
public int WorkshopItemsSizeOnDisk;
|
||||
}
|
||||
|
||||
public class SteamWorkshopItem
|
||||
{
|
||||
public SteamGame Game;
|
||||
public SteamGame? Game;
|
||||
public int ItemID;
|
||||
public int Size;
|
||||
}
|
||||
|
||||
public class SteamHandler : AStoreHandler
|
||||
{
|
||||
public override List<AStoreGame> Games { get; set; }
|
||||
public override StoreType Type { get; internal set; } = StoreType.STEAM;
|
||||
|
||||
private const string SteamRegKey = @"Software\Valve\Steam";
|
||||
|
||||
public string SteamPath { get; set; }
|
||||
private List<string> SteamUniverses { get; set; }
|
||||
public string SteamPath { get; set; } = string.Empty;
|
||||
private List<string>? SteamUniverses { get; set; }
|
||||
|
||||
private string SteamConfig => Path.Combine(SteamPath, "config", "config.vdf");
|
||||
|
||||
@ -54,7 +50,7 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
return false;
|
||||
}
|
||||
|
||||
SteamPath = steamPathKey.ToString();
|
||||
SteamPath = steamPathKey.ToString() ?? string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(SteamPath))
|
||||
{
|
||||
Utils.Error(new StoreException("Path to the Steam Directory from registry is Null or Empty!"));
|
||||
@ -86,9 +82,9 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
return false;
|
||||
}
|
||||
|
||||
private void LoadUniverses()
|
||||
private List<string> LoadUniverses()
|
||||
{
|
||||
SteamUniverses = new List<string>();
|
||||
var ret = new List<string>();
|
||||
|
||||
File.ReadAllLines(SteamConfig).Do(l =>
|
||||
{
|
||||
@ -100,22 +96,24 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
Utils.Log($"Directory {s} does not exist, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
SteamUniverses.Add(s);
|
||||
|
||||
ret.Add(s);
|
||||
Utils.Log($"Steam Library found at {s}");
|
||||
});
|
||||
|
||||
Utils.Log($"Total number of Steam Libraries found: {SteamUniverses.Count}");
|
||||
Utils.Log($"Total number of Steam Libraries found: {ret.Count}");
|
||||
|
||||
// Default path in the Steam folder isn't in the configs
|
||||
if(Directory.Exists(Path.Combine(SteamPath, "steamapps")))
|
||||
SteamUniverses.Add(Path.Combine(SteamPath, "steamapps"));
|
||||
if (Directory.Exists(Path.Combine(SteamPath, "steamapps")))
|
||||
ret.Add(Path.Combine(SteamPath, "steamapps"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override bool LoadAllGames()
|
||||
{
|
||||
if(SteamUniverses == null)
|
||||
LoadUniverses();
|
||||
if (SteamUniverses == null)
|
||||
SteamUniverses = LoadUniverses();
|
||||
|
||||
if (SteamUniverses.Count == 0)
|
||||
{
|
||||
@ -123,9 +121,6 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Games == null)
|
||||
Games = new List<AStoreGame>();
|
||||
|
||||
SteamUniverses.Do(u =>
|
||||
{
|
||||
Utils.Log($"Searching for Steam Games in {u}");
|
||||
@ -188,9 +183,6 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
|
||||
private static void LoadWorkshopItems(SteamGame game)
|
||||
{
|
||||
if(game.WorkshopItems == null)
|
||||
game.WorkshopItems = new List<SteamWorkshopItem>();
|
||||
|
||||
var workshop = Path.Combine(game.Universe, "workshop");
|
||||
if (!Directory.Exists(workshop))
|
||||
return;
|
||||
@ -210,13 +202,13 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
var bracketStart = 0;
|
||||
var bracketEnd = 0;
|
||||
|
||||
var currentItem = new SteamWorkshopItem();
|
||||
SteamWorkshopItem? currentItem = new SteamWorkshopItem();
|
||||
|
||||
lines.Do(l =>
|
||||
{
|
||||
if (end)
|
||||
return;
|
||||
if(currentItem == null)
|
||||
if (currentItem == null)
|
||||
currentItem = new SteamWorkshopItem();
|
||||
|
||||
var currentLine = lines.IndexOf(l);
|
||||
@ -239,7 +231,7 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
if (!int.TryParse(GetVdfValue(l), out var sizeOnDisk))
|
||||
return;
|
||||
|
||||
game.WorkshopItemsSize += sizeOnDisk;
|
||||
game.WorkshopItemsSizeOnDisk += sizeOnDisk;
|
||||
}
|
||||
|
||||
if (l.ContainsCaseInsensitive("\"WorkshopItemsInstalled\""))
|
||||
|
@ -61,15 +61,15 @@ namespace Wabbajack.Common.StoreHandlers
|
||||
public abstract class AStoreGame
|
||||
{
|
||||
public abstract Game Game { get; internal set; }
|
||||
public abstract string Name { get; internal set; }
|
||||
public abstract AbsolutePath Path { get; internal set; }
|
||||
public abstract int ID { get; internal set; }
|
||||
public virtual string Name { get; internal set; } = string.Empty;
|
||||
public virtual AbsolutePath Path { get; internal set; }
|
||||
public virtual int ID { get; internal set; }
|
||||
public abstract StoreType Type { get; internal set; }
|
||||
}
|
||||
|
||||
public abstract class AStoreHandler
|
||||
{
|
||||
public abstract List<AStoreGame> Games { get; set; }
|
||||
public List<AStoreGame> Games { get; } = new List<AStoreGame>();
|
||||
|
||||
public abstract StoreType Type { get; internal set; }
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace Wabbajack.Common
|
||||
{
|
||||
public class AsyncLock
|
||||
{
|
||||
private SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
|
||||
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
|
||||
|
||||
public async Task<IDisposable> Wait()
|
||||
{
|
||||
|
@ -43,9 +43,9 @@ namespace Wabbajack.Common
|
||||
public void Dispose()
|
||||
{
|
||||
_allocated.Do(s => s.Dispose());
|
||||
_mmap?.Dispose();
|
||||
_fileStream?.Dispose();
|
||||
_file?.Dispose();
|
||||
_mmap.Dispose();
|
||||
_fileStream.Dispose();
|
||||
_file.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ namespace Wabbajack.Common
|
||||
return new Percent(percent, check: false);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (!(obj is Percent rhs)) return false;
|
||||
return Equals(rhs);
|
||||
@ -191,7 +191,7 @@ namespace Wabbajack.Common
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is Percent rhs)
|
||||
{
|
||||
|
@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AlphaPath = Alphaleonis.Win32.Filesystem.Path;
|
||||
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
|
@ -3,6 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.HashFunction.xxHash;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@ -132,12 +133,12 @@ namespace Wabbajack.Common
|
||||
Log(errMessage);
|
||||
}
|
||||
|
||||
public static void Error(Exception ex, string extraMessage = null)
|
||||
public static void Error(Exception ex, string? extraMessage = null)
|
||||
{
|
||||
Log(new GenericException(ex, extraMessage));
|
||||
}
|
||||
|
||||
public static void ErrorThrow(Exception ex, string extraMessage = null)
|
||||
public static void ErrorThrow(Exception ex, string? extraMessage = null)
|
||||
{
|
||||
Error(ex, extraMessage);
|
||||
throw ex;
|
||||
@ -231,29 +232,21 @@ namespace Wabbajack.Common
|
||||
Status(status, Percent.FactoryPutInRange(totalRead, maxSize));
|
||||
}
|
||||
}
|
||||
public static string xxHash(this byte[] data, bool nullOnIOError = false)
|
||||
public static string xxHash(this byte[] data)
|
||||
{
|
||||
try
|
||||
var hash = new xxHashConfig();
|
||||
hash.HashSizeInBits = 64;
|
||||
hash.Seed = 0x42;
|
||||
using (var fs = new MemoryStream(data))
|
||||
{
|
||||
var hash = new xxHashConfig();
|
||||
hash.HashSizeInBits = 64;
|
||||
hash.Seed = 0x42;
|
||||
using (var fs = new MemoryStream(data))
|
||||
var config = new xxHashConfig();
|
||||
config.HashSizeInBits = 64;
|
||||
using (var f = new StatusFileStream(fs, $"Hashing memory stream"))
|
||||
{
|
||||
var config = new xxHashConfig();
|
||||
config.HashSizeInBits = 64;
|
||||
using (var f = new StatusFileStream(fs, $"Hashing memory stream"))
|
||||
{
|
||||
var value = xxHashFactory.Instance.Create(config).ComputeHash(f);
|
||||
return value.AsBase64String();
|
||||
}
|
||||
var value = xxHashFactory.Instance.Create(config).ComputeHash(f);
|
||||
return value.AsBase64String();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
if (nullOnIOError) return null;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -673,7 +666,9 @@ namespace Wabbajack.Common
|
||||
return a[a.Length - 1];
|
||||
}
|
||||
|
||||
[return: MaybeNull]
|
||||
public static V GetOrDefault<K, V>(this IDictionary<K, V> dict, K key)
|
||||
where K : notnull
|
||||
{
|
||||
if (dict.TryGetValue(key, out var v)) return v;
|
||||
return default;
|
||||
@ -776,7 +771,7 @@ namespace Wabbajack.Common
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetPatch(Hash foundHash, Hash fileHash, out byte[] ePatch)
|
||||
public static bool TryGetPatch(Hash foundHash, Hash fileHash, [MaybeNullWhen(false)] out byte[] ePatch)
|
||||
{
|
||||
var patchName = Consts.PatchCacheFolder.Combine($"{foundHash.ToHex()}_{fileHash.ToHex()}.patch");
|
||||
if (patchName.Exists)
|
||||
@ -809,17 +804,6 @@ namespace Wabbajack.Common
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
public static void Warning(string s)
|
||||
{
|
||||
Log($"WARNING: {s}");
|
||||
}*/
|
||||
|
||||
public static TV GetOrDefault<TK, TV>(this Dictionary<TK, TV> dict, TK key)
|
||||
{
|
||||
return dict.TryGetValue(key, out var result) ? result : default;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> ButLast<T>(this IEnumerable<T> coll)
|
||||
{
|
||||
var lst = coll.ToList();
|
||||
@ -1097,7 +1081,7 @@ namespace Wabbajack.Common
|
||||
public class NexusErrorResponse
|
||||
{
|
||||
public int code;
|
||||
public string message;
|
||||
public string message = string.Empty;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="7z.dll.gz" />
|
||||
|
@ -25,7 +25,7 @@ namespace Wabbajack.Common
|
||||
|
||||
public static bool WorkerThread => AsyncLocalCurrentQueue.Value != null;
|
||||
public bool IsWorkerThread => WorkerThread;
|
||||
internal static readonly AsyncLocal<WorkQueue> AsyncLocalCurrentQueue = new AsyncLocal<WorkQueue>();
|
||||
internal static readonly AsyncLocal<WorkQueue?> AsyncLocalCurrentQueue = new AsyncLocal<WorkQueue?>();
|
||||
|
||||
private readonly Subject<CPUStatus> _Status = new Subject<CPUStatus>();
|
||||
public IObservable<CPUStatus> Status => _Status;
|
||||
@ -194,7 +194,7 @@ namespace Wabbajack.Common
|
||||
public class CPUStatus
|
||||
{
|
||||
public Percent ProgressPercent { get; internal set; }
|
||||
public string Msg { get; internal set; }
|
||||
public string Msg { get; internal set; } = string.Empty;
|
||||
public int ID { get; internal set; }
|
||||
public bool IsWorking { get; internal set; }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user