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
@ -122,3 +122,66 @@ csharp_preserve_single_line_blocks = true
|
|||||||
dotnet_diagnostic.CS4014.severity = error
|
dotnet_diagnostic.CS4014.severity = error
|
||||||
# CS1998: Async function does not contain await
|
# 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,14 +9,9 @@ namespace Wabbajack.Common
|
|||||||
{
|
{
|
||||||
public class AsyncBlockingCollection<T> : IDisposable
|
public class AsyncBlockingCollection<T> : IDisposable
|
||||||
{
|
{
|
||||||
private readonly ConcurrentQueue<T> _collection;
|
private readonly ConcurrentQueue<T> _collection = new ConcurrentQueue<T>();
|
||||||
private bool isDisposed = false;
|
private bool isDisposed = false;
|
||||||
|
|
||||||
public AsyncBlockingCollection()
|
|
||||||
{
|
|
||||||
_collection = new ConcurrentQueue<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(T val)
|
public void Add(T val)
|
||||||
{
|
{
|
||||||
_collection.Enqueue(val);
|
_collection.Enqueue(val);
|
||||||
|
@ -10,10 +10,10 @@ namespace Wabbajack.Common
|
|||||||
public static bool NoSettings { get; set; }
|
public static bool NoSettings { get; set; }
|
||||||
|
|
||||||
[CLIOptions("apikey", HelpText = "Manually input an Nexus api key")]
|
[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")]
|
[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")]
|
[CLIOptions("help", ShortOption = 'h', HelpText = "Display this message")]
|
||||||
public static bool Help { get; set; }
|
public static bool Help { get; set; }
|
||||||
@ -94,7 +94,7 @@ namespace Wabbajack.Common
|
|||||||
// -shortOption, short name of the option. Eg: -o
|
// -shortOption, short name of the option. Eg: -o
|
||||||
public char ShortOption;
|
public char ShortOption;
|
||||||
// text to be displayed when --help is called
|
// text to be displayed when --help is called
|
||||||
public string HelpText;
|
public string HelpText = string.Empty;
|
||||||
|
|
||||||
public CLIOptions(string option)
|
public CLIOptions(string option)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Dynamic;
|
using System.Dynamic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@ -35,7 +36,7 @@ namespace Wabbajack.Common
|
|||||||
return true;
|
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)
|
if (indexes.Length > 1)
|
||||||
{
|
{
|
||||||
@ -114,7 +115,7 @@ namespace Wabbajack.Common
|
|||||||
return Encoding.UTF8.GetString(acc.ToArray());
|
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)
|
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 readonly static ErrorResponse Failure = new ErrorResponse();
|
||||||
|
|
||||||
public bool Succeeded { get; }
|
public bool Succeeded { get; }
|
||||||
public Exception Exception { get; }
|
public Exception? Exception { get; }
|
||||||
private readonly string _reason;
|
private readonly string _reason;
|
||||||
|
|
||||||
public bool Failed => !Succeeded;
|
public bool Failed => !Succeeded;
|
||||||
@ -32,15 +32,15 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IErrorResponse.Succeeded => Succeeded;
|
bool IErrorResponse.Succeeded => Succeeded;
|
||||||
Exception IErrorResponse.Exception => Exception;
|
Exception? IErrorResponse.Exception => Exception;
|
||||||
|
|
||||||
private ErrorResponse(
|
private ErrorResponse(
|
||||||
bool succeeded,
|
bool succeeded,
|
||||||
string reason = null,
|
string? reason = null,
|
||||||
Exception ex = null)
|
Exception? ex = null)
|
||||||
{
|
{
|
||||||
Succeeded = succeeded;
|
Succeeded = succeeded;
|
||||||
_reason = reason;
|
_reason = reason ?? string.Empty;
|
||||||
Exception = ex;
|
Exception = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ namespace Wabbajack
|
|||||||
return new ErrorResponse(true, reason);
|
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);
|
return new ErrorResponse(false, reason: reason, ex: ex);
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ namespace Wabbajack
|
|||||||
return new ErrorResponse(false);
|
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);
|
return new ErrorResponse(successful, reason);
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ namespace Wabbajack
|
|||||||
public interface IErrorResponse
|
public interface IErrorResponse
|
||||||
{
|
{
|
||||||
bool Succeeded { get; }
|
bool Succeeded { get; }
|
||||||
Exception Exception { get; }
|
Exception? Exception { get; }
|
||||||
string Reason { get; }
|
string Reason { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ namespace Wabbajack
|
|||||||
|
|
||||||
public readonly T Value;
|
public readonly T Value;
|
||||||
public readonly bool Succeeded;
|
public readonly bool Succeeded;
|
||||||
public readonly Exception Exception;
|
public readonly Exception? Exception;
|
||||||
private readonly string _reason;
|
private readonly string _reason;
|
||||||
|
|
||||||
public bool Failed => !Succeeded;
|
public bool Failed => !Succeeded;
|
||||||
@ -25,17 +25,17 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IErrorResponse.Succeeded => Succeeded;
|
bool IErrorResponse.Succeeded => Succeeded;
|
||||||
Exception IErrorResponse.Exception => Exception;
|
Exception? IErrorResponse.Exception => Exception;
|
||||||
|
|
||||||
private GetResponse(
|
private GetResponse(
|
||||||
bool succeeded,
|
bool succeeded,
|
||||||
T val = default(T),
|
T val = default,
|
||||||
string reason = null,
|
string? reason = null,
|
||||||
Exception ex = null)
|
Exception? ex = null)
|
||||||
{
|
{
|
||||||
Value = val;
|
Value = val;
|
||||||
Succeeded = succeeded;
|
Succeeded = succeeded;
|
||||||
_reason = reason;
|
_reason = reason ?? string.Empty;
|
||||||
Exception = ex;
|
Exception = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ namespace Wabbajack
|
|||||||
&& Equals(Value, other.Value);
|
&& Equals(Value, other.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (!(obj is GetResponse<T> rhs)) return false;
|
if (!(obj is GetResponse<T> rhs)) return false;
|
||||||
return Equals(rhs);
|
return Equals(rhs);
|
||||||
@ -53,8 +53,10 @@ namespace Wabbajack
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashHelper.GetHashCode(Value)
|
System.HashCode hash = new HashCode();
|
||||||
.CombineHashCode(Succeeded.GetHashCode());
|
hash.Add(Value);
|
||||||
|
hash.Add(Succeeded);
|
||||||
|
return hash.ToHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -124,7 +126,7 @@ namespace Wabbajack
|
|||||||
return new GetResponse<T>(false, val);
|
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);
|
return new GetResponse<T>(successful, val, reason);
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,37 @@ namespace Wabbajack
|
|||||||
public static class DictionaryExt
|
public static class DictionaryExt
|
||||||
{
|
{
|
||||||
public static V TryCreate<K, V>(this IDictionary<K, V> dict, K key)
|
public static V TryCreate<K, V>(this IDictionary<K, V> dict, K key)
|
||||||
|
where K : notnull
|
||||||
where V : new()
|
where V : new()
|
||||||
{
|
{
|
||||||
return dict.TryCreate(key, () => new V());
|
return dict.TryCreate(key, () => new V());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static V TryCreate<K, V>(this IDictionary<K, V> dict, K key, Func<V> create)
|
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;
|
if (dict.TryGetValue(key, out var val)) return val;
|
||||||
var ret = create();
|
var ret = create();
|
||||||
dict[key] = ret;
|
dict[key] = ret;
|
||||||
return 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");
|
throw new ArgumentException("T must be an Enum");
|
||||||
}
|
}
|
||||||
|
|
||||||
var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
|
var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()!)!.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
return attributes.Length > 0 ? attributes[0].Description : val.ToString();
|
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)
|
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);
|
return source.ShuffleIterator(rng);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,5 +27,11 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#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>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="source"></param>
|
/// <param name="source"></param>
|
||||||
/// <returns>Source events that are not null</returns>
|
/// <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
|
where T : class
|
||||||
{
|
{
|
||||||
return source.Where(u => u != null);
|
return source
|
||||||
|
.Where(u => u != null)
|
||||||
|
.Select(u => u!);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -88,9 +90,9 @@ namespace Wabbajack
|
|||||||
/// Inspiration:
|
/// Inspiration:
|
||||||
/// http://reactivex.io/documentation/operators/debounce.html
|
/// 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
|
/// 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 =>
|
return Observable.Create<T>(o =>
|
||||||
{
|
{
|
||||||
var hasValue = false;
|
var hasValue = false;
|
||||||
@ -218,8 +220,8 @@ namespace Wabbajack
|
|||||||
.StartWith(false));
|
.StartWith(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IObservable<T> DisposeOld<T>(this IObservable<T> source)
|
public static IObservable<T?> DisposeOld<T>(this IObservable<T?> source)
|
||||||
where T : IDisposable
|
where T : class, IDisposable
|
||||||
{
|
{
|
||||||
return source
|
return source
|
||||||
.StartWith(default(T))
|
.StartWith(default(T))
|
||||||
|
@ -5,7 +5,7 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
public static class TaskExt
|
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
|
try
|
||||||
{
|
{
|
||||||
|
@ -58,45 +58,46 @@ namespace Wabbajack.Common
|
|||||||
public class GameMetaData
|
public class GameMetaData
|
||||||
{
|
{
|
||||||
public ModManager SupportedModManager { get; internal set; }
|
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 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
|
// Nexus DB id for the game, used in some specific situations
|
||||||
public long NexusGameId { get; internal set; }
|
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 HumanFriendlyGameName => Game.GetDescription();
|
||||||
|
|
||||||
public string GameLocationRegistryKey { get; internal set; }
|
public string? GameLocationRegistryKey { get; internal set; }
|
||||||
// to get steam ids: https://steamdb.info
|
// 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
|
// 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
|
// 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
|
// 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; }
|
public bool Disabled { get; internal set; }
|
||||||
|
|
||||||
// Games that this game are commonly confused with, for example Skyrim SE vs Skyrim LE
|
// 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
|
public string InstalledVersion
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (GameLocation() == null)
|
AbsolutePath? gameLoc = GameLocation();
|
||||||
|
if (gameLoc == null)
|
||||||
throw new GameNotInstalledException(this);
|
throw new GameNotInstalledException(this);
|
||||||
if (MainExecutable == null)
|
if (MainExecutable == null)
|
||||||
throw new NotImplementedException();
|
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 bool IsInstalled => GameLocation() != null;
|
||||||
|
|
||||||
public string MainExecutable { get; internal set; }
|
public string? MainExecutable { get; internal set; }
|
||||||
|
|
||||||
public AbsolutePath? GameLocation()
|
public AbsolutePath? GameLocation()
|
||||||
{
|
{
|
||||||
@ -114,14 +115,14 @@ namespace Wabbajack.Common
|
|||||||
public static class EnumExtensions
|
public static class EnumExtensions
|
||||||
{
|
{
|
||||||
public static string GetDescription<T>(this T enumerationValue)
|
public static string GetDescription<T>(this T enumerationValue)
|
||||||
where T : struct
|
where T : Enum
|
||||||
{
|
{
|
||||||
var type = enumerationValue.GetType();
|
var type = enumerationValue.GetType();
|
||||||
if(!type.IsEnum)
|
if(!type.IsEnum)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"{nameof(enumerationValue)} must be of Enum type", nameof(enumerationValue));
|
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)
|
if(memberInfo.Length > 0)
|
||||||
{
|
{
|
||||||
var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
|
var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||||
@ -131,7 +132,7 @@ namespace Wabbajack.Common
|
|||||||
return ((DescriptionAttribute)attrs[0]).Description;
|
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,
|
/// 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>
|
/// <param nambe="someName"></param>
|
||||||
/// <returns></returns>
|
/// <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);
|
result = GetByNexusName(someName);
|
||||||
if (result != null) return result;
|
if (result != null) return result;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#nullable enable
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.HashFunction.xxHash;
|
using System.Data.HashFunction.xxHash;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -52,7 +52,7 @@ namespace Wabbajack.Common
|
|||||||
new JsonSerializerSettings
|
new JsonSerializerSettings
|
||||||
{
|
{
|
||||||
TypeNameHandling = handling, TypeNameAssemblyFormatHandling = format, Converters = Converters
|
TypeNameHandling = handling, TypeNameAssemblyFormatHandling = format, Converters = Converters
|
||||||
});
|
})!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T FromJSONString<T>(this string data,
|
public static T FromJSONString<T>(this string data,
|
||||||
@ -63,7 +63,7 @@ namespace Wabbajack.Common
|
|||||||
new JsonSerializerSettings
|
new JsonSerializerSettings
|
||||||
{
|
{
|
||||||
TypeNameHandling = handling, TypeNameAssemblyFormatHandling = format, Converters = Converters
|
TypeNameHandling = handling, TypeNameAssemblyFormatHandling = format, Converters = Converters
|
||||||
});
|
})!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T FromJSON<T>(this Stream data)
|
public static T FromJSON<T>(this Stream data)
|
||||||
@ -72,7 +72,7 @@ namespace Wabbajack.Common
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject<T>(s,
|
return JsonConvert.DeserializeObject<T>(s,
|
||||||
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto, Converters = Converters});
|
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto, Converters = Converters})!;
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException)
|
catch (JsonSerializationException)
|
||||||
{
|
{
|
||||||
@ -95,7 +95,7 @@ namespace Wabbajack.Common
|
|||||||
public override Hash ReadJson(JsonReader reader, Type objectType, Hash existingValue, bool hasExistingValue,
|
public override Hash ReadJson(JsonReader reader, Type objectType, Hash existingValue, bool hasExistingValue,
|
||||||
JsonSerializer serializer)
|
JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
return Hash.FromBase64((string)reader.Value);
|
return Hash.FromBase64((string)reader.Value!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ namespace Wabbajack.Common
|
|||||||
bool hasExistingValue,
|
bool hasExistingValue,
|
||||||
JsonSerializer serializer)
|
JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
return (RelativePath)(string)reader.Value;
|
return (RelativePath)(string)reader.Value!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ namespace Wabbajack.Common
|
|||||||
bool hasExistingValue,
|
bool hasExistingValue,
|
||||||
JsonSerializer serializer)
|
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)
|
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);
|
return Percent.FactoryPutInRange(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,13 +162,13 @@ namespace Wabbajack.Common
|
|||||||
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
||||||
reader.Read();
|
reader.Read();
|
||||||
|
|
||||||
var hash = Hash.FromBase64((string)reader.Value);
|
var hash = Hash.FromBase64((string)reader.Value!);
|
||||||
var paths = new List<RelativePath>();
|
var paths = new List<RelativePath>();
|
||||||
|
|
||||||
reader.Read();
|
reader.Read();
|
||||||
while (reader.TokenType != JsonToken.EndArray)
|
while (reader.TokenType != JsonToken.EndArray)
|
||||||
{
|
{
|
||||||
paths.Add((RelativePath)(string)reader.Value);
|
paths.Add((RelativePath)(string)reader.Value!);
|
||||||
reader.Read();
|
reader.Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,13 +195,13 @@ namespace Wabbajack.Common
|
|||||||
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
||||||
reader.Read();
|
reader.Read();
|
||||||
|
|
||||||
var abs = (AbsolutePath)(string)reader.Value;
|
var abs = (AbsolutePath)(string)reader.Value!;
|
||||||
var paths = new List<RelativePath>();
|
var paths = new List<RelativePath>();
|
||||||
|
|
||||||
reader.Read();
|
reader.Read();
|
||||||
while (reader.TokenType != JsonToken.EndArray)
|
while (reader.TokenType != JsonToken.EndArray)
|
||||||
{
|
{
|
||||||
paths.Add((RelativePath)(string)reader.Value);
|
paths.Add((RelativePath)(string)reader.Value!);
|
||||||
reader.Read();
|
reader.Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +228,13 @@ namespace Wabbajack.Common
|
|||||||
return (Game)i;
|
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;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
namespace Wabbajack.Common.IO
|
namespace Wabbajack.Common.IO
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
namespace Wabbajack.Common.IO
|
namespace Wabbajack.Common.IO
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
namespace Wabbajack.Common.IO
|
namespace Wabbajack.Common.IO
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,8 @@ namespace Wabbajack.Common
|
|||||||
{
|
{
|
||||||
public partial class Utils
|
public partial class Utils
|
||||||
{
|
{
|
||||||
private static MessagePackSerializerOptions _messagePackOptions;
|
private static MessagePackSerializerOptions? _messagePackOptions;
|
||||||
private static IFormatterResolver _resolver;
|
private static IFormatterResolver? _resolver;
|
||||||
|
|
||||||
private static void MessagePackInit()
|
private static void MessagePackInit()
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ namespace Wabbajack.Common
|
|||||||
var tempKey = progIDKey?.OpenSubKey("shell\\open\\command");
|
var tempKey = progIDKey?.OpenSubKey("shell\\open\\command");
|
||||||
if (progIDKey == null || tempKey == null) return true;
|
if (progIDKey == null || tempKey == null) return true;
|
||||||
var value = tempKey.GetValue("");
|
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()
|
public static bool IsAssociated()
|
@ -33,7 +33,7 @@ namespace Wabbajack.Common
|
|||||||
return string.Equals(_path, other._path, StringComparison.InvariantCultureIgnoreCase);
|
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);
|
return obj is AbsolutePath other && Equals(other);
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return _path?.GetHashCode(StringComparison.InvariantCultureIgnoreCase) ?? 0;
|
return _path.GetHashCode(StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -50,11 +50,12 @@ namespace Wabbajack.Common
|
|||||||
return _path;
|
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)
|
public AbsolutePath(string path, bool skipValidation = false)
|
||||||
{
|
{
|
||||||
_path = path.Replace("/", "\\").TrimEnd('\\');
|
_nullable_path = path.Replace("/", "\\").TrimEnd('\\');
|
||||||
if (!skipValidation)
|
if (!skipValidation)
|
||||||
{
|
{
|
||||||
ValidateAbsolutePath();
|
ValidateAbsolutePath();
|
||||||
@ -63,7 +64,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public AbsolutePath(AbsolutePath path)
|
public AbsolutePath(AbsolutePath path)
|
||||||
{
|
{
|
||||||
_path = path._path;
|
_nullable_path = path._path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateAbsolutePath()
|
private void ValidateAbsolutePath()
|
||||||
@ -150,7 +151,8 @@ namespace Wabbajack.Common
|
|||||||
var location = Assembly.GetEntryAssembly()?.Location ?? null;
|
var location = Assembly.GetEntryAssembly()?.Location ?? null;
|
||||||
if (location == null)
|
if (location == null)
|
||||||
location = Assembly.GetExecutingAssembly().Location ?? null;
|
location = Assembly.GetExecutingAssembly().Location ?? null;
|
||||||
|
if (location == null)
|
||||||
|
throw new ArgumentException("Could not find entry point.");
|
||||||
return ((AbsolutePath)location).Parent;
|
return ((AbsolutePath)location).Parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +266,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public AbsolutePath Combine(params RelativePath[] paths)
|
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)
|
public AbsolutePath Combine(params string[] paths)
|
||||||
@ -371,23 +373,24 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public struct RelativePath : IPath, IEquatable<RelativePath>, IComparable<RelativePath>
|
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)
|
public RelativePath(string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
{
|
{
|
||||||
_path = null;
|
_nullable_path = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var trimmed = path.Replace("/", "\\").Trim('\\');
|
var trimmed = path.Replace("/", "\\").Trim('\\');
|
||||||
if (string.IsNullOrEmpty(trimmed))
|
if (string.IsNullOrEmpty(trimmed))
|
||||||
{
|
{
|
||||||
_path = null;
|
_nullable_path = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_path = trimmed;
|
_nullable_path = trimmed;
|
||||||
Validate();
|
Validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +403,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return _path?.GetHashCode(StringComparison.InvariantCultureIgnoreCase) ?? 0;
|
return _path.GetHashCode(StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RelativePath RandomFileName()
|
public static RelativePath RandomFileName()
|
||||||
@ -418,7 +421,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public AbsolutePath RelativeTo(AbsolutePath abs)
|
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()
|
public AbsolutePath RelativeToEntryPoint()
|
||||||
@ -470,7 +473,7 @@ namespace Wabbajack.Common
|
|||||||
return string.Equals(_path, other._path, StringComparison.InvariantCultureIgnoreCase);
|
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);
|
return obj is RelativePath other && Equals(other);
|
||||||
}
|
}
|
||||||
@ -586,7 +589,7 @@ namespace Wabbajack.Common
|
|||||||
return string.Equals(_extension, other._extension, StringComparison.InvariantCultureIgnoreCase);
|
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);
|
return obj is Extension other && Equals(other);
|
||||||
}
|
}
|
||||||
@ -603,23 +606,24 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private readonly string _extension;
|
private readonly string? _nullable_extension;
|
||||||
|
private string _extension => _nullable_extension ?? string.Empty;
|
||||||
|
|
||||||
public Extension(string extension)
|
public Extension(string extension)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(extension))
|
if (string.IsNullOrWhiteSpace(extension))
|
||||||
{
|
{
|
||||||
_extension = None._extension;
|
_nullable_extension = None._extension;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_extension = string.Intern(extension);
|
_nullable_extension = string.Intern(extension);
|
||||||
Validate();
|
Validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Extension(string extension, bool validate)
|
private Extension(string extension, bool validate)
|
||||||
{
|
{
|
||||||
_extension = string.Intern(extension);
|
_nullable_extension = string.Intern(extension);
|
||||||
if (validate)
|
if (validate)
|
||||||
{
|
{
|
||||||
Validate();
|
Validate();
|
||||||
@ -628,7 +632,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public Extension(Extension other)
|
public Extension(Extension other)
|
||||||
{
|
{
|
||||||
_extension = other._extension;
|
_nullable_extension = other._extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Validate()
|
private void Validate()
|
||||||
@ -652,16 +656,6 @@ namespace Wabbajack.Common
|
|||||||
public static bool operator ==(Extension a, Extension b)
|
public static bool operator ==(Extension a, Extension b)
|
||||||
{
|
{
|
||||||
// Super fast comparison because extensions are interned
|
// 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);
|
return ReferenceEquals(a._extension, b._extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,7 +720,7 @@ namespace Wabbajack.Common
|
|||||||
return this == other;
|
return this == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
return obj is HashRelativePath other && Equals(other);
|
return obj is HashRelativePath other && Equals(other);
|
||||||
}
|
}
|
||||||
@ -772,7 +766,6 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public static bool operator ==(FullPath a, FullPath b)
|
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)
|
if (a.Base != b.Base || a.Paths.Length != b.Paths.Length)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -799,7 +792,7 @@ namespace Wabbajack.Common
|
|||||||
return this == other;
|
return this == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
return obj is FullPath other && Equals(other);
|
return obj is FullPath other && Equals(other);
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ namespace Wabbajack.Common
|
|||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Path { get; set; }
|
public string Path { get; set; } = string.Empty;
|
||||||
public IEnumerable<object> Arguments { get; set; }
|
public IEnumerable<object> Arguments { get; set; } = Enumerable.Empty<object>();
|
||||||
|
|
||||||
public bool LogError { get; set; } = true;
|
public bool LogError { get; set; } = true;
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ namespace Wabbajack.Common.StatusFeed.Errors
|
|||||||
{
|
{
|
||||||
private string _filename;
|
private string _filename;
|
||||||
private string _destination;
|
private string _destination;
|
||||||
public override string ShortDescription { get; }
|
public override string ShortDescription { get; } = string.Empty;
|
||||||
public override string ExtendedDescription { get; }
|
public override string ExtendedDescription { get; } = string.Empty;
|
||||||
|
|
||||||
public FileExtractionError(string filename, string destination)
|
public FileExtractionError(string filename, string destination)
|
||||||
{
|
{
|
||||||
|
@ -8,19 +8,19 @@ namespace Wabbajack.Common.StatusFeed.Errors
|
|||||||
{
|
{
|
||||||
public class GenericException : IException
|
public class GenericException : IException
|
||||||
{
|
{
|
||||||
public string ExtraMessage { get; }
|
public string ExtraMessage { get; } = string.Empty;
|
||||||
|
|
||||||
public DateTime Timestamp { get; } = DateTime.Now;
|
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 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;
|
Exception = exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ namespace Wabbajack.Common.StatusFeed
|
|||||||
private readonly string _extendedDescription;
|
private readonly string _extendedDescription;
|
||||||
public override string ExtendedDescription => _extendedDescription ?? ShortDescription;
|
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;
|
ShortDescription = short_description;
|
||||||
_extendedDescription = long_description;
|
_extendedDescription = long_description ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
@ -6,9 +6,9 @@ namespace Wabbajack.Common
|
|||||||
{
|
{
|
||||||
private string _message;
|
private string _message;
|
||||||
private Stream _inner;
|
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;
|
_queue = queue;
|
||||||
_inner = fs;
|
_inner = fs;
|
||||||
|
@ -10,21 +10,17 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
public class GOGGame : AStoreGame
|
public class GOGGame : AStoreGame
|
||||||
{
|
{
|
||||||
public override Game Game { get; internal set; }
|
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 override StoreType Type { get; internal set; } = StoreType.GOG;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GOGHandler : AStoreHandler
|
public class GOGHandler : AStoreHandler
|
||||||
{
|
{
|
||||||
public override List<AStoreGame> Games { get; set; }
|
|
||||||
public override StoreType Type { get; internal set; }
|
public override StoreType Type { get; internal set; }
|
||||||
|
|
||||||
private const string GOGRegKey = @"Software\GOG.com\Games";
|
private const string GOGRegKey = @"Software\GOG.com\Games";
|
||||||
private const string GOG64RegKey = @"Software\WOW6432Node\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()
|
public override bool Init()
|
||||||
{
|
{
|
||||||
@ -56,9 +52,11 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
|
|
||||||
public override bool LoadAllGames()
|
public override bool LoadAllGames()
|
||||||
{
|
{
|
||||||
if(Games == null)
|
if (GOGKey == null)
|
||||||
Games = new List<AStoreGame>();
|
{
|
||||||
|
Utils.Error("GOGHandler could not read from registry!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string[] keys = GOGKey.GetSubKeyNames();
|
string[] keys = GOGKey.GetSubKeyNames();
|
||||||
@ -86,7 +84,7 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gameName = gameNameValue.ToString();
|
var gameName = gameNameValue.ToString() ?? string.Empty;
|
||||||
|
|
||||||
var pathValue = subKey.GetValue("PATH");
|
var pathValue = subKey.GetValue("PATH");
|
||||||
if (pathValue == null)
|
if (pathValue == null)
|
||||||
@ -95,7 +93,7 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = pathValue.ToString();
|
var path = pathValue.ToString() ?? string.Empty;
|
||||||
|
|
||||||
var game = new GOGGame
|
var game = new GOGGame
|
||||||
{
|
{
|
||||||
|
@ -11,33 +11,29 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
public class SteamGame : AStoreGame
|
public class SteamGame : AStoreGame
|
||||||
{
|
{
|
||||||
public override Game Game { get; internal set; }
|
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 override StoreType Type { get; internal set; } = StoreType.STEAM;
|
||||||
|
|
||||||
public string Universe;
|
public string Universe = string.Empty;
|
||||||
|
|
||||||
public List<SteamWorkshopItem> WorkshopItems;
|
public readonly List<SteamWorkshopItem> WorkshopItems = new List<SteamWorkshopItem>();
|
||||||
public int WorkshopItemsSize;
|
public int WorkshopItemsSizeOnDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SteamWorkshopItem
|
public class SteamWorkshopItem
|
||||||
{
|
{
|
||||||
public SteamGame Game;
|
public SteamGame? Game;
|
||||||
public int ItemID;
|
public int ItemID;
|
||||||
public int Size;
|
public int Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SteamHandler : AStoreHandler
|
public class SteamHandler : AStoreHandler
|
||||||
{
|
{
|
||||||
public override List<AStoreGame> Games { get; set; }
|
|
||||||
public override StoreType Type { get; internal set; } = StoreType.STEAM;
|
public override StoreType Type { get; internal set; } = StoreType.STEAM;
|
||||||
|
|
||||||
private const string SteamRegKey = @"Software\Valve\Steam";
|
private const string SteamRegKey = @"Software\Valve\Steam";
|
||||||
|
|
||||||
public string SteamPath { get; set; }
|
public string SteamPath { get; set; } = string.Empty;
|
||||||
private List<string> SteamUniverses { get; set; }
|
private List<string>? SteamUniverses { get; set; }
|
||||||
|
|
||||||
private string SteamConfig => Path.Combine(SteamPath, "config", "config.vdf");
|
private string SteamConfig => Path.Combine(SteamPath, "config", "config.vdf");
|
||||||
|
|
||||||
@ -54,7 +50,7 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamPath = steamPathKey.ToString();
|
SteamPath = steamPathKey.ToString() ?? string.Empty;
|
||||||
if (string.IsNullOrWhiteSpace(SteamPath))
|
if (string.IsNullOrWhiteSpace(SteamPath))
|
||||||
{
|
{
|
||||||
Utils.Error(new StoreException("Path to the Steam Directory from registry is Null or Empty!"));
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadUniverses()
|
private List<string> LoadUniverses()
|
||||||
{
|
{
|
||||||
SteamUniverses = new List<string>();
|
var ret = new List<string>();
|
||||||
|
|
||||||
File.ReadAllLines(SteamConfig).Do(l =>
|
File.ReadAllLines(SteamConfig).Do(l =>
|
||||||
{
|
{
|
||||||
@ -101,21 +97,23 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamUniverses.Add(s);
|
ret.Add(s);
|
||||||
Utils.Log($"Steam Library found at {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
|
// Default path in the Steam folder isn't in the configs
|
||||||
if(Directory.Exists(Path.Combine(SteamPath, "steamapps")))
|
if (Directory.Exists(Path.Combine(SteamPath, "steamapps")))
|
||||||
SteamUniverses.Add(Path.Combine(SteamPath, "steamapps"));
|
ret.Add(Path.Combine(SteamPath, "steamapps"));
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool LoadAllGames()
|
public override bool LoadAllGames()
|
||||||
{
|
{
|
||||||
if(SteamUniverses == null)
|
if (SteamUniverses == null)
|
||||||
LoadUniverses();
|
SteamUniverses = LoadUniverses();
|
||||||
|
|
||||||
if (SteamUniverses.Count == 0)
|
if (SteamUniverses.Count == 0)
|
||||||
{
|
{
|
||||||
@ -123,9 +121,6 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Games == null)
|
|
||||||
Games = new List<AStoreGame>();
|
|
||||||
|
|
||||||
SteamUniverses.Do(u =>
|
SteamUniverses.Do(u =>
|
||||||
{
|
{
|
||||||
Utils.Log($"Searching for Steam Games in {u}");
|
Utils.Log($"Searching for Steam Games in {u}");
|
||||||
@ -188,9 +183,6 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
|
|
||||||
private static void LoadWorkshopItems(SteamGame game)
|
private static void LoadWorkshopItems(SteamGame game)
|
||||||
{
|
{
|
||||||
if(game.WorkshopItems == null)
|
|
||||||
game.WorkshopItems = new List<SteamWorkshopItem>();
|
|
||||||
|
|
||||||
var workshop = Path.Combine(game.Universe, "workshop");
|
var workshop = Path.Combine(game.Universe, "workshop");
|
||||||
if (!Directory.Exists(workshop))
|
if (!Directory.Exists(workshop))
|
||||||
return;
|
return;
|
||||||
@ -210,13 +202,13 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
var bracketStart = 0;
|
var bracketStart = 0;
|
||||||
var bracketEnd = 0;
|
var bracketEnd = 0;
|
||||||
|
|
||||||
var currentItem = new SteamWorkshopItem();
|
SteamWorkshopItem? currentItem = new SteamWorkshopItem();
|
||||||
|
|
||||||
lines.Do(l =>
|
lines.Do(l =>
|
||||||
{
|
{
|
||||||
if (end)
|
if (end)
|
||||||
return;
|
return;
|
||||||
if(currentItem == null)
|
if (currentItem == null)
|
||||||
currentItem = new SteamWorkshopItem();
|
currentItem = new SteamWorkshopItem();
|
||||||
|
|
||||||
var currentLine = lines.IndexOf(l);
|
var currentLine = lines.IndexOf(l);
|
||||||
@ -239,7 +231,7 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
if (!int.TryParse(GetVdfValue(l), out var sizeOnDisk))
|
if (!int.TryParse(GetVdfValue(l), out var sizeOnDisk))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
game.WorkshopItemsSize += sizeOnDisk;
|
game.WorkshopItemsSizeOnDisk += sizeOnDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l.ContainsCaseInsensitive("\"WorkshopItemsInstalled\""))
|
if (l.ContainsCaseInsensitive("\"WorkshopItemsInstalled\""))
|
||||||
|
@ -61,15 +61,15 @@ namespace Wabbajack.Common.StoreHandlers
|
|||||||
public abstract class AStoreGame
|
public abstract class AStoreGame
|
||||||
{
|
{
|
||||||
public abstract Game Game { get; internal set; }
|
public abstract Game Game { get; internal set; }
|
||||||
public abstract string Name { get; internal set; }
|
public virtual string Name { get; internal set; } = string.Empty;
|
||||||
public abstract AbsolutePath Path { get; internal set; }
|
public virtual AbsolutePath Path { get; internal set; }
|
||||||
public abstract int ID { get; internal set; }
|
public virtual int ID { get; internal set; }
|
||||||
public abstract StoreType Type { get; internal set; }
|
public abstract StoreType Type { get; internal set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class AStoreHandler
|
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; }
|
public abstract StoreType Type { get; internal set; }
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace Wabbajack.Common
|
|||||||
{
|
{
|
||||||
public class AsyncLock
|
public class AsyncLock
|
||||||
{
|
{
|
||||||
private SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
public async Task<IDisposable> Wait()
|
public async Task<IDisposable> Wait()
|
||||||
{
|
{
|
||||||
|
@ -43,9 +43,9 @@ namespace Wabbajack.Common
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_allocated.Do(s => s.Dispose());
|
_allocated.Do(s => s.Dispose());
|
||||||
_mmap?.Dispose();
|
_mmap.Dispose();
|
||||||
_fileStream?.Dispose();
|
_fileStream.Dispose();
|
||||||
_file?.Dispose();
|
_file.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ namespace Wabbajack.Common
|
|||||||
return new Percent(percent, check: false);
|
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;
|
if (!(obj is Percent rhs)) return false;
|
||||||
return Equals(rhs);
|
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)
|
if (obj is Percent rhs)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,6 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AlphaPath = Alphaleonis.Win32.Filesystem.Path;
|
using AlphaPath = Alphaleonis.Win32.Filesystem.Path;
|
||||||
|
|
||||||
|
|
||||||
namespace Wabbajack.Common
|
namespace Wabbajack.Common
|
||||||
{
|
{
|
||||||
public class TempFile : IDisposable
|
public class TempFile : IDisposable
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.HashFunction.xxHash;
|
using System.Data.HashFunction.xxHash;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@ -132,12 +133,12 @@ namespace Wabbajack.Common
|
|||||||
Log(errMessage);
|
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));
|
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);
|
Error(ex, extraMessage);
|
||||||
throw ex;
|
throw ex;
|
||||||
@ -231,29 +232,21 @@ namespace Wabbajack.Common
|
|||||||
Status(status, Percent.FactoryPutInRange(totalRead, maxSize));
|
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();
|
var config = new xxHashConfig();
|
||||||
hash.HashSizeInBits = 64;
|
config.HashSizeInBits = 64;
|
||||||
hash.Seed = 0x42;
|
using (var f = new StatusFileStream(fs, $"Hashing memory stream"))
|
||||||
using (var fs = new MemoryStream(data))
|
|
||||||
{
|
{
|
||||||
var config = new xxHashConfig();
|
var value = xxHashFactory.Instance.Create(config).ComputeHash(f);
|
||||||
config.HashSizeInBits = 64;
|
return value.AsBase64String();
|
||||||
using (var f = new StatusFileStream(fs, $"Hashing memory stream"))
|
|
||||||
{
|
|
||||||
var value = xxHashFactory.Instance.Create(config).ComputeHash(f);
|
|
||||||
return value.AsBase64String();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
if (nullOnIOError) return null;
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -673,7 +666,9 @@ namespace Wabbajack.Common
|
|||||||
return a[a.Length - 1];
|
return a[a.Length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[return: MaybeNull]
|
||||||
public static V GetOrDefault<K, V>(this IDictionary<K, V> dict, K key)
|
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;
|
if (dict.TryGetValue(key, out var v)) return v;
|
||||||
return default;
|
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");
|
var patchName = Consts.PatchCacheFolder.Combine($"{foundHash.ToHex()}_{fileHash.ToHex()}.patch");
|
||||||
if (patchName.Exists)
|
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)
|
public static IEnumerable<T> ButLast<T>(this IEnumerable<T> coll)
|
||||||
{
|
{
|
||||||
var lst = coll.ToList();
|
var lst = coll.ToList();
|
||||||
@ -1097,7 +1081,7 @@ namespace Wabbajack.Common
|
|||||||
public class NexusErrorResponse
|
public class NexusErrorResponse
|
||||||
{
|
{
|
||||||
public int code;
|
public int code;
|
||||||
public string message;
|
public string message = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="7z.dll.gz" />
|
<None Remove="7z.dll.gz" />
|
||||||
|
@ -25,7 +25,7 @@ namespace Wabbajack.Common
|
|||||||
|
|
||||||
public static bool WorkerThread => AsyncLocalCurrentQueue.Value != null;
|
public static bool WorkerThread => AsyncLocalCurrentQueue.Value != null;
|
||||||
public bool IsWorkerThread => WorkerThread;
|
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>();
|
private readonly Subject<CPUStatus> _Status = new Subject<CPUStatus>();
|
||||||
public IObservable<CPUStatus> Status => _Status;
|
public IObservable<CPUStatus> Status => _Status;
|
||||||
@ -194,7 +194,7 @@ namespace Wabbajack.Common
|
|||||||
public class CPUStatus
|
public class CPUStatus
|
||||||
{
|
{
|
||||||
public Percent ProgressPercent { get; internal set; }
|
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 int ID { get; internal set; }
|
||||||
public bool IsWorking { get; internal set; }
|
public bool IsWorking { get; internal set; }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user