Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Hex v0.1.18
plugins/Hex/Hex.Core.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ExtraPotions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")] [assembly: AssemblyFileVersion("0.1.18.0")] [assembly: AssemblyInformationalVersion("0.1.18+da1d6644b921fba451b3511c7b98b4c9770d446f")] [assembly: AssemblyProduct("Hex.Core")] [assembly: AssemblyTitle("Hex.Core")] [assembly: AssemblyVersion("0.1.18.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ExtraPotions.Hex { public static class HexActionKeys { public static IReadOnlyList<string> Powers { get; } = new string[8] { "GP_Eikthyr", "GP_TheElder", "GP_Bonemass", "GP_Moder", "GP_Yagluth", "GP_Queen", "GP_Ashlands", "GP_DeepNorth" }; public static IReadOnlyList<string> Keys { get; } = new string[17] { "heal", "rested", "reveal", "poi", "estimatepoi", "seed", "reset", "reset_speeds", "spawn_protection", "GP_Eikthyr", "GP_TheElder", "GP_Bonemass", "GP_Moder", "GP_Yagluth", "GP_Queen", "GP_Ashlands", "GP_DeepNorth" }; public static string Label(string key) { return key switch { "spawn_protection" => "spawn_protection_label", "reset" => "map_reset", "seed" => "seed_label", "reset_speeds" => "speeds_reset_all", "estimatepoi" => "poi_estimate", "poi" => "poi_actual", "reveal" => "map_reveal", "rested" => "actions_rested", "heal" => "actions_heal", _ => "actions_power", }; } } public static class HexCatalog { public static IReadOnlyList<string> AgreedUnits { get; } = new string[26] { "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "B1", "B2", "B3", "C1", "C2", "C3", "C4", "D1", "E1", "E2", "F1", "F2", "F3", "G1", "G2", "G3", "G4", "G5" }; public static IReadOnlyList<string> RuntimeKeys { get; } = new string[35] { "unlimited_stamina", "unlimited_eitr", "infinite_jumps", "walk_speed", "run_speed", "swim_speed", "jump_power", "moon_gravity", "disable_durability_loss", "no_carry_limit", "custom_carry_weight", "disable_food_degradation", "god_mode", "ghost_mode", "fly", "noclip", "freecam", "fly_speed", "mounted_speed", "keep_items", "keep_food", "keep_skills", "keep_status_effects", "achievements_despite_cheats", "clear_inventory_marks", "clear_container_marks", "clear_drop_marks", "local_time_minute", "local_time_freeze", "bouncy", "super_knockback", "party_hits", "player_size", "debug_mode", "esp" }; public static float SpeedFactor(int percent) { return (float)Math.Min(300, Math.Max(10, percent)) / 100f; } public static float SizeFactor(int percent) { return (float)Math.Min(300, Math.Max(25, percent)) / 100f; } public static float JumpFactor(int percent) { return (float)Math.Min(500, Math.Max(25, percent)) / 100f; } public static float CarryCapacity(float native, bool noLimit, int custom) { if (!noLimit) { if (custom <= 0) { return native; } return Math.Min(99999, custom); } return float.PositiveInfinity; } } public readonly struct OwnedScale { public readonly float Before; public readonly float Applied; public OwnedScale(float before, float factor) { Before = before; Applied = before * factor; } public float Restore(float current) { if (current != Applied) { return current; } return Before; } } public static class HexCore { public const string PluginGuid = "com.meadworks.hex"; public const string ProductName = "Hex"; public const string ProductVersion = "0.1.18"; public const string Family = "Mischief"; public const string TokenNamespace = "hex"; public const string SupportedGameVersion = "1.0.17"; public const string TokenPrefix = "meadworks_hex_"; public const string DataFolder = "Meadworks/hex"; } public static class HexDebugView { public const float DayPerMouse = 0.005f; public const float FovMin = 0.5f; public const float FovMax = 165f; public static float Day(float fraction, float mouseY) { float num = (fraction + mouseY * 0.005f) % 1f; if (!(num < 0f)) { return num; } return num + 1f; } public static float Fov(float fov, float mouseX) { return Math.Max(0.5f, Math.Min(165f, fov + mouseX)); } } public sealed class HexHotkeyValues { private readonly Dictionary<string, object> selected = new Dictionary<string, object>(StringComparer.Ordinal); public void Remember(string key, object current, object safe) { if (current is int && !object.Equals(current, safe)) { selected[key] = current; } } public bool Next(string key, object current, object safe, out object next) { Remember(key, current, safe); next = safe; if (current is bool flag) { next = !flag; return true; } if (!(current is int)) { return false; } if (!object.Equals(current, safe)) { return true; } return selected.TryGetValue(key, out next); } } public readonly struct HexKillReply { public int Targets { get; } public int Submitted { get; } public int Skipped { get; } public HexKillReply(int targets, int submitted, int skipped) { Targets = targets; Submitted = submitted; Skipped = skipped; } } public readonly struct HexAreaRequest { public float Radius { get; } public HexAreaRequest(float radius) { Radius = radius; } } public static class HexKillData { public const string OperationId = "meadworks.hex.debug_kill"; public const string DropsOperationId = "meadworks.hex.debug_drops"; public const string TameOperationId = "meadworks.hex.debug_tame"; public const string EventOperationId = "meadworks.hex.debug_event"; public const int MaxTargets = 512; public static readonly Version Version = new Version(1, 0); public static byte[] EncodeRequest(HexAreaRequest request) { if (!HexOwnerData.ValidRadius(request.Radius)) { throw new ArgumentException("Invalid radius."); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write((byte)2); binaryWriter.Write((byte)1); binaryWriter.Write(request.Radius); return memoryStream.ToArray(); } public static HexAreaRequest DecodeRequest(byte[] bytes) { if (bytes == null || bytes.Length != 6 || bytes[0] != 2 || bytes[1] != 1) { throw new FormatException("Invalid kill request."); } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes, writable: false)); binaryReader.ReadByte(); binaryReader.ReadByte(); float radius = binaryReader.ReadSingle(); if (!HexOwnerData.ValidRadius(radius)) { throw new FormatException("Invalid radius."); } return new HexAreaRequest(radius); } public static byte[] EncodeEvent(bool confirmed) { if (!confirmed) { throw new ArgumentException("Event confirmation required."); } return new byte[2] { 1, 1 }; } public static bool DecodeEvent(byte[] bytes) { if (bytes == null || bytes.Length != 2 || bytes[0] != 1 || bytes[1] != 1) { throw new FormatException("Invalid event request."); } return true; } private static bool Valid(HexKillReply value) { if (value.Targets >= 0 && value.Targets <= 512 && value.Submitted >= 0 && value.Skipped >= 0 && value.Submitted <= value.Targets) { return value.Skipped == value.Targets - value.Submitted; } return false; } public static byte[] EncodeReply(HexKillReply value) { if (!Valid(value)) { throw new ArgumentException("Invalid kill result."); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write((byte)1); binaryWriter.Write(value.Targets); binaryWriter.Write(value.Submitted); binaryWriter.Write(value.Skipped); return memoryStream.ToArray(); } public static HexKillReply DecodeReply(byte[] bytes) { if (bytes == null || bytes.Length != 13 || bytes[0] != 1) { throw new FormatException("Invalid kill result."); } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes, writable: false)); binaryReader.ReadByte(); HexKillReply hexKillReply = new HexKillReply(binaryReader.ReadInt32(), binaryReader.ReadInt32(), binaryReader.ReadInt32()); if (!Valid(hexKillReply)) { throw new FormatException("Invalid kill counts."); } return hexKillReply; } } public static class HexMenu { public const float ValueX = 380f; public const float RowEnd = 708f; public static IReadOnlyList<string> Tabs { get; } = new string[7] { "cheats", "movement", "skills", "spawn", "map", "debug", "presets" }; public static IReadOnlyList<string> Speeds { get; } = new string[5] { "walk_speed", "run_speed", "swim_speed", "fly_speed", "mounted_speed" }; public static IReadOnlyDictionary<string, string[]> Preferences { get; } = new Dictionary<string, string[]> { ["cheats"] = new string[17] { "god_mode", "ghost_mode", "fly", "noclip", "freecam", "unlimited_stamina", "unlimited_eitr", "infinite_jumps", "disable_durability_loss", "disable_food_degradation", "no_carry_limit", "custom_carry_weight", "keep_items", "keep_food", "keep_skills", "keep_status_effects", "quick_actions" }, ["movement"] = new string[11] { "moon_gravity", "bouncy", "super_knockback", "party_hits", "jump_power", "player_size", "walk_speed", "run_speed", "swim_speed", "fly_speed", "mounted_speed" }, ["skills"] = new string[1] { "skill_editor" }, ["spawn"] = new string[0], ["map"] = new string[1] { "map_tools" }, ["debug"] = new string[5] { "debug_tools", "debug_mode", "esp", "local_time_minute", "local_time_freeze" }, ["presets"] = new string[0] }; public static IReadOnlyList<string> AlmanacOnly { get; } = new string[4] { "achievements_despite_cheats", "clear_inventory_marks", "clear_container_marks", "clear_drop_marks" }; public static IReadOnlyList<(string Id, int Minute)> TimePresets { get; } = new(string, int)[4] { ("midnight", 0), ("sunrise", 360), ("noon", 720), ("sunset", 1080) }; public static (float X, float Width) ResetSpan(float captionWidth) { float num = Math.Min(150f, Math.Max(68f, captionWidth + 18f)); return (X: 708f - num, Width: num); } public static float ValueWidth(float preferred, float resetX) { return Math.Max(120f, Math.Min(preferred, resetX - 10f - 380f)); } } public enum HexOwnerAction : byte { Kill = 1, Drops, Tame } public readonly struct HexTargetId : IEquatable<HexTargetId> { public long User { get; } public uint Id { get; } public HexTargetId(long user, uint id) { User = user; Id = id; } public bool Equals(HexTargetId other) { if (User == other.User) { return Id == other.Id; } return false; } public override bool Equals(object? obj) { if (obj is HexTargetId other) { return Equals(other); } return false; } public override int GetHashCode() { return (User.GetHashCode() * 397) ^ (int)Id; } public override string ToString() { return User + ":" + Id; } } public sealed class HexOwnerCommand { public HexOwnerAction Action { get; } public float X { get; } public float Y { get; } public float Z { get; } public float Radius { get; } public IReadOnlyList<HexTargetId> Targets { get; } public HexOwnerCommand(HexOwnerAction action, float x, float y, float z, float radius, IReadOnlyList<HexTargetId> targets) { Action = action; X = x; Y = y; Z = z; Radius = radius; Targets = targets; } } public readonly struct HexOwnerReply { public int Applied { get; } public int Skipped { get; } public HexOwnerReply(int applied, int skipped) { Applied = applied; Skipped = skipped; } } public static class HexOwnerData { public const string CommandId = "meadworks.hex.debug_owner"; public const int MaxBatch = 64; public const float MinRadius = 5f; public const float MaxRadius = 1000f; public static readonly Version Version = new Version(2, 0); private static bool Finite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static bool Defined(HexOwnerAction action) { if (action != HexOwnerAction.Kill && action != HexOwnerAction.Drops) { return action == HexOwnerAction.Tame; } return true; } public static bool ValidRadius(float radius) { if (Finite(radius) && radius >= 5f) { return radius <= 1000f; } return false; } public static bool SkipCreature(HexOwnerAction action, bool player, bool tamed) { if (action != HexOwnerAction.Drops) { return player || tamed; } return false; } public static bool Within(float cx, float cy, float cz, float x, float y, float z, float radius) { if (!Finite(cx) || !Finite(cy) || !Finite(cz) || !Finite(x) || !Finite(y) || !Finite(z)) { return false; } double num = x - cx; double num2 = y - cy; double num3 = z - cz; return num * num + num2 * num2 + num3 * num3 <= (double)radius * (double)radius; } public static byte[] Encode(HexOwnerCommand command) { if (command == null || !Defined(command.Action) || !Finite(command.X) || !Finite(command.Y) || !Finite(command.Z) || !ValidRadius(command.Radius) || command.Targets == null || command.Targets.Count < 1 || command.Targets.Count > 64 || command.Targets.Distinct().Count() != command.Targets.Count) { throw new ArgumentException("Invalid owner command."); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write((byte)2); binaryWriter.Write((byte)command.Action); binaryWriter.Write(command.X); binaryWriter.Write(command.Y); binaryWriter.Write(command.Z); binaryWriter.Write(command.Radius); binaryWriter.Write((ushort)command.Targets.Count); foreach (HexTargetId target in command.Targets) { binaryWriter.Write(target.User); binaryWriter.Write(target.Id); } return memoryStream.ToArray(); } public static HexOwnerCommand Decode(byte[] bytes) { if (bytes == null || bytes.Length < 20 || bytes[0] != 2 || !Defined((HexOwnerAction)bytes[1])) { throw new FormatException("Invalid owner command."); } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes, writable: false)); binaryReader.ReadByte(); HexOwnerAction action = (HexOwnerAction)binaryReader.ReadByte(); float num = binaryReader.ReadSingle(); float num2 = binaryReader.ReadSingle(); float num3 = binaryReader.ReadSingle(); float radius = binaryReader.ReadSingle(); int num4 = binaryReader.ReadUInt16(); if (!Finite(num) || !Finite(num2) || !Finite(num3) || !ValidRadius(radius) || num4 < 1 || num4 > 64 || bytes.Length != 20 + num4 * 12) { throw new FormatException("Invalid owner command."); } List<HexTargetId> list = new List<HexTargetId>(num4); for (int i = 0; i < num4; i++) { list.Add(new HexTargetId(binaryReader.ReadInt64(), binaryReader.ReadUInt32())); } if (list.Distinct().Count() != num4) { throw new FormatException("Repeated owner target."); } return new HexOwnerCommand(action, num, num2, num3, radius, list); } private static bool Valid(int applied, int skipped) { if (applied >= 0 && skipped >= 0 && applied <= 64 && skipped <= 64 && applied + skipped >= 1) { return applied + skipped <= 64; } return false; } public static byte[] EncodeReply(HexOwnerReply reply) { if (!Valid(reply.Applied, reply.Skipped)) { throw new ArgumentException("Invalid owner reply."); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write((byte)1); binaryWriter.Write(reply.Applied); binaryWriter.Write(reply.Skipped); return memoryStream.ToArray(); } public static HexOwnerReply DecodeReply(byte[] bytes) { if (bytes == null || bytes.Length != 9 || bytes[0] != 1) { throw new FormatException("Invalid owner reply."); } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes, writable: false)); binaryReader.ReadByte(); int applied = binaryReader.ReadInt32(); int skipped = binaryReader.ReadInt32(); if (!Valid(applied, skipped)) { throw new FormatException("Invalid owner counts."); } return new HexOwnerReply(applied, skipped); } } public readonly struct HexOwnedTarget { public long Owner { get; } public HexTargetId Id { get; } public HexOwnedTarget(long owner, HexTargetId id) { Owner = owner; Id = id; } } public sealed class HexOwnerBatch { public long Owner { get; } public IReadOnlyList<HexTargetId> Ids { get; } public HexOwnerBatch(long owner, IReadOnlyList<HexTargetId> ids) { Owner = owner; Ids = ids; } } public sealed class HexOwnerPlan { public IReadOnlyList<HexOwnerBatch> Batches { get; } public int Targets { get; } public int Unowned { get; } public bool OverLimit { get; } internal HexOwnerPlan(IReadOnlyList<HexOwnerBatch> batches, int targets, int unowned, bool overLimit) { Batches = batches; Targets = targets; Unowned = unowned; OverLimit = overLimit; } } public static class HexOwnerPlanner { public static HexOwnerPlan Plan(IEnumerable<HexOwnedTarget> targets, int maxTargets, int batchSize) { if (maxTargets < 1) { throw new ArgumentOutOfRangeException("maxTargets"); } if (batchSize < 1) { throw new ArgumentOutOfRangeException("batchSize"); } HashSet<HexTargetId> hashSet = new HashSet<HexTargetId>(); List<long> list = new List<long>(); Dictionary<long, List<HexTargetId>> dictionary = new Dictionary<long, List<HexTargetId>>(); int num = 0; int num2 = 0; foreach (HexOwnedTarget target in targets) { if (!hashSet.Add(target.Id)) { continue; } if (target.Owner == 0L) { num++; continue; } num2++; if (!dictionary.TryGetValue(target.Owner, out var value)) { value = new List<HexTargetId>(); dictionary.Add(target.Owner, value); list.Add(target.Owner); } value.Add(target.Id); } if (num2 > maxTargets) { return new HexOwnerPlan(Array.Empty<HexOwnerBatch>(), num2, num, overLimit: true); } List<HexOwnerBatch> list2 = new List<HexOwnerBatch>(); foreach (long item in list) { for (int i = 0; i < dictionary[item].Count; i += batchSize) { list2.Add(new HexOwnerBatch(item, dictionary[item].Skip(i).Take(batchSize).ToArray())); } } return new HexOwnerPlan(list2, num2, num, overLimit: false); } } public enum HexBatchState { Applied, Refused, Unknown } public sealed class HexOwnerTally { private readonly int targets; private int submitted; private int recorded; public bool Uncertain { get; private set; } public HexKillReply Reply { get { if (!Uncertain) { return new HexKillReply(targets, submitted, targets - submitted); } throw new InvalidOperationException("Owner outcome uncertain."); } } public HexOwnerTally(int targets) { if (targets < 0) { throw new ArgumentOutOfRangeException("targets"); } this.targets = targets; } public void Record(int batchSize, HexBatchState state, HexOwnerReply reply) { recorded += batchSize; if (recorded > targets || batchSize < 1) { Uncertain = true; return; } switch (state) { case HexBatchState.Refused: return; case HexBatchState.Unknown: Uncertain = true; return; } if (reply.Applied < 0 || reply.Skipped < 0 || reply.Applied + reply.Skipped != batchSize) { Uncertain = true; } else { submitted += reply.Applied; } } } public static class HexPoiRows { public const string CapabilityId = "meadworks.thing.poi"; public static readonly Version Version = new Version(1, 0); public const int Maximum = 512; private static readonly Dictionary<string, string> names = new Dictionary<string, string>(StringComparer.Ordinal) { ["Eikthyrnir"] = "$enemy_eikthyr", ["GDKing"] = "$enemy_gdking", ["Bonemass"] = "$enemy_bonemass", ["Dragonqueen"] = "$enemy_dragon", ["GoblinKing"] = "$enemy_goblinking", ["Mistlands_DvergrBossEntrance1"] = "$enemy_seekerqueen", ["FaderLocation"] = "$enemy_fader", ["DN_Bossroom"] = "$enemy_frozenking", ["Vendor_BlackForest"] = "$npc_haldor", ["Hildir_camp"] = "$npc_hildir", ["BogWitch_Camp"] = "$npc_bogwitch" }; public static bool Trader(string name) { if (!(name == "Vendor_BlackForest") && !(name == "Hildir_camp")) { return name == "BogWitch_Camp"; } return true; } public static string Token(string name) { if (!names.TryGetValue(name, out string value)) { return name; } return value; } private static bool Coordinate(float value) { if (!float.IsNaN(value) && !float.IsInfinity(value)) { return Math.Abs(value) <= 20000f; } return false; } public static IReadOnlyList<Tuple<string, float, float, float, bool>> Select(IEnumerable<Tuple<string, float, float, float, bool>> source) { List<Tuple<string, float, float, float, bool>> list = new List<Tuple<string, float, float, float, bool>>(); foreach (Tuple<string, float, float, float, bool> item in source) { if (item != null && names.ContainsKey(item.Item1 ?? "") && Coordinate(item.Item2) && Coordinate(item.Item3) && Coordinate(item.Item4)) { list.Add(item); if (list.Count > 512) { throw new InvalidOperationException("PoiLimit"); } } } HashSet<string> confirmed = new HashSet<string>(from row in list where Trader(row.Item1) && row.Item5 select row.Item1, StringComparer.Ordinal); return Array.AsReadOnly(list.Where((Tuple<string, float, float, float, bool> row) => !Trader(row.Item1) || row.Item5 || !confirmed.Contains(row.Item1)).Distinct().ToArray()); } } public static class HexSourceImport { public const string VatFile = "com.icecub.valheimadmintool.cfg"; public const string VatPresetFile = "com.icecub.valheimadmintool.cheats.cfg"; public const string AsFile = "liveriadevs.valheim.achievementsync.cfg"; public static IReadOnlyDictionary<string, string> ToggleKeys { get; } = new Dictionary<string, string>(StringComparer.Ordinal) { ["GodMode"] = "god_mode", ["DebugMode"] = "debug_mode", ["UnlimitedStamina"] = "unlimited_stamina", ["UnlimitedEitr"] = "unlimited_eitr", ["FlyMode"] = "fly", ["InfiniteJumps"] = "infinite_jumps", ["NoClipMode"] = "noclip", ["FreeCamMode"] = "freecam", ["GhostMode"] = "ghost_mode", ["NoCarryLimit"] = "no_carry_limit", ["DisableFoodDegradation"] = "disable_food_degradation", ["DisableDurabilityLoss"] = "disable_durability_loss", ["DisableItemLoss"] = "keep_items", ["DisableFoodLoss"] = "keep_food", ["DisableStatusLoss"] = "keep_status_effects", ["DisableSkillLoss"] = "keep_skills", ["MoonGravity"] = "moon_gravity", ["SuperKnockback"] = "super_knockback", ["BouncyMode"] = "bouncy", ["PartyHits"] = "party_hits" }; public static IReadOnlyDictionary<string, string> Owners { get; } = new Dictionary<string, string>(StringComparer.Ordinal) { ["NoBuildCost"] = "Timber", ["BuildEverywhere"] = "Timber", ["NoStructuralDamage"] = "Timber", ["MapTeleport"] = "Wayfarer", ["UnrestrictedPortals"] = "Threshold", ["ForgeAlwaysSucceed"] = "Inscribe", ["InstantCrafting"] = "Kindle", ["WindInBack"] = "Keel", ["ShipSpeed"] = "Keel", ["WardOverride"] = "Thing", ["RemoveDrops"] = "Thing" }; public static IReadOnlyDictionary<string, string> ActionKeys { get; } = new Dictionary<string, string>(StringComparer.Ordinal) { ["QuickHeal"] = "heal", ["Rested"] = "rested", ["ExploreMap"] = "reveal", ["RevealPoi"] = "poi", ["ShowWorldSeed"] = "seed", ["ResetMap"] = "reset", ["BossPowerEikthyr"] = "GP_Eikthyr", ["BossPowerElder"] = "GP_TheElder", ["BossPowerBonemass"] = "GP_Bonemass", ["BossPowerModer"] = "GP_Moder", ["BossPowerYagluth"] = "GP_Yagluth", ["BossPowerQueen"] = "GP_Queen", ["BossPowerFader"] = "GP_Ashlands" }; public static IReadOnlyDictionary<string, string> AchievementKeys { get; } = new Dictionary<string, string>(StringComparer.Ordinal) { ["EnableAchievements"] = "achievements_despite_cheats", ["ClearItemCheatFlags"] = "clear_inventory_marks", ["ClearContainerCheatFlags"] = "clear_container_marks", ["ClearWorldDropCheatFlags"] = "clear_drop_marks" }; public static string? Target(string source, string sectionKey) { if (source == "vat") { if (sectionKey == "General.Toggle menu") { return "menu"; } if (sectionKey.StartsWith("Hotkeys.", StringComparison.Ordinal)) { if (ToggleKeys.TryGetValue(sectionKey.Substring(8), out string value)) { return "hotkey:" + value; } if (ActionKeys.TryGetValue(sectionKey.Substring(8), out string value2)) { return "action:" + value2; } } } if (source == "as" && sectionKey.StartsWith("General.", StringComparison.Ordinal) && AchievementKeys.TryGetValue(sectionKey.Substring(8), out string value3)) { return "preference:" + value3; } if (source == "as-guard" && (sectionKey == "General.SyncPastStats" || sectionKey == "General.ResyncKey")) { return "Achievements." + sectionKey.Substring(8); } return null; } public static string? Referral(string sectionKey) { if (sectionKey.StartsWith("Automatic resets.", StringComparison.Ordinal)) { return "Delve"; } if (!sectionKey.StartsWith("Hotkeys.", StringComparison.Ordinal) || !Owners.TryGetValue(sectionKey.Substring(8), out string value)) { return null; } return value; } public static string? PresetKey(string sectionKey) { int num = sectionKey.LastIndexOf('.'); string text = ((num >= 0) ? sectionKey.Substring(num + 1) : sectionKey); if (ToggleKeys.TryGetValue(text, out string value)) { return value; } foreach (string runtimeKey in HexCatalog.RuntimeKeys) { if (runtimeKey == text) { return runtimeKey; } } return null; } } public enum HexSpawnKind : byte { Item = 1, Creature } public sealed class HexSpawnRequest { public HexSpawnKind Kind { get; } public string Prefab { get; } public int Amount { get; } public int Level { get; } public bool Tamed { get; } public bool Inventory { get; } public HexSpawnRequest(HexSpawnKind kind, string prefab, int amount, int level, bool tamed, bool inventory) { Kind = kind; Prefab = prefab; Amount = amount; Level = level; Tamed = tamed; Inventory = inventory; } } public sealed class HexSpawnReply { public string Receipt { get; } public int Created { get; } public bool Partial { get; } public HexSpawnReply(string receipt, int created, bool partial) { Receipt = receipt; Created = created; Partial = partial; } } public static class HexSpawnData { public const string OperationId = "meadworks.hex.spawn"; public const string AuditCapability = "meadworks.thing.hex_spawn_audit"; public static readonly Version Version = new Version(1, 0); public const int MaxAmount = 9999; public const int MaxCreatureLevel = 100; private static readonly Regex Markup = new Regex("</?(?:color|b|i|u|s|size|material|quad|sprite|link|mark|align|alpha|font|style|rotate|sup|sub|nobr|noparse|cspace|mspace|pos|space|indent|margin|line-height|line-indent|lowercase|uppercase|smallcaps|voffset|width|gradient|page)(?:[=\\s][^<>]*)?>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant); private static readonly Regex Unresolved = new Regex("^(?:\\$[A-Za-z0-9_.]+|\\[[A-Za-z0-9_.]+\\])$", RegexOptions.Compiled | RegexOptions.CultureInvariant); public static bool PrefabValid(string prefab) { if (!string.IsNullOrWhiteSpace(prefab) && prefab.Length <= 160) { return prefab.All((char c) => !char.IsControl(c)); } return false; } public static bool Valid(HexSpawnRequest request) { if (request != null && Enum.IsDefined(typeof(HexSpawnKind), request.Kind) && PrefabValid(request.Prefab) && request.Amount >= 1 && request.Amount <= 9999 && request.Level >= 1) { if (request.Kind != HexSpawnKind.Item) { if (request.Level <= 100) { return !request.Inventory; } return false; } return !request.Tamed; } return false; } public static bool Supported(HexSpawnRequest request, int itemMaxQuality, bool tameable) { if (Valid(request)) { if (request.Kind != HexSpawnKind.Item) { return !request.Tamed || tameable; } return request.Level <= itemMaxQuality; } return false; } private static bool Flag(BinaryReader reader) { byte b = reader.ReadByte(); if (b > 1) { throw new FormatException("Invalid spawn flag."); } return b == 1; } private static BinaryReader Reader(byte[] bytes, int maximum) { if (bytes == null || bytes.Length < 2 || bytes.Length > maximum) { throw new FormatException("Invalid spawn payload length."); } BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes, writable: false), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true)); if (binaryReader.ReadByte() != 1) { binaryReader.Dispose(); throw new FormatException("Invalid spawn format."); } return binaryReader; } public static byte[] Encode(HexSpawnRequest request) { if (!Valid(request)) { throw new ArgumentException("Invalid spawn request."); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8, leaveOpen: true); binaryWriter.Write((byte)1); binaryWriter.Write((byte)request.Kind); binaryWriter.Write(request.Prefab); binaryWriter.Write(request.Amount); binaryWriter.Write(request.Level); binaryWriter.Write(request.Tamed); binaryWriter.Write(request.Inventory); return memoryStream.ToArray(); } public static HexSpawnRequest Decode(byte[] bytes) { using BinaryReader binaryReader = Reader(bytes, 1024); HexSpawnRequest hexSpawnRequest = new HexSpawnRequest((HexSpawnKind)binaryReader.ReadByte(), binaryReader.ReadString(), binaryReader.ReadInt32(), binaryReader.ReadInt32(), Flag(binaryReader), Flag(binaryReader)); if (!Valid(hexSpawnRequest) || binaryReader.BaseStream.Position != binaryReader.BaseStream.Length) { throw new FormatException("Invalid spawn request."); } return hexSpawnRequest; } private static bool Valid(HexSpawnReply reply) { if (reply != null && Guid.TryParseExact(reply.Receipt, "N", out var _) && reply.Created >= 0) { return reply.Created <= 9999; } return false; } public static byte[] Encode(HexSpawnReply reply) { if (!Valid(reply)) { throw new ArgumentException("Invalid spawn reply."); } using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8, leaveOpen: true); binaryWriter.Write((byte)1); binaryWriter.Write(reply.Receipt); binaryWriter.Write(reply.Created); binaryWriter.Write(reply.Partial); return memoryStream.ToArray(); } public static HexSpawnReply DecodeReply(byte[] bytes) { using BinaryReader binaryReader = Reader(bytes, 128); HexSpawnReply hexSpawnReply = new HexSpawnReply(binaryReader.ReadString(), binaryReader.ReadInt32(), Flag(binaryReader)); if (!Valid(hexSpawnReply) || binaryReader.BaseStream.Position != binaryReader.BaseStream.Length) { throw new FormatException("Invalid spawn reply."); } return hexSpawnReply; } public static string DisplayName(string? localized, string prefab) { string text = Markup.Replace(localized ?? "", ""); StringBuilder stringBuilder = new StringBuilder(text.Length); string text2 = text; foreach (char c in text2) { stringBuilder.Append((char.IsControl(c) || CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Format) ? ' ' : c); } string text3 = Regex.Replace(stringBuilder.ToString(), "\\s+", " ").Trim(); if (text3.Length != 0 && !Unresolved.IsMatch(text3)) { return text3; } return prefab; } public static string Fold(string value) { StringBuilder stringBuilder = new StringBuilder(); string text = (value ?? "").Normalize(NormalizationForm.FormD); foreach (char c in text) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark && !char.IsWhiteSpace(c) && c != '_' && c != '-') { stringBuilder.Append(char.ToUpperInvariant(c)); } } return stringBuilder.ToString().Normalize(NormalizationForm.FormC); } } public static class HexToolAccess { public static bool Allows(bool fullAdmin, bool granted, bool mischiefAllowed, bool refusedBecauseNotAdmin, bool adminRequired) { if (adminRequired && !fullAdmin && !granted) { return false; } if (mischiefAllowed) { return true; } return granted && refusedBecauseNotAdmin; } } public sealed class LocalClock { private int selected = -1; private bool frozen; private float offset; public void Reset() { selected = -1; offset = 0f; } public float Resolve(float native, int minute, bool freeze) { if (minute < 0 || minute > 1439 || float.IsNaN(native) || float.IsInfinity(native)) { Reset(); return native; } float num = (float)minute / 1440f; if (selected != minute || frozen != freeze) { selected = minute; frozen = freeze; offset = num - native; } float num2 = (freeze ? num : (native + offset)); return num2 - (float)Math.Floor(num2); } } public static class SpawnProtectionGeometry { public readonly struct Point { public double X { get; } public double Z { get; } public Point(double x, double z) { X = x; Z = z; } } public readonly struct Circle { public double X { get; } public double Z { get; } public double Radius { get; } public int Segments { get; } public double InnerRadius => Radius * Math.Cos(Math.PI / (double)Segments); public Circle(double x, double z, double radius) { if (!Finite(x) || !Finite(z) || !Finite(radius) || radius <= 0.0 || radius > 1024.0) { throw new ArgumentOutOfRangeException("radius"); } X = x; Z = z; Radius = radius; Segments = Math.Max(12, (int)Math.Ceiling(Math.PI / Math.Acos(1.0 - Math.Min(0.005, radius) / radius))); } } public sealed class Region { public IReadOnlyList<Point> Points { get; } public bool Covered { get; } internal Region(List<Point> points, bool covered) { Points = points; Covered = covered; } } public const double ChordError = 0.005; private const double Epsilon = 1E-09; private const int MaximumRegions = 512; public static IReadOnlyList<Region> Partition(double x, double z, double size, IReadOnlyList<Circle> circles, Circle? extent = null, bool covered = false) { if (!Finite(x) || !Finite(z) || !Finite(size) || size <= 0.0) { throw new ArgumentOutOfRangeException("size"); } return Partition(new List<Point> { new Point(x, z), new Point(x + size, z), new Point(x + size, z + size), new Point(x, z + size) }, circles, extent, covered); } public static IReadOnlyList<Region> PartitionTriangle(Point a, Point b, Point c, IReadOnlyList<Circle> circles, Circle? extent = null, bool covered = false) { double num = Side(c, a, b); if (!Finite(a.X) || !Finite(a.Z) || !Finite(b.X) || !Finite(b.Z) || !Finite(c.X) || !Finite(c.Z) || Math.Abs(num) <= 1E-09) { throw new ArgumentOutOfRangeException("c"); } return Partition((num > 0.0) ? new List<Point> { a, b, c } : new List<Point> { a, c, b }, circles, extent, covered); } public static double TriangleHeight(Point point, Point a, double heightA, Point b, double heightB, Point c, double heightC) { double num = Side(c, a, b); if (Math.Abs(num) <= 1E-09) { throw new ArgumentOutOfRangeException("c"); } double num2 = Side(point, b, c) / num; double num3 = Side(point, c, a) / num; return num2 * heightA + num3 * heightB + (1.0 - num2 - num3) * heightC; } private static IReadOnlyList<Region> Partition(List<Point> cell, IReadOnlyList<Circle> circles, Circle? extent, bool covered) { if (circles == null || circles.Count > 512) { throw new ArgumentOutOfRangeException("circles"); } if (extent.HasValue) { cell = Intersect(cell, extent.Value); } List<Region> list = new List<Region>(); if (covered) { if (Valid(cell)) { list.Add(new Region(cell, covered: true)); } return list; } List<List<Point>> list2 = new List<List<Point>>(); if (Valid(cell)) { list2.Add(cell); } foreach (Circle circle in circles) { List<List<Point>> list3 = new List<List<Point>>(); foreach (List<Point> item in list2) { if (Outside(item, circle)) { list3.Add(item); continue; } if (Inside(item, circle)) { list.Add(new Region(item, covered: true)); continue; } List<Point> list4 = item; for (int i = 0; i < circle.Segments; i++) { if (!Valid(list4)) { break; } Edge(circle, i, out var a, out var b); List<Point> list5 = Clip(list4, a, b, inside: false); if (Valid(list5)) { list3.Add(list5); } list4 = Clip(list4, a, b, inside: true); if (list3.Count + list.Count > 512) { throw new InvalidOperationException("Protection geometry limit"); } } if (Valid(list4)) { list.Add(new Region(list4, covered: true)); } } list2 = list3; if (list2.Count == 0) { break; } } foreach (List<Point> item2 in list2) { list.Add(new Region(item2, covered: false)); } return list; } private static List<Point> Intersect(List<Point> polygon, Circle circle) { if (Outside(polygon, circle)) { return new List<Point>(); } if (Inside(polygon, circle)) { return polygon; } for (int i = 0; i < circle.Segments; i++) { if (!Valid(polygon)) { break; } Edge(circle, i, out var a, out var b); polygon = Clip(polygon, a, b, inside: true); } return polygon; } private static void Edge(Circle circle, int edge, out Point a, out Point b) { double num = (double)edge * Math.PI * 2.0 / (double)circle.Segments; double num2 = (double)(edge + 1) * Math.PI * 2.0 / (double)circle.Segments; a = new Point(circle.X + Math.Cos(num) * circle.Radius, circle.Z + Math.Sin(num) * circle.Radius); b = new Point(circle.X + Math.Cos(num2) * circle.Radius, circle.Z + Math.Sin(num2) * circle.Radius); } private static bool Inside(List<Point> polygon, Circle circle) { double innerRadius = circle.InnerRadius; double num = innerRadius * innerRadius; foreach (Point item in polygon) { if ((item.X - circle.X) * (item.X - circle.X) + (item.Z - circle.Z) * (item.Z - circle.Z) > num) { return false; } } return true; } private static bool Outside(List<Point> polygon, Circle circle) { double num = double.PositiveInfinity; double num2 = num; double num3 = double.NegativeInfinity; double num4 = num3; foreach (Point item in polygon) { num = Math.Min(num, item.X); num3 = Math.Max(num3, item.X); num2 = Math.Min(num2, item.Z); num4 = Math.Max(num4, item.Z); } double num5 = Math.Max(num - circle.X, Math.Max(0.0, circle.X - num3)); double num6 = Math.Max(num2 - circle.Z, Math.Max(0.0, circle.Z - num4)); return num5 * num5 + num6 * num6 >= circle.Radius * circle.Radius; } private static List<Point> Clip(List<Point> polygon, Point a, Point b, bool inside) { List<Point> list = new List<Point>(); if (polygon.Count == 0) { return list; } Point point = polygon[polygon.Count - 1]; double num = Side(point, a, b); bool flag = (inside ? (num >= 0.0) : (num <= 0.0)); foreach (Point item in polygon) { double num2 = Side(item, a, b); bool num3 = (inside ? (num2 >= 0.0) : (num2 <= 0.0)); if (num3 != flag) { double num4 = num / (num - num2); list.Add(new Point(point.X + (item.X - point.X) * num4, point.Z + (item.Z - point.Z) * num4)); } if (num3) { list.Add(item); } point = item; num = num2; flag = num3; } return list; } private static double Side(Point point, Point a, Point b) { return (b.X - a.X) * (point.Z - a.Z) - (b.Z - a.Z) * (point.X - a.X); } private static bool Valid(List<Point> points) { if (points.Count >= 3) { return Area(points) > 1E-09; } return false; } private static bool Finite(double value) { if (!double.IsNaN(value)) { return !double.IsInfinity(value); } return false; } public static double Area(IReadOnlyList<Point> points) { double num = 0.0; for (int i = 0; i < points.Count; i++) { Point point = points[(i + 1) % points.Count]; num += points[i].X * point.Z - point.X * points[i].Z; } return Math.Abs(num) * 0.5; } } } namespace ExtraPotions.Hex.Ghost { public readonly struct GhostKey : IEquatable<GhostKey>, IComparable<GhostKey> { public long User { get; } public uint Id { get; } public bool IsNone { get { if (User == 0L) { return Id == 0; } return false; } } public GhostKey(long user, uint id) { User = user; Id = id; } public bool Equals(GhostKey other) { if (User == other.User) { return Id == other.Id; } return false; } public override bool Equals(object? obj) { if (obj is GhostKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (User.GetHashCode() * 397) ^ (int)Id; } public int CompareTo(GhostKey other) { int num = User.CompareTo(other.User); if (num == 0) { return Id.CompareTo(other.Id); } return num; } public static bool operator ==(GhostKey a, GhostKey b) { return a.Equals(b); } public static bool operator !=(GhostKey a, GhostKey b) { return !a.Equals(b); } public override string ToString() { return User + ":" + Id; } } public enum GhostVerb : byte { Off, On } public enum GhostState : byte { Off, Confirmed, Refused } public enum GhostReason : byte { None, Inactive, Character, Denied, Capacity, Vanilla } public readonly struct GhostAnswer : IEquatable<GhostAnswer> { public GhostState State { get; } public GhostReason Reason { get; } public bool Keeps => State == GhostState.Confirmed; public GhostAnswer(GhostState state, GhostReason reason) { State = state; Reason = reason; } public bool Equals(GhostAnswer other) { if (State == other.State) { return Reason == other.Reason; } return false; } public override bool Equals(object? obj) { if (obj is GhostAnswer other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)State * 16 + (int)Reason; } public override string ToString() { return State.ToString() + ((Reason == GhostReason.None) ? "" : (":" + Reason)); } } public static class GhostDecision { public static GhostAnswer Decide(GhostVerb verb, bool active, bool characterMatches, bool allowed, bool capacityAvailable, bool vanillaBlocked = false) { if (!active) { return new GhostAnswer(GhostState.Refused, GhostReason.Inactive); } if (!characterMatches) { return new GhostAnswer(GhostState.Refused, GhostReason.Character); } if (verb == GhostVerb.Off) { return new GhostAnswer(GhostState.Off, GhostReason.None); } if (!allowed) { return new GhostAnswer(GhostState.Refused, GhostReason.Denied); } if (vanillaBlocked) { return new GhostAnswer(GhostState.Refused, GhostReason.Vanilla); } if (!capacityAvailable) { return new GhostAnswer(GhostState.Refused, GhostReason.Capacity); } return new GhostAnswer(GhostState.Confirmed, GhostReason.None); } } public readonly struct GhostRequestFacts : IEquatable<GhostRequestFacts> { public long Generation { get; } public GhostKey Character { get; } public bool Wish { get; } public bool Confirmed { get; } public string Stamp { get; } public GhostRequestFacts(long generation, GhostKey character, bool wish, bool confirmed, string stamp) { Generation = generation; Character = character; Wish = wish; Confirmed = confirmed; Stamp = stamp ?? ""; } internal bool SameKey(GhostRequestFacts other) { if (Generation == other.Generation && Character == other.Character && Wish == other.Wish) { return string.Equals(Stamp, other.Stamp, StringComparison.Ordinal); } return false; } public bool Equals(GhostRequestFacts other) { if (SameKey(other)) { return Confirmed == other.Confirmed; } return false; } public override bool Equals(object? obj) { if (obj is GhostRequestFacts other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((uint)((Generation.GetHashCode() * 397) ^ Character.GetHashCode()) ^ (Wish ? 1u : 0u)) ^ Stamp.GetHashCode(); } } public sealed class GhostRequester { public const double Spacing = 1.0; public const double FailureDelay = 5.0; public const int MaxAttempts = 3; private GhostRequestFacts? current; private GhostRequestFacts? sent; private int attempts; private bool answered; private bool inFlight; private double nextAllowed = double.NegativeInfinity; public bool InFlight => inFlight; public GhostVerb? Next(double now, GhostRequestFacts facts) { if (facts.Character.IsNone) { return null; } if (!current.HasValue || !current.Value.SameKey(facts)) { current = facts; attempts = 0; answered = false; } if (facts.Wish == facts.Confirmed || inFlight || answered || attempts >= 3 || now < nextAllowed) { return null; } attempts++; inFlight = true; sent = facts; nextAllowed = now + 1.0; return facts.Wish ? GhostVerb.On : GhostVerb.Off; } public void Completed(double now, bool wasAnswered) { if (!inFlight) { return; } inFlight = false; bool flag = sent.HasValue && current.HasValue && sent.Value.SameKey(current.Value); if (wasAnswered) { if (flag) { answered = true; } } else { nextAllowed = Math.Max(nextAllowed, now + 5.0); } sent = null; } public void Reset() { current = (sent = null); attempts = 0; answered = (inFlight = false); nextAllowed = double.NegativeInfinity; } } public sealed class GhostPublisher { private sealed class Peer { public long Delivered = -1L; public bool InFlight; public double NextAttempt; public int Failures; } public const double Spacing = 2.0; public const double MaxBackoff = 10.0; private readonly Dictionary<string, Peer> peers = new Dictionary<string, Peer>(StringComparer.Ordinal); public bool Due(string peer, long revision, bool empty, double now) { if (!peers.TryGetValue(peer, out Peer value)) { return !empty; } if (!value.InFlight && value.Delivered != revision) { return now >= value.NextAttempt; } return false; } public void Sent(string peer, long revision, double now) { if (!peers.TryGetValue(peer, out Peer value)) { value = (peers[peer] = new Peer()); } value.InFlight = true; value.NextAttempt = now + 2.0; } public void Delivered(string peer, long revision) { if (peers.TryGetValue(peer, out Peer value)) { value.InFlight = false; value.Delivered = revision; value.Failures = 0; } } public void Failed(string peer, double now) { if (peers.TryGetValue(peer, out Peer value)) { value.InFlight = false; value.Failures = Math.Min(value.Failures + 1, 8); value.NextAttempt = now + Math.Min(10.0, Math.Pow(2.0, value.Failures)); } } public void Retain(IEnumerable<string> live) { if (peers.Count == 0) { return; } ICollection<string> collection = (live as ICollection<string>) ?? new HashSet<string>(live ?? Array.Empty<string>(), StringComparer.Ordinal); List<string> list = null; foreach (string key in peers.Keys) { if (!collection.Contains(key)) { (list ?? (list = new List<string>())).Add(key); } } if (list == null) { return; } foreach (string item in list) { peers.Remove(item); } } public void Clear() { peers.Clear(); } } public enum GhostVanillaPolicy { Allow, Refuse } public static class GhostVanillaRule { public const GhostVanillaPolicy Default = GhostVanillaPolicy.Allow; public static bool Blocks(GhostVanillaPolicy policy, bool vanillaClientsConnected) { return policy == GhostVanillaPolicy.Refuse && vanillaClientsConnected; } public static bool VanillaPresent(GhostVanillaPolicy policy, bool known, bool anyVanilla) { if (!known) { return policy == GhostVanillaPolicy.Refuse; } return anyVanilla; } public static bool BlocksForPeer(bool pending, bool crucible, bool hasHex) { if (!pending) { if (crucible) { return !hasHex; } return true; } return false; } } public sealed class GhostVanillaGrace { public const double GraceSeconds = 5.0; private double since = double.NaN; public bool Blocks(GhostVanillaPolicy policy, bool known, bool anyVanilla, double now) { if (policy != GhostVanillaPolicy.Refuse || (known && !anyVanilla)) { since = double.NaN; return false; } if (!known) { since = double.NaN; return true; } if (double.IsNaN(since)) { since = now; } return now - since >= 5.0; } public void Reset() { since = double.NaN; } } public static class GhostNotices { public const string RevokedKey = "ghost_revoked"; public const string SettingKey = "ghost_vanilla_setting"; public static IReadOnlyList<string> TextKeys { get; } = new string[7] { "ghost_refused_inactive", "ghost_refused_character", "ghost_refused_denied", "ghost_refused_capacity", "ghost_refused_vanilla", "ghost_revoked", "ghost_vanilla_setting" }; public static string? RefusalKey(GhostReason reason) { return reason switch { GhostReason.Inactive => "ghost_refused_inactive", GhostReason.Character => "ghost_refused_character", GhostReason.Denied => "ghost_refused_denied", GhostReason.Capacity => "ghost_refused_capacity", GhostReason.Vanilla => "ghost_refused_vanilla", _ => null, }; } public static string? For(GhostAnswer answer) { if (answer.State != GhostState.Refused) { return null; } return RefusalKey(answer.Reason); } } public sealed class GhostRegistry { public const int MaxEntries = 256; private readonly Dictionary<string, GhostKey> entries = new Dictionary<string, GhostKey>(StringComparer.Ordinal); private readonly HashSet<GhostKey> keys = new HashSet<GhostKey>(); public long Revision { get; private set; } public int Count => entries.Count; public bool Has(string peer) { if (peer != null) { return entries.ContainsKey(peer); } return false; } public bool Contains(GhostKey key) { if (!key.IsNone) { return keys.Contains(key); } return false; } public bool CanAdmit(string peer) { if (!Has(peer)) { return entries.Count < 256; } return true; } public bool Grant(string peer, GhostKey key) { if (string.IsNullOrEmpty(peer)) { throw new ArgumentException("Expected a peer.", "peer"); } if (key.IsNone) { throw new ArgumentException("Expected a character.", "key"); } if (entries.TryGetValue(peer, out var value) && value == key) { return false; } if (!CanAdmit(peer)) { throw new InvalidOperationException("Ghost registry is full."); } entries[peer] = key; Rebuild(); return true; } public bool Revoke(string peer) { if (peer == null || !entries.Remove(peer)) { return false; } Rebuild(); return true; } public IReadOnlyList<string> RetainWhere(Func<string, GhostKey, bool> keep) { if (keep == null) { throw new ArgumentNullException("keep"); } string[] array = (from pair in entries where !keep(pair.Key, pair.Value) select pair.Key).OrderBy<string, string>((string p) => p, StringComparer.Ordinal).ToArray(); if (array.Length == 0) { return array; } string[] array2 = array; foreach (string key in array2) { entries.Remove(key); } Rebuild(); return array; } public void Clear() { if (entries.Count != 0) { entries.Clear(); Rebuild(); } } public GhostKey[] Snapshot() { return keys.OrderBy((GhostKey k) => k).ToArray(); } private void Rebuild() { keys.Clear(); foreach (GhostKey value in entries.Values) { keys.Add(value); } checked { Revision++; } } } public sealed class GhostView { private readonly HashSet<GhostKey> keys = new HashSet<GhostKey>(); private long generation = -1L; private long revision = -1L; public int Count => keys.Count; public long Generation => generation; public bool Contains(GhostKey key) { if (!key.IsNone) { return keys.Contains(key); } return false; } public void Reset(long sessionGeneration) { generation = sessionGeneration; revision = -1L; keys.Clear(); } public bool Accept(long sessionGeneration, long setRevision, IReadOnlyCollection<GhostKey> set) { if (set == null || sessionGeneration != generation || setRevision <= revision) { return false; } revision = setRevision; keys.Clear(); foreach (GhostKey item in set) { if (!item.IsNone) { keys.Add(item); } } return true; } } public sealed class GhostSet { public long Revision { get; } public IReadOnlyList<GhostKey> Keys { get; } public GhostSet(long revision, IReadOnlyList<GhostKey> keys) { Revision = revision; Keys = keys; } } public static class GhostWire { public const byte Version = 1; public const int MaxEntries = 256; private const int KeySize = 12; private const int SetHeader = 11; public static byte[] EncodeRequest(GhostVerb verb, GhostKey key) { if (verb != GhostVerb.On && verb != GhostVerb.Off) { throw new ArgumentException("Unknown verb.", "verb"); } byte[] obj = new byte[14] { 1, (byte)verb, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; WriteKey(obj, 2, key); return obj; } public static (GhostVerb Verb, GhostKey Key) DecodeRequest(byte[] bytes) { if (bytes == null || bytes.Length != 14 || bytes[0] != 1) { throw new FormatException("Malformed Ghost request."); } if (bytes[1] > 1) { throw new FormatException("Unknown Ghost verb."); } GhostKey item = ReadKey(bytes, 2); if (item.IsNone) { throw new FormatException("Ghost request without a character."); } return (Verb: (GhostVerb)bytes[1], Key: item); } public static byte[] EncodeAnswer(GhostAnswer answer) { return new byte[3] { 1, (byte)answer.State, (byte)answer.Reason }; } public static GhostAnswer DecodeAnswer(byte[] bytes) { if (bytes == null || bytes.Length != 3 || bytes[0] != 1) { throw new FormatException("Malformed Ghost answer."); } if (bytes[1] > 2 || bytes[2] > 5) { throw new FormatException("Unknown Ghost answer."); } return new GhostAnswer((GhostState)bytes[1], (GhostReason)bytes[2]); } public static byte[] EncodeSet(long revision, IReadOnlyCollection<GhostKey> keys) { if (keys == null) { throw new ArgumentNullException("keys"); } if (revision < 0) { throw new ArgumentException("Negative revision.", "revision"); } GhostKey[] array = (from k in keys.Distinct() orderby k select k).ToArray(); if (array.Length > 256) { throw new ArgumentException("Too many Ghost entries.", "keys"); } if (array.Any((GhostKey k) => k.IsNone)) { throw new ArgumentException("Ghost set with an empty character.", "keys"); } byte[] array2 = new byte[11 + array.Length * 12]; array2[0] = 1; WriteLong(array2, 1, revision); array2[9] = (byte)(array.Length >> 8); array2[10] = (byte)array.Length; for (int num = 0; num < array.Length; num++) { WriteKey(array2, 11 + num * 12, array[num]); } return array2; } public static GhostSet DecodeSet(byte[] bytes) { if (bytes == null || bytes.Length < 11 || bytes[0] != 1) { throw new FormatException("Malformed Ghost set."); } long num = ReadLong(bytes, 1); if (num < 0) { throw new FormatException("Negative Ghost revision."); } int num2 = (bytes[9] << 8) | bytes[10]; if (num2 > 256 || bytes.Length != 11 + num2 * 12) { throw new FormatException("Ghost set length mismatch."); } GhostKey[] array = new GhostKey[num2]; for (int i = 0; i < num2; i++) { array[i] = ReadKey(bytes, 11 + i * 12); if (array[i].IsNone) { throw new FormatException("Ghost set with an empty character."); } if (i > 0 && array[i - 1].CompareTo(array[i]) >= 0) { throw new FormatException("Ghost set is not strictly ordered."); } } return new GhostSet(num, array); } public static byte[] EncodeAck() { return new byte[2] { 1, 1 }; } public static bool DecodeAck(byte[] bytes) { if (bytes == null || bytes.Length != 2 || bytes[0] != 1 || bytes[1] != 1) { throw new FormatException("Malformed Ghost acknowledgment."); } return true; } private static void WriteKey(byte[] bytes, int at, GhostKey key) { WriteLong(bytes, at, key.User); for (int i = 0; i < 4; i++) { bytes[at + 8 + i] = (byte)(key.Id >> 24 - 8 * i); } } private static GhostKey ReadKey(byte[] bytes, int at) { uint num = 0u; for (int i = 0; i < 4; i++) { num = (num << 8) | bytes[at + 8 + i]; } return new GhostKey(ReadLong(bytes, at), num); } private static void WriteLong(byte[] bytes, int at, long value) { for (int i = 0; i < 8; i++) { bytes[at + i] = (byte)(value >> 56 - 8 * i); } } private static long ReadLong(byte[] bytes, int at) { long num = 0L; for (int i = 0; i < 8; i++) { num = (num << 8) | bytes[at + i]; } return num; } } }
plugins/Hex/Hex.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExtraPotions.Hex.Ghost; using ExtraPotions.Hex.Runtime.Native; using ExtraPotions.Meadworks.Contracts; using ExtraPotions.Meadworks.Crucible; using ExtraPotions.Meadworks.Crucible.UI; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ExtraPotions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2026 expDARE (ExtraPotions Meadworks)")] [assembly: AssemblyFileVersion("0.1.18.0")] [assembly: AssemblyInformationalVersion("0.1.18+da1d6644b921fba451b3511c7b98b4c9770d446f")] [assembly: AssemblyProduct("Hex")] [assembly: AssemblyTitle("Hex")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.18.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ExtraPotions.Hex.Runtime { public sealed class HexConfig { private readonly Dictionary<string, ConfigEntryBase> entries = new Dictionary<string, ConfigEntryBase>(); private readonly Dictionary<string, object> safeValues = new Dictionary<string, object>(); private readonly Dictionary<string, MischiefCategory> categories = new Dictionary<string, MischiefCategory>(); private readonly Dictionary<string, string> cheatIds = new Dictionary<string, string>(); private Dictionary<string, ConfigEntryBase>? preferences; private readonly List<string> nonNeutral = new List<string>(); private bool rememberStale = true; private bool neutralStale = true; private readonly ConfigFile file; private readonly Dictionary<string, ConfigEntry<KeyboardShortcut>> hotkeys = new Dictionary<string, ConfigEntry<KeyboardShortcut>>(StringComparer.Ordinal); private readonly HexHotkeyValues hotkeyValues = new HexHotkeyValues(); internal readonly Dictionary<string, ConfigEntry<KeyboardShortcut>> ActionHotkeys = new Dictionary<string, ConfigEntry<KeyboardShortcut>>(StringComparer.Ordinal); internal readonly Dictionary<string, ConfigEntry<bool>> EspKinds = new Dictionary<string, ConfigEntry<bool>>(StringComparer.Ordinal); public ConfigEntry<bool> Enabled { get; } public ConfigEntry<KeyboardShortcut> PanicKey { get; } public ConfigEntry<KeyboardShortcut> MenuKey { get; } public ConfigEntry<bool> QuickActions { get; } public ConfigEntry<bool> DebugTools { get; } public ConfigEntry<bool> MapTools { get; } public ConfigEntry<bool> SkillEditor { get; } public ConfigEntry<bool> Spawning { get; } public ConfigEntry<int> EspDistance { get; } public ConfigEntry<string> EspSearch { get; } public ConfigEntry<int> ConfirmSpawnAbove { get; } public ConfigEntry<bool> RestorePresetOnJoin { get; } public ConfigEntry<GhostVanillaPolicy> GhostWithVanilla { get; } public HexConfig(ConfigFile file) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_05f8: Unknown result type (might be due to invalid IL or missing references) this.file = file; bool saveOnConfigSet = file.SaveOnConfigSet; file.SaveOnConfigSet = false; try { Enabled = MeadworksConfig.Bind<bool>(file, "General", "Enabled", true, Localized<bool>("enabled", null, Array.Empty<object>())); RestorePresetOnJoin = MeadworksConfig.Bind<bool>(file, "General", "Restore Preset On Join", true, Localized<bool>("preset_restore", null, Array.Empty<object>()), (ConfigScope)0); SkillEditor = MeadworksConfig.Bind<bool>(file, "General", "Skill Editor", false, Localized<bool>("skill_editor", null, Array.Empty<object>()), (ConfigScope)0); Spawning = MeadworksConfig.Bind<bool>(file, "General", "Spawning", false, Localized<bool>("spawning", null, Array.Empty<object>()), (ConfigScope)0); ConfirmSpawnAbove = MeadworksConfig.Bind<int>(file, "General", "Confirm Spawn Above", 100, Localized<int>("spawn_confirm_above", (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 9999), new object[1] { (object)new ConfigDependency((Func<bool>)(() => Enabled.Value && Spawning.Value), (Func<string>)(() => "Requires General: Enabled and Spawning."), (Func<bool>)null) }), (ConfigScope)0); MapTools = MeadworksConfig.Bind<bool>(file, "General", "Map Tools", false, Localized<bool>("map_tools", null, Array.Empty<object>()), (ConfigScope)0); DebugTools = MeadworksConfig.Bind<bool>(file, "General", "Debug Tools", false, Localized<bool>("debug_tools", null, Array.Empty<object>()), (ConfigScope)0); QuickActions = MeadworksConfig.Bind<bool>(file, "General", "Quick Actions", false, Localized<bool>("quick_actions", null, Array.Empty<object>())); MenuKey = MeadworksConfig.Bind<KeyboardShortcut>(file, "General", "Menu Key", KeyboardShortcut.Empty, Localized<KeyboardShortcut>("menu_key", null, Array.Empty<object>()), (ConfigScope)0); PanicKey = MeadworksConfig.Bind<KeyboardShortcut>(file, "General", "Panic Key", KeyboardShortcut.Empty, Localized<KeyboardShortcut>("panic", null, Array.Empty<object>())); Toggle("unlimited_stamina"); Toggle("unlimited_eitr"); Toggle("infinite_jumps"); Toggle("moon_gravity"); Toggle("bouncy"); Toggle("super_knockback"); Toggle("party_hits"); Toggle("disable_durability_loss"); Toggle("disable_food_degradation"); Toggle("no_carry_limit"); Bind("custom_carry_weight", 0, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(0, 99999)); Number("walk_speed", 10, 300); Number("run_speed", 10, 300); Number("swim_speed", 10, 300); Number("fly_speed", 10, 300); Number("mounted_speed", 10, 300); Number("jump_power", 25, 500); Number("player_size", 25, 300); Bind("local_time_minute", -1, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(-1, 1439)); Toggle("local_time_freeze"); Toggle("keep_items"); Toggle("keep_food"); Toggle("keep_skills"); Toggle("keep_status_effects"); BindValue("achievements_despite_cheats", initial: true, safe: false, (MischiefCategory)5); BindValue("clear_inventory_marks", initial: true, safe: false, (MischiefCategory)5); BindValue("clear_container_marks", initial: true, safe: false, (MischiefCategory)5); BindValue("clear_drop_marks", initial: true, safe: false, (MischiefCategory)5); Toggle("debug_mode"); BindValue("esp", initial: false, safe: false, (MischiefCategory)3); EspDistance = MeadworksConfig.Bind<int>(file, "ESP", "Max Distance", 100, EspDescription<int>("esp_distance", (AcceptableValueBase?)(object)new AcceptableValueRange<int>(10, 500)), (ConfigScope)0); EspSearch = MeadworksConfig.Bind<string>(file, "ESP", "Search", "", EspDescription<string>("esp_search"), (ConfigScope)0); string[] array = new string[6] { "players", "creatures", "drops", "resources", "pickables", "dungeons" }; foreach (string text in array) { EspKinds.Add(text, MeadworksConfig.Bind<bool>(file, "ESP", text, true, EspDescription<bool>("esp_" + text), (ConfigScope)0)); } Toggle("god_mode"); Toggle("ghost_mode"); Toggle("fly"); Toggle("noclip"); Toggle("freecam"); GhostWithVanilla = MeadworksConfig.Bind<GhostVanillaPolicy>(file, "Server", "Ghost With Vanilla Clients", (GhostVanillaPolicy)0, Localized<GhostVanillaPolicy>("ghost_vanilla_setting", null, Array.Empty<object>()), (ConfigScope)0); foreach (string key in HexActionKeys.Keys) { ActionHotkeys.Add(key, MeadworksConfig.Bind<KeyboardShortcut>(file, "Action Hotkeys", key, KeyboardShortcut.Empty, HotkeyDescription(HexActionKeys.Label(key), key.StartsWith("GP_", StringComparison.Ordinal) ? (" " + key) : ""), (ConfigScope)0)); } foreach (KeyValuePair<string, ConfigEntryBase> item in PreferenceEntries()) { hotkeys.Add(item.Key, MeadworksConfig.Bind<KeyboardShortcut>(file, "Hotkeys", item.Key, KeyboardShortcut.Empty, HotkeyDescription("label_" + item.Key), (ConfigScope)0)); } } finally { file.SaveOnConfigSet = saveOnConfigSet; } file.Save(); file.SettingChanged += delegate { rememberStale = (neutralStale = true); }; file.ConfigReloaded += delegate { rememberStale = (neutralStale = true); }; } private ConfigDescription EspDescription<T>(string key, AcceptableValueBase? range = null) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown return Localized<T>(key, range, new object[1] { (object)new ConfigDependency((Func<bool>)(() => Effective("esp", safe: false)), (Func<string>)(() => "Requires ESP enabled and Information permission."), (Func<bool>)null) }); } private static string? CatalogText(string key, string language) { ProductTranslations val = default(ProductTranslations); if (!MeadworksTranslations.Registry.TryGet("hex", ref val)) { return null; } string text = val.Text(key, language); if (!string.Equals(text, key, StringComparison.Ordinal)) { return text; } return null; } private static ConfigDescription Localized<T>(string key, AcceptableValueBase? range = null, params object[] tags) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown string labelKey = ((key == "menu_key") ? "ui_menu_key" : (key.StartsWith("esp_", StringComparison.Ordinal) ? key : ("label_" + key))); string helpKey = ((key == "esp_distance") ? "help_esp_distance" : ((key == "esp_search") ? "help_esp_search" : (key.StartsWith("esp_", StringComparison.Ordinal) ? "help_esp_filters" : key))); object[] array = new object[tags.Length + 1]; Array.Copy(tags, array, tags.Length); array[tags.Length] = new ConfigPresentation<T>("com.meadworks.hex", (Func<ConfigEntry<T>, string, ConfigPresentationText>)((ConfigEntry<T> _, string language) => new ConfigPresentationText(CatalogText(labelKey, language), (string)null, CatalogText(helpKey, language)))); return new ConfigDescription(CatalogText(helpKey, "English") ?? key, range, array); } private static ConfigDescription HotkeyDescription(string labelKey, string suffix = "") { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown return new ConfigDescription(Help("English"), (AcceptableValueBase)null, new object[1] { new ConfigPresentation<KeyboardShortcut>("com.meadworks.hex", (Func<ConfigEntry<KeyboardShortcut>, string, ConfigPresentationText>)delegate(ConfigEntry<KeyboardShortcut> _, string language) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown string text = CatalogText(labelKey, language); string text2 = CatalogText("hotkey_description", language); return (text != null && text2 != null) ? new ConfigPresentationText(text + suffix, (string)null, string.Format(text2, text + suffix)) : ((ConfigPresentationText)null); }) }); string Help(string language) { return string.Format(CatalogText("hotkey_description", language) ?? "{0}", (CatalogText(labelKey, language) ?? labelKey) + suffix); } } private ConfigEntry<T> Bind<T>(string key, T safe, AcceptableValueBase? range = null) { return BindValue(key, safe, safe, (MischiefCategory)0, range); } private ConfigEntry<T> BindValue<T>(string key, T initial, T safe, MischiefCategory category, AcceptableValueBase? range = null) { //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0632: Invalid comparison between Unknown and I4 //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_0637: Invalid comparison between Unknown and I4 //IL_0688: Unknown result type (might be due to invalid IL or missing references) //IL_06b7: Unknown result type (might be due to invalid IL or missing references) string text = key switch { "unlimited_stamina" => "Unlimited Stamina", "unlimited_eitr" => "Unlimited Eitr", "infinite_jumps" => "Infinite Jumps", "walk_speed" => "Walk Speed Percent", "run_speed" => "Run Speed Percent", "fly_speed" => "Fly Speed Percent", "mounted_speed" => "Mounted Speed Percent", "swim_speed" => "Swim Speed Percent", "player_size" => "Player Size Percent", "party_hits" => "Party Hits", "super_knockback" => "Super Knockback", "bouncy" => "Bouncy", "jump_power" => "Jump Power Percent", "moon_gravity" => "Moon Gravity", "disable_durability_loss" => "Disable Durability Loss", "disable_food_degradation" => "Disable Food Degradation", "no_carry_limit" => "No Carry Limit", "local_time_minute" => "Local Time Minute", "local_time_freeze" => "Freeze Local Time", "custom_carry_weight" => "Custom Carry Weight", "achievements_despite_cheats" => "Achievements Despite Cheats", "clear_inventory_marks" => "Clear Inventory Cheat Marks", "clear_container_marks" => "Clear Container Cheat Marks", "clear_drop_marks" => "Clear Drop Cheat Marks", "keep_items" => "Keep Items On Death", "keep_food" => "Keep Food On Death", "keep_skills" => "Keep Skills On Death", "keep_status_effects" => "Keep Status Effects On Death", "debug_mode" => "Debug Mode", "esp" => "ESP", "god_mode" => "God Mode", "ghost_mode" => "Ghost Mode", "fly" => "Fly", "noclip" => "NoClip", "freecam" => "FreeCam", _ => key, }; ConfigEntry<T> val = MeadworksConfig.Bind<T>(file, ((int)category == 5) ? "Achievements" : (((int)category == 3) ? "Information" : "Personal"), text, initial, Localized<T>(key, range, Array.Empty<object>()), (ConfigScope)0); entries.Add(key, (ConfigEntryBase)(object)val); safeValues.Add(key, safe); categories.Add(key, category); cheatIds.Add(key, CheatId((ConfigEntryBase)(object)val)); MeadworksMischief.Cheats.Tag("com.meadworks.hex", cheatIds[key], (MischiefCategory?)category); return val; } private void Toggle(string key) { Bind(key, safe: false); } private static string CheatId(ConfigEntryBase entry) { return entry.Definition.Section + "." + entry.Definition.Key; } private void Number(string key, int min, int max) { Bind(key, 100, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(min, max)); } internal Dictionary<string, ConfigEntryBase> PreferenceEntries() { return preferences ?? (preferences = BuildPreferenceEntries()); } private Dictionary<string, ConfigEntryBase> BuildPreferenceEntries() { return new Dictionary<string, ConfigEntryBase>(entries, StringComparer.Ordinal) { { "quick_actions", (ConfigEntryBase)(object)QuickActions }, { "debug_tools", (ConfigEntryBase)(object)DebugTools }, { "map_tools", (ConfigEntryBase)(object)MapTools }, { "skill_editor", (ConfigEntryBase)(object)SkillEditor }, { "spawning", (ConfigEntryBase)(object)Spawning } }; } internal MischiefCategory? Category(string key) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!categories.TryGetValue(key, out var value)) { return null; } return value; } internal object SafeValue(string key) { if (!safeValues.TryGetValue(key, out object value)) { return false; } return value; } internal ConfigEntry<KeyboardShortcut> Hotkey(string key) { return hotkeys[key]; } internal bool SetPreference(string key, object value) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Ready || !Plugin.Active || !ValidPreference(key, value)) { return false; } if (!object.Equals(value, SafeValue(key)) && categories.TryGetValue(key, out var value2) && (!Enabled.Value || (!MeadworksMischief.PlayersMay(PreferenceEntries()[key]) && !MeadworksMischief.TryUse("com.meadworks.hex", CheatId(PreferenceEntries()[key]), value2, HexText.Text(key))))) { return false; } return MeadworksConfig.Amend(PreferenceEntries()[key], value, HexText.Text(key)).Applied; } internal bool MayUse(string key) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (categories.TryGetValue(key, out var value)) { return MeadworksMischief.AllowsCheat(PreferenceEntries()[key], "com.meadworks.hex", value); } return true; } internal string ResetSpeeds() { if (!Plugin.Ready || !Plugin.Active || !HexMovement.Owned((Character)(object)Player.m_localPlayer)) { return HexText.Text("actions_unavailable"); } foreach (string speed in HexMenu.Speeds) { if (!SetPreference(speed, SafeValue(speed))) { return HexText.Text("actions_unavailable"); } } return HexText.Text("speeds_reset_done"); } internal void PanicReset() { HexSpawnProtection.Reset(); ConfigEntry<bool>[] array = new ConfigEntry<bool>[5] { QuickActions, DebugTools, MapTools, SkillEditor, Spawning }; for (int i = 0; i < array.Length; i++) { MeadworksConfig.Amend((ConfigEntryBase)(object)array[i], (object)false, (string)null); } HexPresets.CancelJoinRestore(); foreach (KeyValuePair<string, ConfigEntryBase> entry in entries) { MeadworksConfig.Amend(entry.Value, safeValues[entry.Key], (string)null); } } internal Dictionary<string, object> Snapshot() { return PreferenceEntries().ToDictionary<KeyValuePair<string, ConfigEntryBase>, string, object>((KeyValuePair<string, ConfigEntryBase> pair) => pair.Key, (KeyValuePair<string, ConfigEntryBase> pair) => pair.Value.BoxedValue, StringComparer.Ordinal); } internal bool ValidPreference(string key, object value) { if (PreferenceEntries().TryGetValue(key, out ConfigEntryBase value2) && value != null && value.GetType() == value2.SettingType) { if (value2.Description.AcceptableValues != null) { return value2.Description.AcceptableValues.IsValid(value); } return true; } return false; } internal void ApplyPreferences(IReadOnlyDictionary<string, object> snapshot) { foreach (KeyValuePair<string, object> item in snapshot) { if (!ValidPreference(item.Key, item.Value)) { throw new ArgumentException("Invalid preset preference."); } } Dictionary<string, ConfigEntryBase> dictionary = PreferenceEntries(); bool saveOnConfigSet = file.SaveOnConfigSet; file.SaveOnConfigSet = false; try { foreach (KeyValuePair<string, object> item2 in snapshot) { dictionary[item2.Key].BoxedValue = item2.Value; } } finally { file.SaveOnConfigSet = saveOnConfigSet; } file.Save(); } public T Effective<T>(string key, T safe) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Ready || !Plugin.Active || !Enabled.Value) { return safe; } return MeadworksMischief.Effective<T>((ConfigEntry<T>)(object)entries[key], "com.meadworks.hex", categories[key], safe); } public void Tick() { //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Invalid comparison between Unknown and I4 //IL_02c6: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Active) { return; } if (MeadworksInput.Pressed(PanicKey, (InputContext)0)) { PanicReset(); } else { if (!Plugin.Active || !Enabled.Value) { return; } if (rememberStale) { rememberStale = false; foreach (KeyValuePair<string, ConfigEntryBase> item in PreferenceEntries()) { hotkeyValues.Remember(item.Key, item.Value.BoxedValue, SafeValue(item.Key)); } } if (HexMovement.Owned((Character)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead()) { object value = default(object); foreach (KeyValuePair<string, ConfigEntry<KeyboardShortcut>> hotkey in hotkeys) { if (MeadworksInput.Pressed(hotkey.Value, (InputContext)0) && ((!hotkey.Key.StartsWith("achievements_", StringComparison.Ordinal) && !hotkey.Key.StartsWith("clear_", StringComparison.Ordinal)) || HexAchievements.Available)) { ConfigEntryBase val = PreferenceEntries()[hotkey.Key]; if (hotkeyValues.Next(hotkey.Key, val.BoxedValue, SafeValue(hotkey.Key), ref value)) { SetPreference(hotkey.Key, value); } else if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, HexText.Text("hotkey_choose"), 0, (Sprite)null, false, true); } } } } if (HexMovement.Owned((Character)(object)Player.m_localPlayer)) { foreach (KeyValuePair<string, ConfigEntry<KeyboardShortcut>> actionHotkey in ActionHotkeys) { if (MeadworksInput.Pressed(actionHotkey.Value, (InputContext)0)) { HexActionShortcuts.Run(actionHotkey.Key); } } } if (neutralStale) { neutralStale = false; nonNeutral.Clear(); foreach (KeyValuePair<string, ConfigEntryBase> entry in entries) { if (!object.Equals(entry.Value.BoxedValue, safeValues[entry.Key])) { nonNeutral.Add(entry.Key); } } } foreach (string item2 in nonNeutral) { if ((int)categories[item2] != 5 || HexAchievements.Available) { BlockedOption obj = MeadworksMischief.Query("com.meadworks.hex", cheatIds[item2], categories[item2]); MeadworksBlockedOptions.Notify(obj, obj.Allowed ? null : HexText.Text(item2)); } } } } } internal static class EdgeWear { internal static void Register(ProductRegistration registration) { registration.AddCapability<Func<object, object, bool>>("meadworks.items.wear_exempt", WearExemptContract.ContractVersion, (Func<object, object, bool>)Exempt); } internal static bool Exempt(object character, object item) { if (Plugin.Active) { Humanoid val = (Humanoid)((character is Humanoid) ? character : null); if (val != null) { ItemData val2 = (ItemData)((item is ItemData) ? item : null); if (val2 != null && HexMovement.On((Character)(object)val, "disable_durability_loss")) { return val.GetInventory().ContainsItem(val2); } } } return false; } } internal static class HexActionShortcuts { internal static void Run(string key) { if (!Plugin.Ready || !Plugin.Active) { return; } HexConfig? settings = Plugin.Settings; if (settings != null && settings.Enabled.Value && HexMovement.Owned((Character)(object)Player.m_localPlayer)) { string text = key switch { "reveal" => HexMap.Execute(new string[2] { "map", "reveal" }), "spawn_protection" => HexSpawnProtection.Toggle(), "estimatepoi" => HexPoi.RequestEstimate(), "poi" => HexPoi.Request(), "seed" => HexInformation.Seed(), "reset" => HexWindow.ConfirmMapReset(), "reset_speeds" => Plugin.Settings.ResetSpeeds(), _ => HexActionKeys.Powers.Contains(key) ? HexActions.Execute(new string[2] { "power", key }) : ((key == "heal" || key == "rested") ? HexActions.Execute(new string[1] { key }) : ""), }; if (text.Length > 0 && (Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true); } } } } internal sealed class HexImport : IDisposable { private sealed class CheckedTarget : IValidatedConversionTarget, IConversionTarget { private readonly HexImport owner; private readonly PreviewDocument preview; private readonly IConversionTarget target; public int SchemaVersion => target.SchemaVersion; internal CheckedTarget(HexImport owner, PreviewDocument preview) { this.owner = owner; this.preview = preview; target = MeadworksConversion.Target(owner.Owner(preview.Id)); } public void Validate(IReadOnlyDictionary<string, object> values) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) owner.Admission(preview); ((IValidatedConversionTarget)target).Validate(values); foreach (KeyValuePair<string, object> value in values) { ConfigEntryBase val = Entry(owner.Owner(preview.Id), value.Key); object obj = (val.SettingType.IsInstanceOfType(value.Value) ? value.Value : TomlTypeConverter.ConvertToValue(Convert.ToString(value.Value, CultureInfo.InvariantCulture), val.SettingType)); if (val.Description.AcceptableValues != null && !val.Description.AcceptableValues.IsValid(obj)) { throw new ArgumentException(HexText.Text("import_invalid")); } } if (owner.Collisions(owner.Owner(preview.Id), values).Any()) { throw new InvalidOperationException(HexText.Text("import_collision_refused")); } } public void Backup() { owner.Admission(preview); target.Backup(); } public void WriteAtomic(IReadOnlyDictionary<string, object> values) { owner.Admission(preview); target.WriteAtomic(values); } } private sealed class PresetTarget : IValidatedConversionTarget, IConversionTarget { private readonly HexImport owner; private readonly PreviewDocument preview; private readonly string expected; private string proposal = ""; public int SchemaVersion => 0; internal PresetTarget(HexImport owner, PreviewDocument preview) { this.owner = owner; this.preview = preview; expected = HexPresets.ImportDisk(); } public void Validate(IReadOnlyDictionary<string, object> values) { owner.Admission(preview); proposal = HexPresets.ImportProposal(expected, values); } public void Backup() { owner.Admission(preview); HexPresets.ImportBackup(expected); } public void WriteAtomic(IReadOnlyDictionary<string, object> values) { owner.Admission(preview); if (proposal.Length == 0) { throw new InvalidOperationException(); } HexPresets.ImportWrite(expected, proposal); } } internal sealed class PreviewDocument { internal HexImport Owner { get; } internal string Id { get; } internal ConfigConverter Converter { get; } internal long Generation { get; } public ConversionPreview Plan { get; } public IReadOnlyList<string> Notes { get; } public IReadOnlyList<string> Errors { get; } public string SourceSha256 { get; } public string TargetSha256 { get; } internal PreviewDocument(HexImport owner, string id, ConfigConverter converter, ConversionPreview plan, IReadOnlyList<string> notes, IReadOnlyList<string> errors, string source, string target, long generation) { Owner = owner; Id = id; Converter = converter; Plan = plan; Notes = notes; Errors = errors.Concat(plan.Errors).ToArray(); SourceSha256 = source; TargetSha256 = target; Generation = generation; } public override string ToString() { return string.Join("\n", new string[1] { HexText.Format("import_review", Id) }.Concat(Plan.Values.Select((ConversionValue value) => value.SourceId + " → " + value.TargetId + " = " + value.Value)).Concat(Notes).Concat(Errors.Select((string error) => HexText.Format("import_error", error))) .Concat(Plan.BindingConflicts.Select((ConversionConflict conflict) => HexText.Format("import_collision", conflict.TargetId))) .Concat(new string[2] { "Source SHA256: " + SourceSha256, "Target SHA256: " + TargetSha256 })); } } private readonly ConfigFile config; private readonly List<IDisposable> registrations = new List<IDisposable>(); private readonly int thread = Thread.CurrentThread.ManagedThreadId; private bool disposed; private static readonly string[] kinds = new string[4] { "vat", "as", "as-guard", "vat-preset" }; internal HexImport(ConfigFile config) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown this.config = config; try { string[] array = kinds; foreach (string text in array) { string id = text; registrations.Add(MeadworksConversion.Register(new ConversionRegistration("hex." + id, "com.meadworks.hex", id.StartsWith("vat", StringComparison.Ordinal) ? "com.icecub.valheimadmintool" : "liveriadevs.valheim.achievementsync", id.StartsWith("vat", StringComparison.Ordinal) ? "Valheim_Admin_Tool" : ("AchievementSync" + ((id == "as-guard") ? " (Crucible guard)" : " (Hex preferences)")), (Func<bool>)(() => !disposed && File.Exists(SourcePath(id)) && MeadworksHeadless.AllowsUi), (Func<object>)(() => Preview(id)), (Func<object, IReadOnlyDictionary<string, string>, bool, object>)delegate(object value, IReadOnlyDictionary<string, string> resolutions, bool backup) { if (!backup) { throw new InvalidOperationException(HexText.Text("import_backup_required")); } return Apply((value as PreviewDocument) ?? throw new ArgumentException("Wrong Hex import preview."), resolutions); }))); } } catch { Dispose(); throw; } } public void Dispose() { if (disposed) { return; } disposed = true; foreach (IDisposable registration in registrations) { registration.Dispose(); } registrations.Clear(); } private void Check() { if (disposed || !Plugin.Ready || thread != Thread.CurrentThread.ManagedThreadId) { throw new InvalidOperationException(HexText.Text("import_unavailable")); } } private static string SourcePath(string id) { return Path.Combine(Paths.ConfigPath, (id == "vat") ? "com.icecub.valheimadmintool.cfg" : ((id == "vat-preset") ? "com.icecub.valheimadmintool.cheats.cfg" : "liveriadevs.valheim.achievementsync.cfg")); } private static string Read(string path, out string hash) { using FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); if (fileStream.Length > 1048576) { throw new IOException("Reference config exceeds 1 MiB."); } using (SHA256 sHA = SHA256.Create()) { hash = BitConverter.ToString(sHA.ComputeHash(fileStream)).Replace("-", ""); } fileStream.Position = 0L; using StreamReader streamReader = new StreamReader(fileStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), detectEncodingFromByteOrderMarks: true); return streamReader.ReadToEnd(); } private static string Hash(string text) { using SHA256 sHA = SHA256.Create(); return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", ""); } private ConfigFile Owner(string id) { if (id != "as-guard") { return config; } ConfigEntry<bool> val = default(ConfigEntry<bool>); ConfigEntry<KeyboardShortcut> val2 = default(ConfigEntry<KeyboardShortcut>); if (!Chainloader.PluginInfos.TryGetValue("com.meadworks.crucible", out var value) || (Object)(object)value.Instance == (Object)null || !value.Instance.Config.TryGetEntry<bool>("Achievements", "SyncPastStats", ref val) || !value.Instance.Config.TryGetEntry<KeyboardShortcut>("Achievements", "ResyncKey", ref val2)) { throw new InvalidOperationException(HexText.Text("import_guard_unavailable")); } return value.Instance.Config; } private static string EntryId(ConfigEntryBase entry) { return entry.Definition.Section + "." + entry.Definition.Key; } private static ConfigEntryBase Entry(ConfigFile owner, string target) { return owner[owner.Keys.Single((ConfigDefinition key) => key.Section + "." + key.Key == target)]; } private ConfigEntryBase MappedEntry(string id, string logical) { if (id == "as-guard") { return Entry(Owner(id), logical); } if (logical == "menu") { return (ConfigEntryBase)(object)Plugin.Settings.MenuKey; } if (logical.StartsWith("action:", StringComparison.Ordinal)) { return (ConfigEntryBase)(object)Plugin.Settings.ActionHotkeys[logical.Substring(7)]; } if (logical.StartsWith("hotkey:", StringComparison.Ordinal)) { return (ConfigEntryBase)(object)Plugin.Settings.Hotkey(logical.Substring(7)); } return Plugin.Settings.PreferenceEntries()[logical.Substring(11)]; } private static string ConfigHash(ConfigFile owner) { string hash; return Hash((File.Exists(owner.ConfigFilePath) ? Read(owner.ConfigFilePath, out hash) : "missing") + "\n" + string.Join("\n", from key in owner.Keys.OrderBy<ConfigDefinition, string>((ConfigDefinition key) => key.Section, StringComparer.Ordinal).ThenBy<ConfigDefinition, string>((ConfigDefinition key) => key.Key, StringComparer.Ordinal) select key.Section + "." + key.Key + "=" + TomlTypeConverter.ConvertToString(owner[key].BoxedValue, owner[key].SettingType))); } private string TargetHash(string id) { if (!(id == "vat-preset")) { return ConfigHash(Owner(id)); } return Hash(HexPresets.ImportDisk()); } internal PreviewDocument Preview(string id) { //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Expected O, but got Unknown //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Expected O, but got Unknown //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown Check(); if (!kinds.Contains(id)) { throw new ArgumentException("Unknown Hex source import."); } string hash; string text = Read(SourcePath(id), out hash); IReadOnlyList<KeyValuePair<string, string>> readOnlyList = CfgText.Read(text, "source"); List<ConversionRule> list = new List<ConversionRule>(); List<KeyValuePair<string, string>> list2 = new List<KeyValuePair<string, string>>(); List<string> list3 = new List<string>(); List<string> list4 = new List<string>(); if (id == "vat-preset") { list3.Add(HexText.Text("import_preset_note")); } if (readOnlyList.Count == 0 && text.Any((char character) => !char.IsWhiteSpace(character)) && !text.TrimStart().StartsWith("#", StringComparison.Ordinal)) { list4.Add(HexText.Text("import_format_unknown")); } foreach (KeyValuePair<string, string> item in readOnlyList) { string text2 = item.Key.Substring(7); string text3 = ((id == "vat-preset") ? HexSourceImport.PresetKey(text2) : HexSourceImport.Target(id, text2)); if (text3 == null) { string text4 = HexSourceImport.Referral(text2); list3.Add((text4 != null) ? HexText.Format("import_owner", text2, text4) : HexText.Format("import_unknown", text2)); continue; } ConfigEntryBase val = ((id == "vat-preset") ? Plugin.Settings.PreferenceEntries()[text3] : MappedEntry(id, text3)); if (val.SettingType == typeof(KeyboardShortcut) && string.IsNullOrWhiteSpace(item.Value)) { list3.Add(HexText.Format("import_unassigned", text2)); continue; } string text5 = ((id == "vat-preset") ? text3 : EntryId(val)); string text6 = ((val.SettingType == typeof(KeyboardShortcut)) ? "KeyboardShortcut" : val.SettingType.Name); string text7 = ((val.Description.AcceptableValues is AcceptableValueRange<int> val2) ? ("From " + val2.MinValue + " to " + val2.MaxValue) : ""); list.Add(new ConversionRule(item.Key, text5, text6, text7, false, val.SettingType == typeof(KeyboardShortcut))); list2.Add(item); } ConfigConverter val3 = new ConfigConverter(new ConversionMapping(1, id, 0, (IEnumerable<ConversionRule>)list)); ConversionPreview val4 = val3.Preview((IEnumerable<KeyValuePair<string, string>>)list2); if (id != "vat-preset") { foreach (string item2 in Collisions(Owner(id), val4.Values.GroupBy<ConversionValue, string>((ConversionValue item) => item.TargetId, StringComparer.Ordinal).ToDictionary((IGrouping<string, ConversionValue> group) => group.Key, (IGrouping<string, ConversionValue> group) => group.First().Value))) { list3.Add(HexText.Format("import_collision", item2)); } } return new PreviewDocument(this, id, val3, val4, list3.Distinct().ToArray(), list4, hash, TargetHash(id), Plugin.Session.Generation); } private void Admission(PreviewDocument preview) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) Check(); if (preview.Owner != this) { throw new ArgumentException("Preview belongs to another Hex import."); } Read(SourcePath(preview.Id), out string hash); if (hash != preview.SourceSha256 || preview.TargetSha256 != TargetHash(preview.Id) || preview.Generation != Plugin.Session.Generation) { throw new InvalidOperationException(HexText.Text("import_stale")); } if (preview.Errors.Count != 0) { throw new InvalidOperationException(HexText.Text("import_invalid")); } if (preview.Id == "vat-preset") { return; } string text = ((preview.Id == "as-guard") ? "com.meadworks.crucible" : "com.meadworks.hex"); ConfigEntryMetadata val = default(ConfigEntryMetadata); foreach (ConversionValue value in preview.Plan.Values) { if (!MeadworksConfig.TryGetMetadata(Entry(Owner(preview.Id), value.TargetId), ref val) || val.ProductId != text || (int)val.Scope != 0 || !val.Decision.Allowed || val.Decision.RequiresServerAmendment) { throw new InvalidOperationException(HexText.Text("import_unavailable")); } } } private object Apply(PreviewDocument preview, IReadOnlyDictionary<string, string> resolutions) { Admission(preview); if (preview.Plan.Values.Count == 0) { return HexText.Text("import_no_changes"); } Dictionary<string, string> choices = resolutions.Where<KeyValuePair<string, string>>((KeyValuePair<string, string> pair) => !pair.Key.StartsWith("binding:", StringComparison.Ordinal)).ToDictionary((KeyValuePair<string, string> pair) => pair.Key, (KeyValuePair<string, string> pair) => pair.Value); Dictionary<string, string> bindings = resolutions.Where<KeyValuePair<string, string>>((KeyValuePair<string, string> pair) => pair.Key.StartsWith("binding:", StringComparison.Ordinal)).ToDictionary((KeyValuePair<string, string> pair) => pair.Key.Substring(8), (KeyValuePair<string, string> pair) => pair.Value); if (preview.Id == "vat-preset") { ConversionResult val = preview.Converter.Apply(preview.Plan, (IConversionTarget)(object)new PresetTarget(this, preview), (IReadOnlyDictionary<string, string>)choices, (IReadOnlyDictionary<string, string>)null); return HexText.Format("import_applied", val.Written); } ConversionResult result = null; if (!MeadworksConfig.AmendBatch((preview.Id == "as-guard") ? "com.meadworks.crucible" : "com.meadworks.hex", (IReadOnlyList<ConfigEntryBase>)preview.Plan.Values.Select((ConversionValue value) => Entry(Owner(preview.Id), value.TargetId)).Distinct().ToArray(), (Action)delegate { Admission(preview); result = preview.Converter.Apply(preview.Plan, (IConversionTarget)(object)new CheckedTarget(this, preview), (IReadOnlyDictionary<string, string>)choices, (IReadOnlyDictionary<string, string>)bindings); }, (string)null).Applied || result == null) { throw new InvalidOperationException(HexText.Text("import_unavailable")); } return HexText.Format("import_applied", result.Written); } private IEnumerable<string> Collisions(ConfigFile owner, IReadOnlyDictionary<string, object> values) { List<ConfigFile> owners = new List<ConfigFile> { config }; if (Chainloader.PluginInfos.TryGetValue("com.meadworks.crucible", out var value) && (Object)(object)value.Instance != (Object)null) { owners.Add(value.Instance.Config); } foreach (KeyValuePair<string, object> pair in values) { if (Entry(owner, pair.Key).SettingType != typeof(KeyboardShortcut)) { continue; } HotkeyChord chord = HotkeyChord.Parse(Convert.ToString(pair.Value, CultureInfo.InvariantCulture)); if (chord.IsNone) { continue; } foreach (ConfigFile other in owners.Distinct()) { foreach (ConfigDefinition key in other.Keys) { ConfigEntryBase val = other[key]; if (!(val.SettingType != typeof(KeyboardShortcut)) && (other != owner || !values.ContainsKey(EntryId(val))) && chord == MeadworksInput.Chord((KeyboardShortcut)val.BoxedValue)) { yield return pair.Key + " / " + EntryId(val); } } } } } } internal static class HexPauseMenu { internal const string Id = "hex"; private static IDisposable? registration; internal static void Tick() { if (!Plugin.Ready || !Plugin.Active || !MeadworksHeadless.AllowsUi) { Reset(); } else if (registration == null) { registration = MeadworksMenu.Register("hex", "Hex", (Action)Open, (Func<bool>)(() => Plugin.Ready && Plugin.Active && (Object)(object)Player.m_localPlayer != (Object)null), 100); } } private static void Open() { if (!Plugin.Ready || !Plugin.Active || (Object)(object)Player.m_localPlayer == (Object)null) { return; } if (Menu.IsVisible()) { Menu instance = Menu.instance; if (instance != null) { instance.OnClose(); } } HexWindow.Open(); } internal static void Reset() { registration?.Dispose(); registration = null; } } internal static class HexPolicy { internal static bool Available { get { if (Plugin.Ready && Plugin.Active && Plugin.Session.AuthorityReady && HexMovement.Owned((Character)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead()) { return MeadworksConfig.EditDecision((ConfigScope)1, true, (ServerCrucible?)null).Allowed; } return false; } } private static ConfigEntry<T>? Entry<T>(string key) { if (!Available || !Chainloader.PluginInfos.TryGetValue("com.meadworks.crucible", out var value) || (Object)(object)value.Instance == (Object)null) { return null; } ConfigEntry<T> result = default(ConfigEntry<T>); if (!value.Instance.Config.TryGetEntry<T>("Mischief", key, ref result)) { return null; } return result; } internal static string SetAccess(MischiefCategory category, MischiefAccess value) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (!Enum.IsDefined(typeof(MischiefCategory), category) || !Enum.IsDefined(typeof(MischiefAccess), value)) { return HexText.Text("ui_policy_failed"); } return Amend<MischiefAccess>(MischiefPolicy.SettingKey(category), value); } internal static string ValidatePlayers(string value) { if (value.Length > 50176) { return HexText.Text("ui_policy_invalid"); } IReadOnlyList<string> readOnlyList = default(IReadOnlyList<string>); MischiefPlayers.Parse(value, ref readOnlyList); if (readOnlyList.Count != 0) { return HexText.Text("ui_policy_invalid"); } return ""; } internal static string SetPlayers(string value) { if (ValidatePlayers(value).Length != 0) { return HexText.Text("ui_policy_invalid"); } IReadOnlyList<string> readOnlyList = default(IReadOnlyList<string>); MischiefPlayers val = MischiefPlayers.Parse(value, ref readOnlyList); return Amend("ListedPlayers", val.Format()); } private static string Amend<T>(string key, T value) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<T> val = Entry<T>(key); if (val == null) { return HexText.Text("ui_policy_unavailable"); } try { ConfigAmendResult val2 = MeadworksConfig.Amend<T>(val, "com.meadworks.crucible", (ConfigScope)1, value, key, true); return val2.Applied ? HexText.Text("ui_policy_submitted") : MeadworksBlockedOptions.Reason(val2.Decision.Reason); } catch { return HexText.Text("ui_policy_failed"); } } } internal sealed class HexPresetDocument { internal string Selected = ""; internal readonly Dictionary<string, Dictionary<string, object>> Presets = new Dictionary<string, Dictionary<string, object>>(StringComparer.OrdinalIgnoreCase); internal HexPresetDocument Copy() { HexPresetDocument hexPresetDocument = new HexPresetDocument { Selected = Selected }; foreach (KeyValuePair<string, Dictionary<string, object>> preset in Presets) { hexPresetDocument.Presets.Add(preset.Key, new Dictionary<string, object>(preset.Value, StringComparer.Ordinal)); } return hexPresetDocument; } } internal static class HexPresetJson { internal const int MaximumCharacters = 131072; internal const int MaximumPresets = 32; internal static bool NameValid(string name) { if (!string.IsNullOrWhiteSpace(name) && name.Length <= 64 && name.Trim() == name) { return !name.Any(char.IsControl); } return false; } internal static HexPresetDocument Read(string text, Func<string, object, bool> valid) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Invalid comparison between Unknown and I4 //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Invalid comparison between Unknown and I4 //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Invalid comparison between Unknown and I4 if (text == "") { return new HexPresetDocument(); } if (text.Length > 131072) { throw new FormatException("Preset file exceeds its size limit."); } using StringReader stringReader = new StringReader(text); JsonTextReader val = new JsonTextReader((TextReader)stringReader) { MaxDepth = 8, DateParseHandling = (DateParseHandling)0 }; try { JObject val2 = JObject.Load((JsonReader)(object)val, new JsonLoadSettings { DuplicatePropertyNameHandling = (DuplicatePropertyNameHandling)2 }); if (((JsonReader)val).Read()) { throw new FormatException("Trailing preset content."); } if (!val2.Properties().Any((JProperty p) => p.Name != "version" && p.Name != "selected" && p.Name != "presets")) { JToken obj = val2["version"]; if (obj != null && (int)obj.Type == 6 && Extensions.Value<long>((IEnumerable<JToken>)val2["version"]) == 1) { JToken obj2 = val2["selected"]; if (obj2 != null && (int)obj2.Type == 8) { JToken obj3 = val2["presets"]; JObject val3 = (JObject)(object)((obj3 is JObject) ? obj3 : null); if (val3 != null) { HexPresetDocument hexPresetDocument = new HexPresetDocument { Selected = Extensions.Value<string>((IEnumerable<JToken>)val2["selected"]) }; if (((JContainer)val3).Count > 32) { throw new FormatException("Too many presets."); } foreach (JProperty item in val3.Properties()) { if (NameValid(item.Name)) { JToken value = item.Value; JObject val4 = (JObject)(object)((value is JObject) ? value : null); if (val4 != null && !hexPresetDocument.Presets.ContainsKey(item.Name)) { Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.Ordinal); foreach (JProperty item2 in val4.Properties()) { object obj4; if ((int)item2.Value.Type == 9) { obj4 = Extensions.Value<bool>((IEnumerable<JToken>)item2.Value); } else { if ((int)item2.Value.Type != 6) { throw new FormatException("Preset values must be booleans or integers."); } long num = Extensions.Value<long>((IEnumerable<JToken>)item2.Value); if (num < int.MinValue || num > int.MaxValue) { throw new FormatException("Preset integer outside range."); } obj4 = (int)num; } if (!valid(item2.Name, obj4)) { throw new FormatException("Unknown or invalid preset preference."); } dictionary.Add(item2.Name, obj4); } hexPresetDocument.Presets.Add(item.Name, dictionary); continue; } } throw new FormatException("Invalid or duplicate preset name."); } if (hexPresetDocument.Selected != "" && !hexPresetDocument.Presets.ContainsKey(hexPresetDocument.Selected)) { throw new FormatException("Selected preset missing."); } return hexPresetDocument; } } } } throw new FormatException("Unsupported preset document."); } finally { ((IDisposable)val)?.Dispose(); } } internal static string Write(HexPresetDocument document) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) JObject val = new JObject(); foreach (KeyValuePair<string, Dictionary<string, object>> item in document.Presets.OrderBy<KeyValuePair<string, Dictionary<string, object>>, string>((KeyValuePair<string, Dictionary<string, object>> p) => p.Key, StringComparer.OrdinalIgnoreCase)) { JObject val2 = new JObject(); foreach (KeyValuePair<string, object> item2 in item.Value.OrderBy<KeyValuePair<string, object>, string>((KeyValuePair<string, object> p) => p.Key, StringComparer.Ordinal)) { val2.Add(item2.Key, JToken.FromObject(item2.Value)); } val.Add(item.Key, (JToken)(object)val2); } return ((JToken)new JObject { ["version"] = JToken.op_Implicit(1), ["selected"] = JToken.op_Implicit(document.Selected), ["presets"] = (JToken)(object)val }).ToString((Formatting)1, Array.Empty<JsonConverter>()) + "\n"; } } internal static class HexWindow { [HarmonyPatch(typeof(KitWindow), "Pad")] private static class PadRows { private static bool Prefix(KitWindow __instance, PadButton button) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Invalid comparison between Unknown and I4 //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (__instance == HexWindow.window) { KitWindow? window = HexWindow.window; if (window != null && window.IsOpen && !MeadworksInput.Typing && KitAlmanacDialog.Active == null && list != null && ((int)button == 12 || (int)button == 13)) { EventSystem current = EventSystem.current; GameObject val = ((current != null) ? current.currentSelectedGameObject : null); if ((Object)(object)val == (Object)null || !val.transform.IsChildOf((Transform)(object)list.Root)) { return true; } list.Tick(); int num = ((list.FocusedKey != null) ? keys.IndexOf(list.FocusedKey) : (-1)); int num2 = num + (((int)button == 13) ? 1 : (-1)); if (num < 0 || num2 < 0 || num2 >= keys.Count) { return true; } MeadworksInput.PadConsume(button); if (CatalogTab) { PreserveCatalogColumn(val, keys[num2]); } else { list.Focus(keys[num2]); } return false; } } return true; } } private static IReadOnlyList<HexSpawnCatalog.Entry> catalog = Array.Empty<HexSpawnCatalog.Entry>(); private static readonly List<Selectable> catalogControls = new List<Selectable>(); private static readonly List<GameObject> catalogObjects = new List<GameObject>(); private static readonly Dictionary<RectTransform, List<Button>> catalogTiles = new Dictionary<RectTransform, List<Button>>(); private static KitTextField? catalogField; private static KitToggle? catalogEnable; private static KitToggle? catalogKind; private static TMP_Text? catalogCount; private static string search = ""; private static string category = ""; private static bool catalogDirty; private static bool spawnCreatures; private static KitWindow? window; private static KitVirtualList? list; private static KitToggle? master; private static Button? close; private static Button? panic; private static float nextSkills; private static string skillShape = ""; private static TMP_Text? hint; private static string tab = "cheats"; private static string language = ""; private static long revision; private static bool dirty; private static bool focusTabAfterDraw; private static Player? actor; private static long session = -1L; private static int debugRadius = 50; private static readonly List<Button> tabs = new List<Button>(); private static readonly List<string> keys = new List<string>(); private static readonly Dictionary<RectTransform, List<Action>> cleanup = new Dictionary<RectTransform, List<Action>>(); private static readonly Dictionary<RectTransform, Action> updates = new Dictionary<RectTransform, Action>(); private static bool CatalogTab => tab == "spawn"; private static void SpawnProtectionRow(List<KitVirtualRow> rows) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown rows.Add(new KitVirtualRow("spawn_protection", 100f, (Action<RectTransform>)delegate(RectTransform rect) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) cleanup[rect] = new List<Action>(); string text = HexText.Text("spawn_protection_label"); KitAlmanacDialog.Label((Transform)(object)rect, "Label", text, Vector2.zero, new Vector2(350f, 35f), 16f); KitAlmanacDialog.Label((Transform)(object)rect, "Legend", HexText.Text("spawn_protection_legend"), new Vector2(0f, -40f), new Vector2(708f, 55f), 14f); KitToggle toggle = KitToggle.Create(rect, "Value", HexSpawnProtection.IsEnabled, (Action<bool>)delegate(bool value) { Result(HexSpawnProtection.SetEnabled(value)); }, new Vector2(380f, 0f), new Vector2(140f, 32f), Ui("on"), Ui("off")); toggle.Tooltip(text, HexText.Text("spawn_protection_legend")); cleanup[rect].Add((Action)toggle.Dispose); updates[rect] = delegate { //IL_0067: Unknown result type (might be due to invalid IL or missing references) toggle.SetValue(HexSpawnProtection.IsEnabled); BlockedOption val = MeadworksMischief.Query("com.meadworks.hex", "SpawnProtection", (MischiefCategory)3); toggle.SetUsable(Plugin.Settings.Enabled.Value && Plugin.Settings.DebugTools.Value && HexMovement.Owned((Character)(object)Player.m_localPlayer) && val.Allowed, val.Allowed ? "" : MeadworksBlockedOptions.Reason(val.Reason)); }; updates[rect](); Focus(rect, "spawn_protection"); }, (Action<RectTransform>)Unbind)); } private static void CatalogHeader() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) try { catalog = (spawnCreatures ? HexSpawnCatalog.Creatures() : HexSpawnCatalog.Items()); } catch { catalog = Array.Empty<HexSpawnCatalog.Entry>(); Result(HexText.Text("spawn_unsupported")); } category = ""; catalogField = KitTextField.Create(window.Panel, "CatalogSearch", (KitFieldMode)0, new Vector2(200f, -60f), new Vector2(360f, 32f), Ui("search"), (string)null); if (catalogField != null) { Help(((Component)catalogField.Input).gameObject, Ui("search"), HexText.Text("help_catalog_search")); catalogField.Text = search; catalogField.Changed += SearchChanged; catalogControls.Add((Selectable)(object)catalogField.Input); window.Focusable((Selectable)(object)catalogField.Input, 1, 1); } Button val = KitButton.Create(window.Panel, "CatalogCategory", Ui("category"), (Action)delegate { string[] values = catalog.SelectMany(Categories).Distinct<string>(StringComparer.Ordinal).OrderBy<string, string>(CategoryName, StringComparer.CurrentCulture) .Prepend("") .ToArray(); string[] names = values.Select((string value) => (value.Length != 0) ? (CategoryName(value) + " (" + value + ")") : Ui("all")).ToArray(); KitAlmanacChoice.Open(window, Ui("category"), (IReadOnlyList<string>)names, (IReadOnlyCollection<string>)(object)Array.Empty<string>(), false, (Action<IReadOnlyList<string>>)delegate(IReadOnlyList<string> selected) { int num = ((selected.Count == 1) ? Array.IndexOf(names, selected[0]) : (-1)); if (num >= 0) { category = values[num]; catalogDirty = true; } }); }, new Vector2(580f, -60f), new Vector2(200f, 32f)); Button val2 = KitButton.Create(window.Panel, "CatalogReload", Ui("reload"), (Action)delegate { dirty = true; }, new Vector2(800f, -60f), new Vector2(150f, 32f)); Help(((Component)val).gameObject, Ui("category"), HexText.Text("help_catalog_category")); Help(((Component)val2).gameObject, Ui("reload"), HexText.Text("help_catalog_reload")); catalogControls.Add((Selectable)(object)val); catalogControls.Add((Selectable)(object)val2); catalogObjects.Add(((Component)val).gameObject); catalogObjects.Add(((Component)val2).gameObject); window.Focusable((Selectable)(object)val, 2, 1); window.Focusable((Selectable)(object)val2, 3, 1); catalogEnable = KitToggle.Create(window.Panel, "CatalogEnabled", Plugin.Settings.Spawning.Value, (Action<bool>)delegate(bool value) { Plugin.Settings.SetPreference("spawning", value); }, new Vector2(200f, -104f), new Vector2(180f, 30f), Ui("on"), Ui("off")); catalogEnable.Tooltip(Label("spawning"), HexText.Text("spawning")); catalogControls.Add((Selectable)(object)catalogEnable.Button); window.Focusable((Selectable)(object)catalogEnable.Button, 1, 2); catalogKind = KitToggle.Create(window.Panel, "CatalogKind", spawnCreatures, (Action<bool>)delegate(bool value) { spawnCreatures = value; dirty = true; }, new Vector2(390f, -104f), new Vector2(180f, 30f), Ui("creatures"), Ui("items")); catalogKind.Tooltip(Ui("spawn"), HexText.Text("help_spawn_kind")); catalogControls.Add((Selectable)(object)catalogKind.Button); window.Focusable((Selectable)(object)catalogKind.Button, 2, 2); catalogCount = KitAlmanacDialog.Label((Transform)(object)window.Panel, "CatalogCount", "", new Vector2(580f, -104f), new Vector2(370f, 34f), 14f); catalogObjects.Add(((Component)catalogCount).gameObject); KitAlmanacDialog.Place(list.Root, new Vector2(200f, -148f), new Vector2(750f, 462f)); DrawCatalog(); } private static void SearchChanged(string value) { search = value; catalogDirty = true; } private static IEnumerable<string> Categories(HexSpawnCatalog.Entry entry) { return from value in entry.Category.Split(',') select value.Trim() into value where value.Length > 0 select value; } private static string CategoryName(string value) { if (value == "Unclassified") { return Ui("unclassified"); } string text = "$" + (spawnCreatures ? "biome_" : "itemtype_") + value.ToLowerInvariant(); Localization instance = Localization.instance; string text2 = ((instance != null) ? instance.Localize(text) : null) ?? text; if (!(text2 == text) && !(text2 == "[" + text.TrimStart('$') + "]")) { return text2; } return value; } private static void TickCatalog() { if (CatalogTab) { if (catalogDirty) { DrawCatalog(); } KitToggle? obj = catalogEnable; if (obj != null) { obj.SetValue(Plugin.Settings.Spawning.Value); } KitToggle? obj2 = catalogEnable; if (obj2 != null) { obj2.SetLabels(Ui("on"), Ui("off")); } KitToggle? obj3 = catalogKind; if (obj3 != null) { obj3.SetValue(spawnCreatures); } KitToggle? obj4 = catalogKind; if (obj4 != null) { obj4.SetLabels(Ui("creatures"), Ui("items")); } KitToggle? obj5 = catalogEnable; if (obj5 != null) { obj5.SetUsable(Plugin.Settings.Enabled.Value && HexMovement.Owned((Character)(object)Player.m_localPlayer) && MeadworksMischief.Decide("com.meadworks.hex", (MischiefCategory)1).Allowed, ""); } } } private static void DrawCatalog() { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown catalogDirty = false; if (HexWindow.list == null || !CatalogTab) { return; } HexSpawnCatalog.Entry[] array = catalog.Where((HexSpawnCatalog.Entry entry) => (Object)(object)entry.Prefab != (Object)null && entry.Matches(search) && (category.Length == 0 || Categories(entry).Contains<string>(category, StringComparer.Ordinal))).ToArray(); if ((Object)(object)catalogCount != (Object)null) { catalogCount.text = HexText.Format("ui_catalog_count", array.Length, (category.Length == 0) ? Ui("all") : CategoryName(category)); } List<KitVirtualRow> list = new List<KitVirtualRow>(); for (int num = 0; num < array.Length; num += 4) { HexSpawnCatalog.Entry[] entries = array.Skip(num).Take(4).ToArray(); string key = "catalog:" + entries[0].Identity; list.Add(new KitVirtualRow(key, 108f, (Action<RectTransform>)delegate(RectTransform rect) { BindCatalog(rect, key, entries); }, (Action<RectTransform>)Unbind)); } keys.Clear(); keys.AddRange(list.Select((KitVirtualRow row) => row.Key)); HexWindow.list.SetRows((IReadOnlyList<KitVirtualRow>)list, ++revision); } private static void BindCatalog(RectTransform rect, string key, HexSpawnCatalog.Entry[] entries) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) cleanup[rect] = new List<Action>(); List<Button> buttons = new List<Button>(); List<Image> locks = new List<Image>(); List<HexCatalogLiteralTooltip> tips = new List<HexCatalogLiteralTooltip>(); catalogTiles[rect] = buttons; for (int i = 0; i < entries.Length; i++) { HexSpawnCatalog.Entry entry = entries[i]; Button val = KitButton.Create(rect, "Tile" + i, "", (Action)delegate { SpawnEditor(entry); }, new Vector2((float)(i * 177), 0f), new Vector2(169f, 98f)); buttons.Add(val); locks.Add(LockBadge(((Component)val).transform, new Vector2(143f, -7f))); GameObject val2 = new GameObject("NativeIcon", new Type[2] { typeof(RectTransform), typeof(Image) }) { layer = ((Component)rect).gameObject.layer }; val2.transform.SetParent(((Component)val).transform, false); Image component = val2.GetComponent<Image>(); ((Graphic)component).raycastTarget = false; component.preserveAspect = true; component.sprite = (Sprite)(((Object)(object)entry.Icon != (Object)null) ? ((object)entry.Icon) : ((object)KitGlyphSprites.Of((KitGlyph)10))); KitAlmanacDialog.Place(((Graphic)component).rectTransform, new Vector2(60f, -5f), new Vector2(48f, 48f)); TMP_Text obj = KitAlmanacDialog.Label(((Component)val).transform, "NativeName", entry.Name, new Vector2(5f, -57f), new Vector2(159f, 36f), 13f); obj.alignment = (TextAlignmentOptions)258; obj.overflowMode = (TextOverflowModes)3; HexCatalogLiteralTooltip hexCatalogLiteralTooltip = ((Component)val).gameObject.AddComponent<HexCatalogLiteralTooltip>(); hexCatalogLiteralTooltip.Topic = entry.Name; hexCatalogLiteralTooltip.Detail = entry.Identity + "\n" + string.Join(", ", Categories(entry).Select(CategoryName)) + "\n\n" + HexText.Text("help_spawn_editor"); tips.Add(hexCatalogLiteralTooltip); } updates[rect] = delegate { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) foreach (Image item in locks) { ((Component)item).gameObject.SetActive(!MeadworksMischief.Decide("com.meadworks.hex", (MischiefCategory)1).Allowed); } for (int j = 0; j < buttons.Count; j++) { KitControlDecision val3 = KitButton.Block(buttons[j], MeadworksMischief.Query("com.meadworks.hex", "Spawn.Create", (MischiefCategory)1), Plugin.Settings.Enabled.Value && Plugin.Settings.Spawning.Value && HexMovement.Owned((Character)(object)Player.m_localPlayer)); tips[j].Literal = ((KitControlDecision)(ref val3)).Interactable; Help(((Component)buttons[j]).gameObject, tips[j].Topic, tips[j].Detail, ((KitControlDecision)(ref val3)).Tooltip); } }; cleanup[rect].Add(delegate { catalogTiles.Remove(rect); }); updates[rect](); int num = keys.IndexOf(key); for (int num2 = 0; num2 < buttons.Count; num2++) { window.Focusable((Selectable)(object)buttons[num2], num2 + 1, num + 3); } } private static void SpawnEditor(HexSpawnCatalog.Entry entry) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Invalid comparison between Unknown and I4 //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Invalid comparison between Unknown and I4 //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Invalid comparison between Unknown and I4 //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Invalid comparison between Unknown and I4 //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Invalid comparison between Unknown and I4 //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) if (!HexSpawn.Allowed || (Object)(object)entry.Prefab == (Object)null) { Result(HexText.Text("spawn_denied")); return; } KitAlmanacDialog dialog = KitAlmanacDialog.Create(window, entry.Name, new Vector2(540f, 425f)); if (dialog == null) { return; } int amount = 1; int level = 1; bool inventory = (int)entry.Kind == 1; bool tame = false; KitAlmanacDialog.Label((Transform)(object)dialog.Panel, "Identity", entry.Identity, new Vector2(20f, -50f), new Vector2(500f, 26f), 13f); KitAlmanacDialog.Label((Transform)(object)dialog.Panel, "AmountLabel", Ui("amount"), new Vector2(20f, -92f), new Vector2(185f, 30f), 16f); KitAlmanacDialog.Label((Transform)(object)dialog.Panel, "LevelLabel", Ui(((int)entry.Kind == 1) ? "quality" : "level"), new Vector2(20f, -180f), new Vector2(185f, 30f), 16f); KitAlmanacNumber count = Number("Amount", new Vector2(220f, -88f), 9999, () => amount, delegate(int value) { amount = value; }); KitAlmanacNumber quality = Number("Level", new Vector2(220f, -176f), entry.MaxQuality, () => level, delegate(int value) { level = value; }); KitToggle option = KitToggle.Create(dialog.Panel, "Option", inventory, (Action<bool>)delegate(bool value) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 if ((int)entry.Kind == 1) { inventory = value; } else { tame = value; } }, new Vector2(20f, -270f), new Vector2(500f, 32f), Ui(((int)entry.Kind == 1) ? "inventory" : "tame"), Ui(((int)entry.Kind == 1) ? "drop" : "wild")); option.Tooltip(entry.Name, HexText.Text("help_spawn_option")); dialog.Own((Action)option.Dispose); option.SetUsable((int)entry.Kind == 1 || entry.Tameable, ""); Button create = KitButton.Create(dialog.Panel, "Spawn", Ui("spawn"), (Action)Submit, new Vector2(280f, -350f), new Vector2(240f, 34f)); Button val = KitButton.Create(dialog.Panel, "Cancel", Ui("close"), (Action)dialog.Dispose, new Vector2(20f, -350f), new Vector2(240f, 34f)); Help(((Component)create).gameObject, Ui("spawn"), HexText.Text("help_spawn_submit") + "\n\n" + HexText.Text("spawning")); Help(((Component)val).gameObject, Ui("close"), HexText.Text("help_close")); dialog.Tick += delegate { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 if (!HexSpawn.Allowed || (Object)(object)entry.Prefab == (Object)null) { dialog.Dispose(); } else { count.Set(amount.ToString(CultureInfo.InvariantCulture), (double?)null); quality.Set(level.ToString(CultureInfo.InvariantCulture), (double?)null); option.SetUsable((int)entry.Kind == 1 || entry.Tameable, ""); ((Selectable)create).interactable = count.Field.Valid && quality.Field.Valid; } }; dialog.Window.Focusable((Selectable)(object)count.Field.Input, 1, 0); dialog.Window.Focusable((Selectable)(object)count.Less, 0, 0); dialog.Window.Focusable((Selectable)(object)count.More, 2, 0); if ((Object)(object)count.Slider != (Object)null) { dialog.Window.Focusable((Selectable)(object)count.Slider, 1, 1); } dialog.Window.Focusable((Selectable)(object)quality.Field.Input, 1, 2); dialog.Window.Focusable((Selectable)(object)quality.Less, 0, 2); dialog.Window.Focusable((Selectable)(object)quality.More, 2, 2); if ((Object)(object)quality.Slider != (Object)null) { dialog.Window.Focusable((Selectable)(object)quality.Slider, 1, 3); } dialog.Window.Focusable((Selectable)(object)option.Button, 1, 4); dialog.Window.Focusable((Selectable)(object)val, 0, 5); dialog.Window.Focusable((Selectable)(object)create, 2, 5); KitAlmanacNumber Number(string name, Vector2 position, int maximum, Func<int> read, Action<int> write) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Invalid comparison between Unknown and I4 int result; KitAlmanacNumber val2 = KitAlmanacNumber.Create(dialog.Panel, name, position, new Vector2(300f, 75f), read().ToString(CultureInfo.InvariantCulture), (Func<string, bool>)((string text) => int.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out result) && result >= 1 && result <= maximum), (Action<string>)delegate(string text) { if (int.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out result) && result >= 1 && result <= maximum) { write(result); } }, (Func<int, string>)((int direction) => Math.Max(1L, Math.Min(maximum, (long)read() + (long)direction)).ToString(CultureInfo.InvariantCulture)), (double?)1.0, (double?)maximum, 1.0, false, (Func<double, string>)((double number) => Math.Round(number).ToString(CultureInfo.InvariantCulture))); NumberHelp(val2, Ui((name == "Amount") ? "amount" : (((int)entry.Kind == 1) ? "quality" : "level")), HexText.Text((name == "Amount") ? "help_spawn_amount" : "help_spawn_level")); dialog.Own((Action)val2.Dispose); return val2; } void Submit() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown if (!HexSpawn.Allowed) { Result(HexText.Text("spawn_denied")); } else if (int.TryParse(count.Field.Text, NumberStyles.None, CultureInfo.InvariantCulture, out amount) && amount >= 1 && amount <= 9999 && int.TryParse(quality.Field.Text, NumberStyles.None, CultureInfo.InvariantCulture, out level) && level >= 1 && level <= entry.MaxQuality) { HexSpawnRequest request = new HexSpawnRequest(entry.Kind, entry.Identity, amount, level, tame, inventory); dialog.Dispose(); if (amount > Plugin.Settings.ConfirmSpawnAbove.Value) { KitAlmanacTextEditor.Confirm(window, Ui("spawn"), HexText.Format("spawn_confirm", amount), (Action)delegate { Result(HexSpawn.Request(request, confirmed: true)); }); } else { Result(HexSpawn.Request(request)); } } } } private static Image LockBadge(Transform parent, Vector2 position) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("AuthorityLock", new Type[2] { typeof(RectTransform), typeof(Image) }) { layer = ((Component)parent).gameObject.layer }; val.transform.SetParent(parent, false); Image component = val.GetComponent<Image>(); component.sprite = KitGlyphSprites.Of((KitGlyph)20); ((Graphic)component).raycastTarget = false; ((Graphic)component).color = KitAppearance.Color((KitColorRole)8); KitAlmanacDialog.Place(((Graphic)component).rectTransform, position, new Vector2(18f, 18f)); return component; } private static void PreserveCatalogColumn(GameObject selected, string next) { int val = 0; foreach (List<Button> value in catalogTiles.Values) { int num = value.FindIndex((Button button) => (Object)(object)button != (Object)null && (Object)(object)((Component)button).gameObject == (Object)(object)selected); if (num >= 0) { val = num; break; } } list.Focus(next); EventSystem current = EventSystem.current; GameObject first = ((current != null) ? current.currentSelectedGameObject : null); foreach (List<Button> value2 in catalogTiles.Values) { if (!value2.Any((Button button) => (Object)(object)button != (Object)null && (Object)(object)((Component)button).gameObject == (Object)(object)first)) { continue; } Button val2 = value2[Math.Min(val, value2.Count - 1)]; if ((Object)(object)val2 != (Object)null && ((Selectable)val2).IsInteractable()) { EventSystem current3 = EventSystem.current; if (current3 != null) { current3.SetSelectedGameObject(((Component)val2).gameObject); } } break; } } private static void ClearCatalog() { HexCatalogLiteralTooltip.Restore(); foreach (Selectable catalogControl in catalogControls) { KitWindow? obj = window; if (obj != null) { obj.Unfocusable(catalogControl); } } catalogControls.Clear(); if (catalogField != null) { catalogField.Changed -= SearchChanged; catalogField.Destroy(); catalogField = null; } if (catalogEnable != null) { if ((Object)(object)catalogEnable.Button != (Object)null) { KitUnity.Retire(((Component)catalogEnable.Button).gameObject); } catalogEnable.Dispose(); catalogEnable = null; } if (catalogKind != null) { if ((Object)(object)catalogKind.Button != (Object)null) { KitUnity.Retire(((Component)catalogKind.Button).gameObject); } catalogKind.Dispose(); catalogKind = null; } foreach (GameObject catalogObject in catalogObjects) { if ((Object)(object)catalogObject != (Object)null) { KitUnity.Retire(catalogObject); } } catalogObjects.Clear(); catalogCount = null; catalog = Array.Empty<HexSpawnCatalog.Entry>(); catalogTiles.Clear(); catalogDirty = false; } private static float CaptionWidth(Button button) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) TMP_Text val = (((Object)(object)button != (Object)null) ? ((Component)button).GetComponentInChildren<TMP_Text>(true) : null); if (!((Object)(object)val == (Object)null)) { return val.GetPreferredValues(val.text).x; } return 0f; } private static void Roomy(Button button) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) TMP_Text componentInChildren = ((Component)button).GetComponentInChildren<TMP_Text>(true); if (!((Object)(object)componentInChildren == (Object)null)) { RectTransform rectTransform = componentInChildren.rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; } } private static string Ui(string key) { return HexText.Text("ui_" + key); } private static string Label(string key) { return HexText.Text("label_" + key); } internal static void Tick() { if (!Plugin.Ready || !Plugin.Active || !MeadworksHeadless.AllowsUi || (Object)(object)Player.m_localPlayer == (Object)null) { Shutdown(); return; } if (window != null && ((Object)(object)actor != (Object)(object)Player.m_localPlayer || session != Plugin.Session.Generation)) { Shutdown(); } ConfigEntry<KeyboardShortcut> menuKey = Plugin.Settings.MenuKey; KitWindow? obj = window; if (MeadworksInput.Pressed(menuKey, (InputContext)((obj != null && obj.IsOpen) ? 1 : 0))) { KitWindow? obj2 = window; if (obj2 != null && obj2.IsOpen) { window.Close(); } else { Open(); } } KitWindow? obj3 = window; if (obj3 == null || !obj3.IsOpen) { return; } KitToggle? obj4 = master; if (obj4 != null) { obj4.SetValue(Plugin.Settings.Enabled.Value); } if (language != MeadworksBlockedOptions.Language) { language = MeadworksBlockedOptions.Language; dirty = true; } if (tab == "skills" && Time.unscaledTime >= nextSkills) { nextSkills = Time.unscaledTime + 1f; string text = MeadworksSkills.Registry.Revision + ":" + string.Join(",", from def in ((Character)Player.m_localPlayer).GetSkills().m_skills where def != null select (int)def.m_skill); if (text != skillShape) { skillShape = text; dirty = true; } } PadTabs(); if (dirty) { Draw(); } TickCatalog(); KitVirtualList? obj5 = list; if (obj5 != null) { obj5.Tick(); } Action[] array = updates.Values.ToArray(); for (int num = 0; num < array.Length; num++) { array[num](); } } internal static void Open() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Ready || !Plugin.Active || !MeadworksHeadless.AllowsUi || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)KitCanvas.Font == (Object)null) { return; } KitWindow? obj = window; if ((Object)(object)((obj != null) ? obj.Panel : null) == (Object)null) { Shutdown(); actor = Player.m_localPlayer; session = Plugin.Session.Generation; window = KitWindow.Create("Hex", new Vector2(980f, 680f), (Transform)null, false, false); if (window == null) { return; } TMP_Text val = KitAlmanacDialog.Label((Transform)(object)window.Panel, "Title", "Hex", new Vector2(20f, -12f), new Vector2(220f, 32f), 24f); if ((Object)(object)KitCanvas.Heading != (Object)null) { val.font = KitCanvas.Heading; } master = KitToggle.Create(window.Panel, "Master", Plugin.Settings.Enabled.Value, (Action<bool>)delegate(bool value) { MeadworksConfig.Amend((ConfigEntryBase)(object)Plugin.Settings.Enabled, (object)value, (string)null); }, new Vector2(270f, -12f), new Vector2(160f, 32f), Ui("on"), Ui("off")); master.Tooltip("Hex", HexText.Text("enabled")); window.Focusable((Selectable)(object)master.Button, 1, 0); panic = KitButton.Create(window.Panel, "Panic", Ui("panic"), (Action)delegate { Plugin.Settings.PanicReset(); }, new Vector2(620f, -12f), new Vector2(150f, 32f)); close = KitButton.Create(window.Panel, "Close", Ui("close"), (Action)delegate { KitWindow? obj3 = window; if (obj3 != null) { obj3.Close(); } }, new Vector2(800f, -12f), new Vector2(150f, 32f)); Help(((Component)panic).gameObject, Ui("panic"), HexText.Text("panic")); Help(((Component)close).gameObject, Ui("close"), HexText.Text("help_close")); window.Focusable((Selectable)(object)panic, 2, 0); window.Focusable((Selectable)(object)close, 3, 0); hint = KitAlmanacDialog.Label((Transform)(object)window.Panel, "Hint", "", new Vector2(200f, -620f), new Vector2(750f, 45f), 14f); window.Opened += delegate { dirty = true; }; window.Closed += CloseEditor; } window.Open(); dirty = true; KitToggle? obj2 = master; if ((Object)(object)((obj2 != null) ? obj2.Button : null) != (Object)null && (Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject(((Component)master.Button).gameObject); } } private static void CloseEditor() { if (window != null) { KitAlmanacDialog active = KitAlmanacDialog.Active; if (((active != null) ? active.Parent : null) == window) { KitAlmanacDialog.Active.Dispose(); } } } private static void Result(string value) { if ((Object)(object)hint != (Object)null) { hint.text = value; } } private static void Select(string value) { CloseEditor(); tab = value; dirty = (focusTabAfterDraw = true); Result(""); } private static void Draw() { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_0581: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Expected O, but got Unknown //IL_067a: Unknown result type (might be due to invalid IL or missing references) //IL_0681: Expected I4, but got Unknown //IL_06ba: Unknown result type (might be due to invalid IL or missing references) //IL_06c4: Expected O, but got Unknown if (window == null || Plugin.Settings == null) { return; } dirty = false; ClearRows(); foreach (Button tab in tabs) { window.Unfocusable((Selectable)(object)tab); ((Component)tab).gameObject.SetActive(false); ((Object)tab).name = "retired"; Object.Destroy((Object)(object)((Component)tab).gameObject); } tabs.Clear(); List<Button> list = KitTabs.Place(window.Panel, (IList<KitTab>)((IEnumerable<string>)HexMenu.Tabs).Select((Func<string, KitTab>)((string id) => new KitTab { Id = id, Caption = Ui(id), Click = delegate { Select(id); } })).ToArray(), HexWindow.tab, 20f, 60f, 160f); for (int num = 0; num < list.Count; num++) { Button val = list[num]; KitAlmanacDialog.Place((RectTransform)((Component)val).transform, new Vector2(20f, (float)(-60 - num * 48)), new Vector2(160f, 40f)); Help(((Component)val).gameObject, Ui(VisibleTabs()[num]), HexText.Format("help_tab", Ui(VisibleTabs()[num]))); tabs.Add(val); window.Focusable((Selectable)(object)val, 0, num + 1); } HexWindow.list = KitVirtualList.Create((Transform)(object)window.Panel, "HexRows", new Vector2(750f, 550f), (Func<RectTransform, RectTransform>)delegate(RectTransform parent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown GameObject val2 = new GameObject("HexRow", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent((Transform)(object)parent, false); return (RectTransform)val2.transform; }); if (HexWindow.list == null) { return; } KitAlmanacDialog.Place(HexWindow.list.Root, new Vector2(200f, -60f), new Vector2(750f, 550f)); List<KitVirtualRow> list2 = new List<KitVirtualRow>(); string[] array = HexMenu.Preferences[HexWindow.tab]; foreach (string text in array) { string name = text; ConfigEntryBase entry = Plugin.Settings.PreferenceEntries()[name]; list2.Add(new KitVirtualRow(name, (float)((name == "debug_mode") ? 144 : ((name == "local_time_minute") ? 170 : ((entry.SettingType == typeof(int)) ? 130 : 96))), (Action<RectTransform>)delegate(RectTransform rect) { BindPreference(rect, name, entry); }, (Action<RectTransform>)Unbind)); } if (HexWindow.tab == "cheats") { ActionRow(list2, "heal", HexText.Text("actions_heal"), () => HexActions.Execute(new string[1] { "heal" })); ActionRow(list2, "rested", HexText.Text("actions_rested"), () => HexActions.Execute(new string[1] { "rested" })); ActionRow(list2, "power", HexText.Text("actions_power"), delegate { KitAlmanacChoice.Open(window, HexText.Text("actions_power"), (IReadOnlyList<string>)new string[8] { "GP_Eikthyr", "GP_TheElder", "GP_Bonemass", "GP_Moder", "GP_Yagluth", "GP_Queen", "GP_Ashlands", "GP_DeepNorth" }, (IReadOnlyCollection<string>)(object)Array.Empty<string>(), false, (Action<IReadOnlyList<string>>)delegate(IReadOnlyList<string> values) { if (values.Count == 1) { Result(HexActions.Execute(new string[2] { "power", values[0] })); } }); return ""; }); } if (HexWindow.tab == "movement") { ActionRow(list2, "reset_speeds", HexText.Text("speeds_reset_all"), () => Plugin.Settings.ResetSpeeds()); } if (HexWindow.tab == "map") { ActionRow(list2, "poi", HexText.Text("poi_actual"), HexPoi.Request); ActionRow(list2, "estimatepoi", HexText.Text("poi_estimate"), HexPoi.RequestEstimate); ActionRow(list2, "clearpoi", HexText.Text("poi_clear"), HexPoi.Clear); ActionRow(list2, "reveal", HexText.Text("map_reveal"), () => HexMap.Execute(new string[2] { "map", "reveal" })); ActionRow(list2, "reset", HexText.Text("map_reset"), ConfirmMapReset); ActionRow(list2, "seed", HexText.Text("seed_label"), HexInformation.Seed); } if (HexWindow.tab == "debug") { SpawnProtectionRow(list2); list2.Add(new KitVirtualRow("debug:radius", 90f, (Action<RectTransform>)BindRadius, (Action<RectTransform>)Unbind)); array = new string[6] { "fly", "build", "kill", "drops", "tame", "event" }; foreach (string text2 in array) { string name2 = text2; ActionRow(list2, "debug_" + name2, HexText.Text("debug_" + name2), () => DebugAction(name2)); } } if (HexWindow.tab == "skills") { if (HexSkills.Catalog(out IReadOnlyList<HexSkills.Row> rows, out string message)) { foreach (HexSkills.Row item in rows) { HexSkills.Row row = item; list2.Add(new KitVirtualRow("skill:" + (int)row.Type, 100f, (Action<RectTransform>)delegate(RectTransform rect) { BindSkill(rect, row); }, (Action<RectTransform>)Unbind)); } } else { Result(message); } } if (HexWindow.tab == "presets") { PresetRows(list2); } keys.Clear(); keys.AddRange(list2.Select((KitVirtualRow val2) => val2.Key)); HexWindow.list.SetRows((IReadOnlyList<KitVirtualRow>)list2, ++revision); if (CatalogTab) { CatalogHeader(); } KitToggle? obj = master; if (obj != null) { obj.SetLabels(Ui("on"), Ui("off")); } KitToggle? obj2 = master; if (obj2 != null) { obj2.Tooltip("Hex", HexText.Text("enabled")); } if ((Object)(object)close != (Object)null) { Help(((Component)close).gameObject, Ui("close"), HexText.Text("help_close")); } if ((Object)(object)panic != (Object)null) { Help(((Component)panic).gameObject, Ui("panic"), HexText.Text("panic")); } if ((Object)(object)close != (Object)null) { GameButtons.Caption(((Component)close).gameObject, Ui("close")); } if ((Object)(object)panic != (Object)null) { GameButtons.Caption(((Component)panic).gameObject, Ui("panic")); } if (focusTabAfterDraw && (Object)(object)EventSystem.current != (Object)null) { focusTabAfterDraw = false; int num3 = Array.IndexOf(VisibleTabs(), HexWindow.tab); if (KitAlmanacDialog.Active == null && num3 >= 0 && num3 < tabs.Count) { EventSystem.current.SetSelectedGameObject(((Component)tabs[num3]).gameObject); } } } private static string[] VisibleTabs() { return HexMenu.Tabs.ToArray(); } private static void PadTabs() { KitWindow? obj = window; if (obj == null || !obj.IsOpen || !MeadworksInput.Allows((InputContext)1) || MeadworksInput.Typing || KitAlmanacDialog.Active != null) { return; } EventSystem current = EventSystem.current; GameObject val = ((current != null) ? current.currentSelectedGameObject : null); if ((Object)(object)val == (Object)null || !val.activeInHierarchy || !val.transform.IsChildOf((Transform)(object)window.Panel)) { return; } Transform parent = ((Transform)window.Panel).parent; int num = ((Transform)window.Panel).GetSiblingIndex() + 1; while ((Object)(object)parent != (Object)null && num < parent.childCount) { if (((Component)parent.GetChild(num)).gameObject.activeInHierarchy) { return; } num++; } string[] array = VisibleTabs(); int num2 = Array.IndexOf(array, tab); if (num2 >= 0 && array.Length != 0) { if (MeadworksInput.PadDown((PadButton)4)) { MeadworksInput.PadConsume((PadButton)4); Select(array[(num2 + array.Length - 1) % array.Length]); } else if (MeadworksInput.PadDown((PadButton)5)) { MeadworksInput.PadConsume((PadButton)5); Select(array[(num2 + 1) % array.Length]); } } } private static void BindPreference(RectTransform rect, string key, ConfigEntryBase entry) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) cleanup[rect] = new List<Action>(); TMP_Text description = KitAlmanacDialog.Label((Transform)(object)rect, "Description", HexText.Text(key), new Vector2(0f, -46f), new Vector2(700f, 44f), 12f); TMP_Text label = KitAlmanacDialog.Label((Transform)(object)rect, "Label", Label(key), Vector2.zero, new Vector2(350f, 36f), 16f); Func<bool> allowed = () => Plugin.Settings.Enabled.Value && Plugin.Settings.MayUse(key) && ((!key.StartsWith("achievements_", StringComparison.Ordinal) && !key.StartsWith("clear_", StringComparison.Ordinal)) || HexAchievements.Available); Button val = KitButton.Create(rect, "Reset", Ui("reset"), (Action)delegate { Plugin.Settings.SetPreference(key, Plugin.Settings.SafeValue(key)); }, new Vector2(640f, 0f), new Vector2(68f, 32f)); Roomy(val); Help(((Component)val).gameObject, Ui("reset"), HexText.Format("help_reset", Label(key)) + "\n\n" + HexText.Text(key)); (float, float) tuple = HexMenu.ResetSpan(CaptionWidth(val)); KitAlmanacDialog.Place((RectTransform)((Component)val).transform, new Vector2(tuple.Item1, 0f), new Vector2(tuple.Item2, 32f)); Action action; AcceptableValueRange<int> range; if (entry.SettingType == typeof(bool)) { KitToggle toggle = KitToggle.Create(rect, "Value", (bool)entry.BoxedValue, (Action<bool>)delegate(bool value) { Plugin.Settings.SetPreference(key, value); if (key == "skill_editor") { dirty = true; } }, new Vector2(380f, 0f), new Vector2(HexMenu.ValueWidth(200f, tuple.Item1), 32f), Ui("on"), Ui("off")); cleanup[rect].Add((Ac