v1.3.0.1 (Epic Store release)

This commit is contained in:
Regalis11
2024-03-28 18:34:33 +02:00
parent 81ca8637be
commit 3791670c42
269 changed files with 13160 additions and 2966 deletions
@@ -1,11 +1,11 @@
using System;
using System.Linq;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("WindowsTest"),
InternalsVisibleTo("MacTest"),
InternalsVisibleTo("LinuxTest")]
public static class AssemblyInfo
{
public static readonly string GitRevision;
@@ -13,6 +13,38 @@ public static class AssemblyInfo
public static readonly string ProjectDir;
public static readonly string BuildString;
public enum Platform
{
Windows,
MacOS,
Linux
}
public enum Configuration
{
Release,
Unstable,
Debug
}
#if WINDOWS
public const Platform CurrentPlatform = Platform.Windows;
#elif OSX
public const Platform CurrentPlatform = Platform.MacOS;
#elif LINUX
public const Platform CurrentPlatform = Platform.Linux;
#else
#error Unknown platform
#endif
#if DEBUG
public const Configuration CurrentConfiguration = Configuration.Debug;
#elif UNSTABLE
public const Configuration CurrentConfiguration = Configuration.Unstable;
#else
public const Configuration CurrentConfiguration = Configuration.Release;
#endif
static AssemblyInfo()
{
var asm = typeof(AssemblyInfo).Assembly;
@@ -27,22 +59,7 @@ public static class AssemblyInfo
string[] dirSplit = ProjectDir.Split('/', '\\');
ProjectDir = string.Join(ProjectDir.Contains('/') ? '/' : '\\', dirSplit.Take(dirSplit.Length - 2));
BuildString = "Unknown";
#if WINDOWS
BuildString = "Windows";
#elif OSX
BuildString = "Mac";
#elif LINUX
BuildString = "Linux";
#endif
#if DEBUG
BuildString = "Debug" + BuildString;
#elif UNSTABLE
BuildString = "Unstable" + BuildString;
#else
BuildString = "Release" + BuildString;
#endif
BuildString = $"{CurrentConfiguration}{CurrentPlatform}";
}
public static string CleanupStackTrace(this string stackTrace)
@@ -1,124 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
public class CollectionConcat<T> : ICollection<T>
{
protected readonly IEnumerable<T> enumerableA;
protected readonly IEnumerable<T> enumerableB;
public CollectionConcat(IEnumerable<T> a, IEnumerable<T> b)
{
enumerableA = a; enumerableB = b;
}
public int Count => enumerableA.Count()+enumerableB.Count();
public bool IsReadOnly => true;
public void Add(T item) => throw new InvalidOperationException();
public void Clear() => throw new InvalidOperationException();
public bool Remove(T item) => throw new InvalidOperationException();
public bool Contains(T item) => enumerableA.Contains(item) || enumerableB.Contains(item);
public void CopyTo(T[] array, int arrayIndex)
{
void performCopy(IEnumerable<T> enumerable)
{
if (enumerable is ICollection<T> collection)
{
collection.CopyTo(array, arrayIndex);
arrayIndex += collection.Count;
}
else
{
foreach (var item in enumerable)
{
array[arrayIndex] = item;
arrayIndex++;
}
}
}
performCopy(enumerableA);
performCopy(enumerableB);
}
public IEnumerator<T> GetEnumerator()
{
foreach (T item in enumerableA) { yield return item; }
foreach (T item in enumerableB) { yield return item; }
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class ListConcat<T> : CollectionConcat<T>, IList<T>, IReadOnlyList<T>
{
public ListConcat(IEnumerable<T> a, IEnumerable<T> b) : base(a, b) { }
public int IndexOf(T item)
{
int aCount = 0;
if (enumerableA is IList<T> listA)
{
int index = listA.IndexOf(item);
if (index >= 0) { return index; }
aCount = listA.Count;
}
else
{
foreach (var a in enumerableA)
{
if (object.Equals(item, a)) { return aCount; }
aCount++;
}
}
if (enumerableB is IList<T> listB)
{
int index = listB.IndexOf(item);
if (index >= 0) { return index + aCount; }
}
else
{
foreach (var b in enumerableB)
{
if (object.Equals(item, b)) { return aCount; }
aCount++;
}
}
return -1;
}
public void Insert(int index, T item)
{
throw new InvalidOperationException();
}
public void RemoveAt(int index)
{
throw new InvalidOperationException();
}
public T this[int index]
{
get
{
int aCount = enumerableA.Count();
return index < aCount ? enumerableA.ElementAt(index) : enumerableB.ElementAt(index - aCount);
}
set
{
throw new InvalidOperationException();
}
}
}
}
@@ -1,105 +0,0 @@
#nullable enable
using System;
namespace Barotrauma
{
public abstract class Either<T, U> where T : notnull where U : notnull
{
public static implicit operator Either<T, U>(T t) => new EitherT<T, U>(t);
public static implicit operator Either<T, U>(U u) => new EitherU<T, U>(u);
public static explicit operator T(Either<T, U> e) => e.TryGet(out T t) ? t : throw new InvalidCastException($"Contained object is not of type {typeof(T).Name}");
public static explicit operator U(Either<T, U> e) => e.TryGet(out U u) ? u : throw new InvalidCastException($"Contained object is not of type {typeof(U).Name}");
public abstract bool TryGet(out T t);
public abstract bool TryGet(out U u);
public abstract bool TryCast<V>(out V v);
public abstract override string? ToString();
public abstract override bool Equals(object? obj);
public abstract override int GetHashCode();
public static bool operator ==(Either<T, U>? a, Either<T, U>? b)
=> a is null ? b is null : a.Equals(b);
public static bool operator !=(Either<T, U>? a, Either<T, U>? b)
=> !(a == b);
}
public sealed class EitherT<T, U> : Either<T, U> where T : notnull where U : notnull
{
public readonly T Value;
public EitherT(T value) { Value = value; }
public override string? ToString()
=> $"Either<{typeof(T).NameWithGenerics()}, {typeof(U).NameWithGenerics()}>({Value}: {typeof(T).NameWithGenerics()})";
public override bool TryGet(out T t) { t = Value; return true; }
public override bool TryGet(out U u) { u = default!; return false; }
public override bool TryCast<V>(out V v)
{
if (Value is V result)
{
v = result;
return true;
}
else
{
v = default!;
return false;
}
}
public override bool Equals(object? obj)
=> obj switch
{
EitherT<T, U> other => Value.Equals(other.Value),
T value => Value.Equals(value),
_ => false
};
public override int GetHashCode() => Value.GetHashCode();
}
public sealed class EitherU<T, U> : Either<T, U> where T : notnull where U : notnull
{
public readonly U Value;
public EitherU(U value) { Value = value; }
public override string? ToString()
=> $"Either<{typeof(T).NameWithGenerics()}, {typeof(U).NameWithGenerics()}>({Value}: {typeof(U).NameWithGenerics()})";
public override bool TryGet(out T t) { t = default!; return false; }
public override bool TryGet(out U u) { u = Value; return true; }
public override bool TryCast<V>(out V v)
{
if (Value is V result)
{
v = result;
return true;
}
else
{
v = default!;
return false;
}
}
public override bool Equals(object? obj)
=> obj switch
{
EitherU<T, U> other => Value.Equals(other.Value),
U value => Value.Equals(value),
_ => false
};
public override int GetHashCode() => Value.GetHashCode();
}
}
File diff suppressed because it is too large Load Diff
@@ -44,26 +44,10 @@ namespace Barotrauma
}
private static string ByteRepresentationToStringRepresentation(byte[] byteHash)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteHash.Length; i++)
{
sb.Append(byteHash[i].ToString("X2"));
}
return sb.ToString();
}
=> ToolBoxCore.ByteArrayToHexString(byteHash);
private static byte[] StringRepresentationToByteRepresentation(string strHash)
{
var byteRepresentation = new byte[strHash.Length / 2];
for (int i = 0; i < byteRepresentation.Length; i++)
{
byteRepresentation[i] = Convert.ToByte(strHash.Substring(i * 2, 2), 16);
}
return byteRepresentation;
}
=> ToolBoxCore.HexStringToByteArray(strHash);
public static string GetShortHash(string fullHash)
{
@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
namespace Barotrauma
{
internal sealed class NamedEvent<T> : IDisposable
{
private readonly Dictionary<Identifier, Action<T>> events = new Dictionary<Identifier, Action<T>>();
public void Register(Identifier identifier, Action<T> action)
{
if (HasEvent(identifier))
{
throw new ArgumentException($"Event with the identifier \"{identifier}\" has already been registered.", nameof(identifier));
}
events.Add(identifier, action);
}
public void RegisterOverwriteExisting(Identifier identifier, Action<T> action)
{
if (HasEvent(identifier))
{
Deregister(identifier);
}
Register(identifier, action);
}
public void Deregister(Identifier identifier)
{
events.Remove(identifier);
}
public void TryDeregister(Identifier identifier)
{
if (!HasEvent(identifier)) { return; }
Deregister(identifier);
}
public bool HasEvent(Identifier identifier) => events.ContainsKey(identifier);
public void Invoke(T data)
{
foreach (var (_, action) in events)
{
action?.Invoke(data);
}
}
public void Dispose()
{
events.Clear();
}
}
}
@@ -1,125 +0,0 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
namespace Barotrauma
{
public readonly struct Option<T> where T : notnull
{
private readonly bool hasValue;
private readonly T? value;
private Option(bool hasValue, T? value)
{
this.hasValue = hasValue;
this.value = value;
}
public bool IsSome() => hasValue;
public bool IsNone() => !IsSome();
public bool TryUnwrap<T1>([NotNullWhen(returnValue: true)] out T1? outValue) where T1 : T
{
bool hasValueOfGivenType = false;
outValue = default;
if (hasValue && value is T1 t1)
{
hasValueOfGivenType = true;
outValue = t1;
}
return hasValueOfGivenType;
}
public bool TryUnwrap([NotNullWhen(returnValue: true)] out T? outValue)
=> TryUnwrap<T>(out outValue);
public Option<TType> Select<TType>(Func<T, TType> selector) where TType : notnull
=> TryUnwrap(out T? selfValue) ? Option.Some(selector(selfValue)) : Option.None;
public Option<TType> Bind<TType>(Func<T, Option<TType>> binder) where TType : notnull
=> TryUnwrap(out T? selfValue) ? binder(selfValue) : Option.None;
public T Match(Func<T, T> some, Func<T> none)
=> TryUnwrap(out T? selfValue) ? some(selfValue) : none();
public void Match(Action<T> some, Action none)
{
if (TryUnwrap(out T? selfValue))
{
some(selfValue);
return;
}
none();
}
public T Fallback(T fallback)
=> TryUnwrap(out var v) ? v : fallback;
public Option<T> Fallback(Option<T> fallback)
=> IsSome() ? this : fallback;
public static Option<T> Some(T value)
=> typeof(T) switch
{
var t when t == typeof(bool)
=> throw new Exception("Option type rejects booleans"),
{IsConstructedGenericType: true} t when t.GetGenericTypeDefinition() == typeof(Option<>)
=> throw new Exception("Option type rejects nested Option"),
{IsConstructedGenericType: true} t when t.GetGenericTypeDefinition() == typeof(Nullable<>)
=> throw new Exception("Option type rejects Nullable"),
_
=> new Option<T>(hasValue: true, value: value ?? throw new Exception("Option type rejects null"))
};
public override bool Equals(object? obj)
=> obj switch
{
Option<T> otherOption when otherOption.IsNone()
=> IsNone(),
Option<T> otherOption when otherOption.TryUnwrap(out var otherValue)
=> ValueEquals(otherValue),
T otherValue
=> ValueEquals(otherValue),
_
=> false
};
public bool ValueEquals(T otherValue)
=> TryUnwrap(out T? selfValue) && selfValue.Equals(otherValue);
public override int GetHashCode()
=> TryUnwrap(out T? selfValue) ? selfValue.GetHashCode() : 0;
public static bool operator ==(Option<T> a, Option<T> b)
=> a.Equals(b);
public static bool operator !=(Option<T> a, Option<T> b)
=> !(a == b);
public static Option<T> None()
=> default;
public static implicit operator Option<T>(in Option.UnspecifiedNone _)
=> None();
public override string ToString()
=> TryUnwrap(out var selfValue)
? $"Some<{typeof(T).Name}>({selfValue})"
: $"None<{typeof(T).Name}>";
}
public static class Option
{
public static Option<T> Some<T>(T value) where T : notnull
=> Option<T>.Some(value);
public static UnspecifiedNone None
=> default;
public readonly ref struct UnspecifiedNone
{
}
}
}
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -30,6 +31,7 @@ namespace Barotrauma
public static Random GetRNG(RandSync randSync)
{
CheckRandThreadSafety(randSync);
return randSync == RandSync.Unsynced ? localRandom : syncedRandom[randSync];
}
@@ -70,16 +72,10 @@ namespace Barotrauma
}
public static float Range(float minimum, float maximum, RandSync sync=RandSync.Unsynced)
{
CheckRandThreadSafety(sync);
return (float)(sync == RandSync.Unsynced ? localRandom : (syncedRandom[sync])).NextDouble() * (maximum - minimum) + minimum;
}
=> GetRNG(sync).Range(minimum, maximum);
public static double Range(double minimum, double maximum, RandSync sync = RandSync.Unsynced)
{
CheckRandThreadSafety(sync);
return (sync == RandSync.Unsynced ? localRandom : (syncedRandom[sync])).NextDouble() * (maximum - minimum) + minimum;
}
=> GetRNG(sync).Range(minimum, maximum);
/// <summary>
/// Min inclusive, Max exclusive!
@@ -1,51 +0,0 @@
#nullable enable
using System;
namespace Barotrauma
{
/// <summary>
/// An inclusive range, i.e. [Start, End] where Start <= End
/// </summary>
public struct Range<T> where T : notnull, IComparable<T>
{
private T start; private T end;
public T Start
{
get { return start; }
set
{
start = value;
VerifyStartLessThanEnd();
}
}
public T End
{
get { return end; }
set
{
end = value;
VerifyEndGreaterThanStart();
}
}
public readonly bool Contains(in T v)
=> start.CompareTo(v) <= 0 && end.CompareTo(v) >= 0;
private void VerifyStartLessThanEnd()
{
if (start.CompareTo(end) > 0) { throw new InvalidOperationException($"Range<{typeof(T).Name}>.Start set to a value greater than End ({start} > {end})"); }
}
private void VerifyEndGreaterThanStart()
{
if (end.CompareTo(start) < 0) { throw new InvalidOperationException($"Range<{typeof(T).Name}>.End set to a value less than Start ({end} < {start})"); }
}
public Range(T start, T end)
{
this.start = start; this.end = end;
VerifyEndGreaterThanStart();
}
}
}
@@ -1,84 +0,0 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
namespace Barotrauma
{
public static class ReflectionUtils
{
private static readonly Dictionary<Assembly, ImmutableArray<Type>> cachedNonAbstractTypes
= new Dictionary<Assembly, ImmutableArray<Type>>();
private static readonly Dictionary<Assembly, Dictionary<Type, ImmutableArray<Type>>> cachedDerivedNonAbstract
= new Dictionary<Assembly, Dictionary<Type, ImmutableArray<Type>>>();
public static IEnumerable<Type> GetDerivedNonAbstract<T>()
{
Type t = typeof(T);
Assembly assembly = typeof(T).Assembly;
if (!cachedNonAbstractTypes.ContainsKey(assembly))
{
cachedNonAbstractTypes[assembly] = assembly.GetTypes()
.Where(t => !t.IsAbstract).ToImmutableArray();
cachedDerivedNonAbstract[assembly] = new Dictionary<Type, ImmutableArray<Type>>();
}
if (cachedDerivedNonAbstract[assembly].TryGetValue(t, out var cachedArray))
{
return cachedArray;
}
var newArray = cachedNonAbstractTypes[assembly].Where(t2 => t2.IsSubclassOf(t)).ToImmutableArray();
cachedDerivedNonAbstract[assembly].Add(t, newArray);
return newArray;
}
public static Option<TBase> ParseDerived<TBase, TInput>(TInput input) where TInput : notnull where TBase : notnull
{
static Option<TBase> none() => Option<TBase>.None();
var derivedTypes = GetDerivedNonAbstract<TBase>();
Option<TBase> parseOfType(Type t)
{
//every TBase type is expected to have a method with the following signature:
// public static Option<T> Parse(TInput str)
var parseFunc = t.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static);
if (parseFunc is null) { return none(); }
var parameters = parseFunc.GetParameters();
if (parameters.Length != 1) { return none(); }
var returnType = parseFunc.ReturnType;
if (!returnType.IsConstructedGenericType) { return none(); }
if (returnType.GetGenericTypeDefinition() != typeof(Option<>)) { return none(); }
if (returnType.GenericTypeArguments[0] != t) { return none(); }
//some hacky business to convert from Option<T2> to Option<TBase> when we only know T2 at runtime
static Option<TBase> convert<T2>(Option<T2> option) where T2 : TBase
=> option.Select(v => (TBase)v);
Func<Option<TBase>, Option<TBase>> f = convert;
var genericArgs = f.Method.GetGenericArguments();
genericArgs[^1] = t;
var constructedConverter =
f.Method.GetGenericMethodDefinition().MakeGenericMethod(genericArgs);
return constructedConverter.Invoke(null, new[] { parseFunc.Invoke(null, new object[] { input }) })
as Option<TBase>? ?? none();
}
return derivedTypes.Select(parseOfType).FirstOrDefault(t => t.IsSome());
}
public static string NameWithGenerics(this Type t)
{
if (!t.IsGenericType) { return t.Name; }
string result = t.Name[..t.Name.IndexOf('`')];
result += $"<{string.Join(", ", t.GetGenericArguments().Select(NameWithGenerics))}>";
return result;
}
}
}
@@ -1,85 +0,0 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
namespace Barotrauma
{
public abstract class Result<T, TError>
where T: notnull
where TError: notnull
{
public abstract bool IsSuccess { get; }
public bool IsFailure => !IsSuccess;
public static Result<T, TError> Success(T value)
=> new Success<T, TError>(value);
public static Result<T, TError> Failure(TError error)
=> new Failure<T, TError>(error);
public abstract bool TryUnwrapSuccess([MaybeNullWhen(returnValue: false)] out T value);
public abstract bool TryUnwrapFailure([MaybeNullWhen(returnValue: false)] out TError value);
public abstract override string? ToString();
public static (Func<T, Result<T, TError>> Success, Func<TError, Result<T, TError>> Failure) GetFactoryMethods()
=> (Success, Failure);
}
public sealed class Success<T, TError> : Result<T, TError>
where T: notnull
where TError: notnull
{
public readonly T Value;
public override bool IsSuccess => true;
public override bool TryUnwrapSuccess([MaybeNullWhen(returnValue: false)] out T value)
{
value = Value;
return true;
}
public override bool TryUnwrapFailure([MaybeNullWhen(returnValue: false)] out TError value)
{
value = default;
return false;
}
public override string ToString()
=> $"Success<{typeof(T).NameWithGenerics()}, {typeof(TError).NameWithGenerics()}>({Value})";
public Success(T value)
{
Value = value;
}
}
public sealed class Failure<T, TError> : Result<T, TError>
where T: notnull
where TError: notnull
{
public readonly TError Error;
public override bool IsSuccess => false;
public override bool TryUnwrapSuccess([MaybeNullWhen(returnValue: false)] out T value)
{
value = default;
return false;
}
public override bool TryUnwrapFailure([MaybeNullWhen(returnValue: false)] out TError value)
{
value = Error;
return true;
}
public override string ToString()
=> $"Failure<{typeof(T).NameWithGenerics()}, {typeof(TError).NameWithGenerics()}>({Error})";
public Failure(TError error)
{
Error = error;
}
}
}
@@ -1,20 +1,10 @@
using System.Threading.Tasks;
#nullable enable
using System.Threading.Tasks;
namespace Barotrauma
{
static class TaskExtensions
public static class TaskExtensions
{
public static bool TryGetResult<T>(this Task task, out T result)
{
if (task is Task<T> { IsCompletedSuccessfully: true } castTask)
{
result = castTask.Result;
return true;
}
result = default;
return false;
}
public static async Task<T> WaitForLoadingScreen<T>(this Task<T> task)
{
var result = await task;
@@ -27,4 +17,4 @@ namespace Barotrauma
return result;
}
}
}
}
@@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Barotrauma
{
public static class TaskPool
{
const int MaxTasks = 5000;
private struct TaskAction
{
public string Name;
public Task Task;
public Action<Task, object> OnCompletion;
public object UserData;
}
private static readonly List<TaskAction> taskActions = new List<TaskAction>();
public static void ListTasks()
{
lock (taskActions)
{
DebugConsole.NewMessage($"Task count: {taskActions.Count}");
for (int i = 0; i < taskActions.Count; i++)
{
DebugConsole.NewMessage($" -{i}: {taskActions[i].Name}, {taskActions[i].Task.Status}");
}
}
}
public static bool IsTaskRunning(string name)
{
lock (taskActions)
{
return taskActions.Any(t => t.Name == name);
}
}
private static void AddInternal(string name, Task task, Action<Task, object> onCompletion, object userdata, bool addIfFound = true)
{
lock (taskActions)
{
if (!addIfFound)
{
if (taskActions.Any(t => t.Name == name)) { return; }
}
if (taskActions.Count >= MaxTasks)
{
throw new Exception(
"Too many tasks in the TaskPool:\n" + string.Join('\n', taskActions.Select(ta => ta.Name))
);
}
taskActions.Add(new TaskAction() { Name = name, Task = task, OnCompletion = onCompletion, UserData = userdata });
DebugConsole.Log($"New task: {name} ({taskActions.Count}/{MaxTasks})");
}
}
public static void Add(string name, Task task, Action<Task> onCompletion)
{
AddInternal(name, task, (Task t, object obj) => { onCompletion?.Invoke(t); }, null);
}
public static void AddIfNotFound(string name, Task task, Action<Task> onCompletion)
{
AddInternal(name, task, (Task t, object obj) => { onCompletion?.Invoke(t); }, null, addIfFound: false);
}
public static void Add<U>(string name, Task task, U userdata, Action<Task, U> onCompletion) where U : class
{
AddInternal(name, task, (Task t, object obj) => { onCompletion?.Invoke(t, (U)obj); }, userdata);
}
public static void Update()
{
lock (taskActions)
{
for (int i = 0; i < taskActions.Count; i++)
{
if (taskActions[i].Task.IsCompleted)
{
taskActions[i].OnCompletion?.Invoke(taskActions[i].Task, taskActions[i].UserData);
DebugConsole.Log($"Task {taskActions[i].Name} completed ({taskActions.Count-1}/{MaxTasks})");
taskActions.RemoveAt(i);
i--;
}
}
}
}
public static void PrintTaskExceptions(Task task, string msg)
{
DebugConsole.ThrowError(msg);
foreach (Exception e in task.Exception.InnerExceptions)
{
DebugConsole.ThrowError(e.Message + "\n" + e.StackTrace.CleanupStackTrace());
}
}
}
}
@@ -1,34 +0,0 @@
using System.Threading;
namespace Barotrauma.Threading
{
internal readonly ref struct ReadLock
{
private readonly ReaderWriterLockSlim rwl;
public ReadLock(ReaderWriterLockSlim rwl)
{
this.rwl = rwl;
rwl.EnterReadLock();
}
public void Dispose()
{
rwl.ExitReadLock();
}
}
internal readonly ref struct WriteLock
{
private readonly ReaderWriterLockSlim rwl;
public WriteLock(ReaderWriterLockSlim rwl)
{
this.rwl = rwl;
rwl.EnterWriteLock();
}
public void Dispose()
{
rwl.ExitWriteLock();
}
}
}
@@ -199,38 +199,6 @@ namespace Barotrauma
return inputType;
}
/// <summary>
/// Convert a HSV value into a RGB value.
/// </summary>
/// <param name="hue">Value between 0 and 360</param>
/// <param name="saturation">Value between 0 and 1</param>
/// <param name="value">Value between 0 and 1</param>
/// <see href="https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB">Reference</see>
/// <returns></returns>
public static Color HSVToRGB(float hue, float saturation, float value)
{
float c = value * saturation;
float h = Math.Clamp(hue, 0, 360) / 60f;
float x = c * (1 - Math.Abs(h % 2 - 1));
float r = 0,
g = 0,
b = 0;
if (0 <= h && h <= 1) { r = c; g = x; b = 0; }
else if (1 < h && h <= 2) { r = x; g = c; b = 0; }
else if (2 < h && h <= 3) { r = 0; g = c; b = x; }
else if (3 < h && h <= 4) { r = 0; g = x; b = c; }
else if (4 < h && h <= 5) { r = x; g = 0; b = c; }
else if (5 < h && h <= 6) { r = c; g = 0; b = x; }
float m = value - c;
return new Color(r + m, g + m, b + m);
}
/// <summary>
/// Returns either a green [x] or a red [o]
/// </summary>
@@ -459,24 +427,6 @@ namespace Barotrauma
return default;
}
public static UInt32 IdentifierToUint32Hash(Identifier id, MD5 md5)
=> StringToUInt32Hash(id.Value.ToLowerInvariant(), md5);
public static UInt32 StringToUInt32Hash(string str, MD5 md5)
{
//calculate key based on MD5 hash instead of string.GetHashCode
//to ensure consistent results across platforms
byte[] inputBytes = Encoding.UTF8.GetBytes(str);
byte[] hash = md5.ComputeHash(inputBytes);
UInt32 key = (UInt32)((str.Length & 0xff) << 24); //could use more of the hash here instead?
key |= (UInt32)(hash[hash.Length - 3] << 16);
key |= (UInt32)(hash[hash.Length - 2] << 8);
key |= (UInt32)(hash[hash.Length - 1]);
return key;
}
/// <summary>
/// Returns a new instance of the class with all properties and fields copied.
/// </summary>
@@ -542,14 +492,6 @@ namespace Barotrauma
}
}
public static string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
public static string EscapeCharacters(string str)
{
return str.Replace("\\", "\\\\").Replace("\"", "\\\"");
@@ -692,13 +634,6 @@ namespace Barotrauma
return new Rectangle(topLeft, size);
}
public static Exception GetInnermost(this Exception e)
{
while (e.InnerException != null) { e = e.InnerException; }
return e;
}
public static void ThrowIfNull<T>([NotNull] T o)
{
if (o is null) { throw new ArgumentNullException(); }