/* Copyright (c) 2026-present miku-666, MayNL * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ using System; using System.Collections.Specialized; using System.Text.RegularExpressions; namespace PckStudio.Core.Skin { /// /// Represents a SkinBOX ArmorFlags value where flags can be set /// public class SkinArmorFlags : ICloneable, IEquatable, IEquatable { public static readonly SkinArmorFlags Empty = new SkinArmorFlags(0); public static readonly SkinArmorFlags HeadArmor = new SkinArmorFlags(1); public static readonly SkinArmorFlags ChestplateAndArmArmor = new SkinArmorFlags(2); public static readonly SkinArmorFlags Leggings = new SkinArmorFlags(4); public static readonly SkinArmorFlags Belt = new SkinArmorFlags(6); public static readonly SkinArmorFlags Boots = new SkinArmorFlags(8); public static readonly SkinArmorFlags Socks = new SkinArmorFlags(12); private BitVector32 _flags; private static readonly Regex _validator = new Regex(@"^(0|[1-9]|1[0-6])$", RegexOptions.CultureInvariant); public SkinArmorFlags(SkinArmorFlagsMask mask) : this((int)mask) { } public SkinArmorFlags(int mask) { _flags = new BitVector32(mask); } public override string ToString() => _flags.Data.ToString(); // decimal instead of hexadecimal like the other bitfields in the game public static bool IsValidArmorFlags(string gameFlags) { return !string.IsNullOrWhiteSpace(gameFlags) && _validator.IsMatch(gameFlags); } public static SkinArmorFlags FromString(string value) => IsValidArmorFlags(value) ? new SkinArmorFlags(Convert.ToInt32(value)) : Empty; public static SkinArmorFlags operator |(SkinArmorFlags @this, SkinArmorFlags other) => new SkinArmorFlags(@this._flags.Data | other._flags.Data); public static SkinArmorFlags operator |(SkinArmorFlags @this, SkinArmorFlagsMask mask) => new SkinArmorFlags(@this._flags.Data | (int)mask); public static SkinArmorFlags operator &(SkinArmorFlags @this, SkinArmorFlagsMask mask) => new SkinArmorFlags(@this._flags.Data & (int)mask); public static SkinArmorFlags FromValue(int value) => new SkinArmorFlags(value); public int ToValue() => _flags.Data; public static implicit operator SkinArmorFlags(SkinArmorFlagsMask mask) => new SkinArmorFlags(mask); public static bool operator ==(SkinArmorFlags @this, SkinArmorFlagsMask mask) => @this.Equals(mask); public static bool operator !=(SkinArmorFlags @this, SkinArmorFlagsMask mask) => !@this.Equals(mask); public static bool operator ==(SkinArmorFlags @this, SkinArmorFlags other) => @this.Equals(other); public static bool operator !=(SkinArmorFlags @this, SkinArmorFlags other) => !@this.Equals(other); public bool Equals(SkinArmorFlags other) { return _flags.Data == other._flags.Data; } public bool Equals(SkinArmorFlagsMask other) { return _flags.Data == (int)other; } public override bool Equals(object obj) => obj is SkinArmorFlags a && Equals(a); public override int GetHashCode() => _flags.Data; /// /// Sets the desired flag in the bitfield /// /// SkinArmor Flag to set /// State of the flag public SkinArmorFlags SetFlag(SkinArmorFlagsFlag flag, bool state) { if (!Enum.IsDefined(typeof(SkinArmorFlagsFlag), flag)) throw new ArgumentOutOfRangeException(nameof(flag)); return new SkinArmorFlags(state ? _flags.Data | 1 << (int)flag : _flags.Data & ~(1 << (int)flag)); } /// /// Gets flag state /// /// Flag to check /// True if flag is set, otherwise false public bool GetFlag(SkinArmorFlagsFlag flag) { if (!Enum.IsDefined(typeof(SkinArmorFlagsFlag), flag)) throw new ArgumentOutOfRangeException(nameof(flag)); return _flags[1 << (int)flag]; } public object Clone() { return MemberwiseClone(); } } }