using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; namespace Content.Shared.Database; /// /// Represents a raw HWID value together with its type. /// [Serializable] public sealed class ImmutableTypedHwid(ImmutableArray hwid, HwidType type) { public readonly ImmutableArray Hwid = hwid; public readonly HwidType Type = type; public override string ToString() { var b64 = Convert.ToBase64String(Hwid.AsSpan()); return Type == HwidType.Modern ? $"V2-{b64}" : b64; } public static bool TryParse(string value, [NotNullWhen(true)] out ImmutableTypedHwid? hwid) { var type = HwidType.Legacy; if (value.StartsWith("V2-", StringComparison.Ordinal)) { value = value["V2-".Length..]; type = HwidType.Modern; } var array = new byte[GetBase64ByteLength(value)]; if (!Convert.TryFromBase64String(value, array, out _)) { hwid = null; return false; } // ReSharper disable once UseCollectionExpression // Do not use collection expression, C# compiler is weird and it fails sandbox. hwid = new ImmutableTypedHwid(ImmutableArray.Create(array), type); return true; } private static int GetBase64ByteLength(string value) { // Why is .NET like this man wtf. return 3 * (value.Length / 4) - value.TakeLast(2).Count(c => c == '='); } } /// /// Represents different types of HWIDs as exposed by the engine. /// public enum HwidType { /// /// The legacy HWID system. Should only be used for checking old existing database bans. /// Legacy = 0, /// /// The modern HWID system. /// Modern = 1, }