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 EasyLiving v3.1.0
plugins/EasyLiving/EasyLiving.dll
Decompiled 3 weeks 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.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EasyLiving.Compatibility; using EasyLiving.Configuration; using EasyLiving.Input; using EasyLiving.Localization; using EasyLiving.Modules.AutoRepair; using EasyLiving.Modules.CraftFromChests; using EasyLiving.Modules.ManualStationResources; using EasyLiving.Modules.NearbyStorage; using EasyLiving.Modules.QuickDeposit; using EasyLiving.Modules.VeinMining; using EasyLiving.Modules.WorkbenchRange; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using Valheim.SettingsGui; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("EasyLiving")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("3.1.0.0")] [assembly: AssemblyInformationalVersion("3.1.0")] [assembly: AssemblyProduct("EasyLiving")] [assembly: AssemblyTitle("EasyLiving")] [assembly: AssemblyVersion("3.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [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 EasyLiving { internal static class EasyLivingConfig { internal static ConfigEntry<string> WeightMode; internal static ConfigEntry<string> ConsumableDuration; internal static ConfigEntry<string> PotionCooldown; internal static ConfigEntry<string> BossPowerDuration; internal static ConfigEntry<string> ItemDurability; internal static ConfigEntry<bool> PreventSkillLoss; internal static ConfigEntry<bool> KeepInventoryOnDeath; internal static ConfigEntry<bool> ToolStaminaEnabled; internal static ConfigEntry<bool> PreventRainDamage; internal static ConfigEntry<bool> ProtectPlayerStructures; internal static ConfigEntry<StructureDamageMode> DamageMode; internal static ConfigEntry<string> StackSize; internal static ConfigEntry<bool> FireControlEnabled; internal static ConfigEntry<string> BoatSpeed; internal static ConfigEntry<string> WorkbenchRange; internal static ConfigEntry<string> MapDiscoveryRadius; internal static ConfigEntry<bool> QuickDepositEnabled; internal static ConfigEntry<bool> CraftFromChestsEnabled; internal static ConfigEntry<bool> ManualStationResourcesEnabled; internal static ConfigEntry<bool> AutoEjectCookedFoodEnabled; internal static ConfigEntry<bool> AutoRepairEnabled; internal static ConfigEntry<bool> AllowVeinMining; internal static ConfigEntry<bool> ItemSortingEnabled; internal static ConfigEntry<string> QuickDepositKey; internal static ConfigEntry<string> AutoRepairKey; internal static ConfigEntry<string> VeinMiningKey; internal static void Bind(ConfigFile config) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Expected O, but got Unknown //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Expected O, but got Unknown //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Expected O, but got Unknown //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Expected O, but got Unknown //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Expected O, but got Unknown //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Expected O, but got Unknown //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Expected O, but got Unknown //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Expected O, but got Unknown //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Expected O, but got Unknown //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Expected O, but got Unknown //IL_0559: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Expected O, but got Unknown //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Expected O, but got Unknown //IL_05af: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Expected O, but got Unknown //IL_05da: Unknown result type (might be due to invalid IL or missing references) //IL_05e4: Expected O, but got Unknown //IL_0609: Unknown result type (might be due to invalid IL or missing references) //IL_0613: Expected O, but got Unknown //IL_06a8: Unknown result type (might be due to invalid IL or missing references) //IL_06b2: Expected O, but got Unknown //IL_071f: Unknown result type (might be due to invalid IL or missing references) //IL_0729: Expected O, but got Unknown //IL_074a: Unknown result type (might be due to invalid IL or missing references) //IL_0754: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; ConfigurationManagerAttributes val2 = new ConfigurationManagerAttributes { IsAdminOnly = false }; WeightMode = config.Bind<string>("1 - Item Weight", "WeightMode", "Half", new ConfigDescription("Global item weight. Normal = vanilla, Half = 50%, Quarter = 25%, Zero = weightless.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Normal", "Half", "Quarter", "Zero" }), new object[1] { val })); ConsumableDuration = config.Bind<string>("2 - Consumable Duration", "Duration", "2x", new ConfigDescription("Duration of food and timed effects from consumables such as meads/potions. Already-active effects are not recalculated when the server configuration changes.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Normal", "2x", "3x", "5x" }), new object[1] { val })); PotionCooldown = config.Bind<string>("2.1 - Potion Cooldown", "Cooldown", "100%", new ConfigDescription("Reduces the cooldown between potion and mead uses. Session restart required for changes.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "100%", "75%", "50%", "25%", "Off" }), new object[1] { val })); BossPowerDuration = config.Bind<string>("3 - Boss Power Duration", "Duration", "2x", new ConfigDescription("Duration of Forsaken/Boss powers. Cooldown is not changed. Already-active powers are not recalculated when the server configuration changes.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Normal", "2x", "3x" }), new object[1] { val })); ItemDurability = config.Bind<string>("4 - Item Durability", "Durability", "2x", new ConfigDescription("How long item durability lasts. Normal = vanilla, 2x/3x/5x reduce durability loss by the corresponding factor.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Normal", "2x", "3x", "5x" }), new object[1] { val })); PreventSkillLoss = config.Bind<bool>("5 - Death Penalty", "PreventSkillLoss", true, new ConfigDescription("true = EasyLiving prevents normal skill level/partial-XP loss on death. Direct PvP-death exceptions may be applied only when Valheim can identify the killer safely without continuous polling.", (AcceptableValueBase)null, new object[1] { val })); KeepInventoryOnDeath = config.Bind<bool>("5 - Death Penalty", "KeepInventoryOnDeath", false, new ConfigDescription("true = EasyLiving preserves the player inventory on death through Valheim's native tombstone decision. Skill loss and other death effects remain unchanged. Session restart required for changes.", (AcceptableValueBase)null, new object[1] { val })); ToolStaminaEnabled = config.Bind<bool>("20 - Tool Stamina", "Enabled", false, new ConfigDescription("Removes stamina costs from the Hammer, Hoe and Cultivator. Session restart required for changes.", (AcceptableValueBase)null, new object[1] { val })); bool flag = ConfigMigration.RawEntryExists(config.ConfigFilePath, "6 - Player Structures", "DamageMode"); ProtectPlayerStructures = config.Bind<bool>("6 - Player Structures", "ProtectPlayerStructures", true, new ConfigDescription("Legacy EasyLiving 1.x compatibility value. In EasyLiving 2.x, DamageMode is authoritative. If DamageMode did not exist during migration, true becomes Protected and false becomes Vanilla.", (AcceptableValueBase)null, new object[1] { val })); StructureDamageMode structureDamageMode = ((!ProtectPlayerStructures.Value) ? StructureDamageMode.Vanilla : StructureDamageMode.Protected); DamageMode = config.Bind<StructureDamageMode>("6 - Player Structures", "DamageMode", structureDamageMode, new ConfigDescription("Structure/vehicle damage mode. Protected = blocks normal player, creature and environment damage while preserving support/stability and hammer removal. PvP = allows player-caused damage but blocks creature/environment damage. Vanilla = normal Valheim damage.", (AcceptableValueBase)null, new object[1] { val })); PreventRainDamage = config.Bind<bool>("6 - Player Structures", "PreventRainDamage", false, new ConfigDescription("Prevents only vanilla rain wear on eligible structures. Other damage, support, collapse and repair remain vanilla. Session restart required for changes.", (AcceptableValueBase)null, new object[1] { val })); if (!flag) { DamageMode.Value = structureDamageMode; config.Save(); ManualLogSource modLog = EasyLivingPlugin.ModLog; if (modLog != null) { modLog.LogInfo((object)("EasyLiving 1.x structure protection migrated to DamageMode=" + DamageMode.Value.ToString() + ".")); } } StackSize = config.Bind<string>("7 - Stack Size", "StackSize", "2x", new ConfigDescription("Maximum stack multiplier for items that are already stackable in vanilla. Items with vanilla max stack 1 remain 1.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "Normal", "2x", "3x", "5x", "10x" }), new object[1] { val })); FireControlEnabled = config.Bind<bool>("8 - Fire Control", "Enabled", true, new ConfigDescription("Enables EasyLiving Fire Control for compatible lighting/comfort fires. Fuel remains stored and is not consumed while active; production stations are excluded.", (AcceptableValueBase)null, new object[1] { val })); BoatSpeed = config.Bind<string>("9 - Boat Speed", "Speed", "1.25x", new ConfigDescription("Target boat top-speed multiplier. Normal/1.25x/1.5x/2x. The implementation must preserve normal acceleration, turning, wind and wave behavior as closely as possible.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Normal", "1.25x", "1.5x", "2x" }), new object[1] { val })); WorkbenchRange = config.Bind<string>("10 - Workbench Range", "Range", "1.5x", new ConfigDescription("Effective normal Workbench build/repair range. Normal/1.5x/2x/3x.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Normal", "1.5x", "2x", "3x" }), new object[1] { val })); MapDiscoveryRadius = config.Bind<string>("11 - Map Discovery", "DiscoveryRadius", "2x", new ConfigDescription("Exploration reveal radius while walking/sailing. Normal = vanilla, 2x/3x/5x multiply future exploration only. Areas already revealed remain revealed if this value is later reduced or EasyLiving is removed.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Normal", "2x", "3x", "5x" }), new object[1] { val })); QuickDepositEnabled = config.Bind<bool>("14 - Quick Deposit", "Enabled", true, new ConfigDescription("Enables Quick Deposit for matching stationary chests near the Workbench area the player is currently using. No persistent chest network is created.", (AcceptableValueBase)null, new object[1] { val })); QuickDepositKey = config.Bind<string>("14 - Quick Deposit", "Key", "J", new ConfigDescription("Local-only Quick Deposit key. Ignored while typing or using relevant UI. EasyLiving will refuse conflicting EasyLiving keybinds instead of firing two actions.", (AcceptableValueBase)null, new object[1] { val2 })); ManualStationResourcesEnabled = config.Bind<bool>("18 - Manual Station Resources", "Enabled", true, new ConfigDescription("Uses eligible nearby chest resources only during manual interaction with the Charcoal Kiln, Smelter, Blast Furnace, Windmill, Spinning Wheel, Eitr Refinery, Oven, Frost Foundry, Frost Kiln, cooking stations/grills, Fermenter, Shield Generator and Ballista when no suitable carried resource exists. Requires local ownership of station and chest. No automatic feeding. Session restart required for changes.", (AcceptableValueBase)null, new object[1] { val })); AutoEjectCookedFoodEnabled = config.Bind<bool>("19 - Auto Eject Cooked Food", "Enabled", true, new ConfigDescription("Automatically ejects food exactly when it becomes cooked on the normal Cooking Station, Iron Cooking Station or Stone Oven. Other cooking machines are excluded. Session restart required for changes.", (AcceptableValueBase)null, new object[1] { val })); CraftFromChestsEnabled = config.Bind<bool>("15 - Craft From Chests", "Enabled", true, new ConfigDescription("Enables EasyLiving Craft From Chests for craft/upgrade recipes using eligible stationary chests inside the current normal Workbench area. No persistent chest network is created. Hammer building and production-station feeding are outside this Stage 7 scope. The module remains disabled automatically if a known directly conflicting mod is detected.", (AcceptableValueBase)null, new object[1] { val })); AutoRepairEnabled = config.Bind<bool>("16 - Auto Repair", "Enabled", true, new ConfigDescription("Enables manual Auto Repair. While inside the range of a normal Workbench, press the configured local key to repair the player's eligible damaged items when the required repair station and level exist inside that Workbench area.", (AcceptableValueBase)null, new object[1] { val })); AutoRepairKey = config.Bind<string>("16 - Auto Repair", "Key", "P", new ConfigDescription("Local-only Auto Repair key. Default P. All EasyLiving action keys are configurable; conflicting EasyLiving keybinds are blocked instead of firing two actions.", (AcceptableValueBase)null, new object[1] { val2 })); bool flag2 = ConfigMigration.RawEntryExists(config.ConfigFilePath, "17 - Vein Mining", "AllowVeinMining"); bool flag3 = true; if (!flag2) { bool result; if (ConfigMigration.TryReadRawValue(config.ConfigFilePath, "17 - Vein Mining", "Mode", out var value)) { flag3 = !string.Equals(value, "Off", StringComparison.OrdinalIgnoreCase); } else if (ConfigMigration.TryReadRawValue(config.ConfigFilePath, "17 - Vein Mining", "Enabled", out value) && bool.TryParse(value, out result)) { flag3 = result; } } AllowVeinMining = config.Bind<bool>("17 - Vein Mining", "AllowVeinMining", flag3, new ConfigDescription("Allows players in this world/server to use their personal Vein Mining mode. Session restart required for changes.", (AcceptableValueBase)null, new object[1] { val })); if (!flag2) { AllowVeinMining.Value = flag3; config.Save(); ManualLogSource modLog2 = EasyLivingPlugin.ModLog; if (modLog2 != null) { modLog2.LogInfo((object)("Legacy Vein Mining world setting migrated to AllowVeinMining=" + AllowVeinMining.Value + ".")); } } VeinMiningKey = config.Bind<string>("17 - Vein Mining", "Key", "H", new ConfigDescription("Local-only key used to cycle the player's personal Vein Mining mode: Off, On, On + Stones.", (AcceptableValueBase)null, new object[1] { val2 })); ItemSortingEnabled = config.Bind<bool>("21 - Item Sorting", "Enabled", true, new ConfigDescription("Local-only preference. Shows one context-aware Sort button that groups identical items within each category while preserving first appearance.", (AcceptableValueBase)null, new object[1] { val2 })); } internal static GameplaySnapshot Configured() { return new GameplaySnapshot(WeightMode.Value, ConsumableDuration.Value, BossPowerDuration.Value, ItemDurability.Value, PreventSkillLoss.Value, DamageMode.Value, StackSize.Value, FireControlEnabled.Value, BoatSpeed.Value, WorkbenchRange.Value, MapDiscoveryRadius.Value, QuickDepositEnabled.Value, CraftFromChestsEnabled.Value, AutoRepairEnabled.Value, AllowVeinMining.Value, ManualStationResourcesEnabled.Value, AutoEjectCookedFoodEnabled.Value, KeepInventoryOnDeath.Value, ToolStaminaEnabled.Value, PreventRainDamage.Value, PotionCooldown.Value); } internal static GameplaySnapshot OfficialDefaults() { return new GameplaySnapshot((string)((ConfigEntryBase)WeightMode).DefaultValue, (string)((ConfigEntryBase)ConsumableDuration).DefaultValue, (string)((ConfigEntryBase)BossPowerDuration).DefaultValue, (string)((ConfigEntryBase)ItemDurability).DefaultValue, (bool)((ConfigEntryBase)PreventSkillLoss).DefaultValue, (!(bool)((ConfigEntryBase)ProtectPlayerStructures).DefaultValue) ? StructureDamageMode.Vanilla : StructureDamageMode.Protected, (string)((ConfigEntryBase)StackSize).DefaultValue, (bool)((ConfigEntryBase)FireControlEnabled).DefaultValue, (string)((ConfigEntryBase)BoatSpeed).DefaultValue, (string)((ConfigEntryBase)WorkbenchRange).DefaultValue, (string)((ConfigEntryBase)MapDiscoveryRadius).DefaultValue, (bool)((ConfigEntryBase)QuickDepositEnabled).DefaultValue, (bool)((ConfigEntryBase)CraftFromChestsEnabled).DefaultValue, (bool)((ConfigEntryBase)AutoRepairEnabled).DefaultValue, (bool)((ConfigEntryBase)AllowVeinMining).DefaultValue, (bool)((ConfigEntryBase)ManualStationResourcesEnabled).DefaultValue, (bool)((ConfigEntryBase)AutoEjectCookedFoodEnabled).DefaultValue, (bool)((ConfigEntryBase)KeepInventoryOnDeath).DefaultValue, (bool)((ConfigEntryBase)ToolStaminaEnabled).DefaultValue, (bool)((ConfigEntryBase)PreventRainDamage).DefaultValue, (string)((ConfigEntryBase)PotionCooldown).DefaultValue); } } internal sealed class EasyLivingCommand : ConsoleCommand { public override string Name => "easyliving"; public override string Help => EasyLivingText.Choose("Mostra a configuração ativa do EasyLiving.", "Shows the EasyLiving configuration currently active.", "Показывает текущую активную конфигурацию EasyLiving."); public override bool IsCheat => false; public override bool IsNetwork => false; public override bool IsSecret => false; public override List<string> CommandOptionList() { return new List<string> { "status", "help" }; } public override void Run(string[] args, Terminal context) { GameplaySnapshot active = SessionConfiguration.Active; bool flag = SessionConfiguration.Values.RequiresRestart(EasyLivingConfig.Configured()); string text = "=== EasyLiving 3.1.0 ===\n" + EasyLivingText.Choose("Sessão pronta: ", "Session ready: ", "Сессия готова: ") + SessionConfiguration.Values.Ready + "\n" + EasyLivingText.Choose("ATIVA: ", "ACTIVE: ", "АКТИВНА: ") + active?.ToString() + "\n" + EasyLivingText.Choose("CONFIGURADA (sincronizada pelo Jotunn no multiplayer): ", "CONFIGURED (Jotunn synchronized during multiplayer): ", "НАСТРОЕНА (синхронизировано Jotunn в мультиплеере): ") + EasyLivingConfig.Configured()?.ToString() + "\n" + EasyLivingText.Choose("Reinício necessário: ", "Restart required: ", "Требуется перезапуск: ") + flag; if (context != null) { context.AddString(text); } ManualLogSource modLog = EasyLivingPlugin.ModLog; if (modLog != null) { modLog.LogInfo((object)text); } } } [BepInPlugin("Ignis.EasyLiving", "EasyLiving", "3.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class EasyLivingPlugin : BaseUnityPlugin { public const string PluginGuid = "Ignis.EasyLiving"; public const string PluginName = "EasyLiving"; public const string PluginVersion = "3.1.0"; internal static ManualLogSource ModLog; private Harmony _harmony; private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ModLog = ((BaseUnityPlugin)this).Logger; EasyLivingConfig.Bind(((BaseUnityPlugin)this).Config); SessionConfiguration.Initialize(((BaseUnityPlugin)this).Config); _harmony = new Harmony("Ignis.EasyLiving"); _harmony.PatchAll(); AutoRepairPatches.Install(_harmony); QuickDepositPatches.Install(); CraftFromChestsPatches.Install(_harmony); ManualStationResourcesPatches.Install(_harmony); VeinMiningPatches.Install(_harmony); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new EasyLivingCommand()); ModLog.LogInfo((object)("EasyLiving 3.1.0 loaded. Weight=" + EasyLivingConfig.WeightMode.Value + ", Consumables=" + EasyLivingConfig.ConsumableDuration.Value + ", PotionCooldown=" + EasyLivingConfig.PotionCooldown.Value + ", BossPowers=" + EasyLivingConfig.BossPowerDuration.Value + ", Durability=" + EasyLivingConfig.ItemDurability.Value + ", " + $"PreventSkillLoss={EasyLivingConfig.PreventSkillLoss.Value}, " + $"KeepInventoryOnDeath={EasyLivingConfig.KeepInventoryOnDeath.Value}, " + $"ToolStamina={EasyLivingConfig.ToolStaminaEnabled.Value}, " + $"PreventRainDamage={EasyLivingConfig.PreventRainDamage.Value}, " + $"DamageMode={EasyLivingConfig.DamageMode.Value}, " + "Stack=" + EasyLivingConfig.StackSize.Value + ", " + $"FireControl={EasyLivingConfig.FireControlEnabled.Value}, " + "BoatSpeed=" + EasyLivingConfig.BoatSpeed.Value + ", WorkbenchRange=" + EasyLivingConfig.WorkbenchRange.Value + ", MapDiscovery=" + EasyLivingConfig.MapDiscoveryRadius.Value + ", " + $"QuickDeposit={EasyLivingConfig.QuickDepositEnabled.Value}, " + $"CraftFromChests={EasyLivingConfig.CraftFromChestsEnabled.Value}, " + $"AutoRepair={EasyLivingConfig.AutoRepairEnabled.Value}, " + $"AllowVeinMining={EasyLivingConfig.AllowVeinMining.Value}, " + $"AutoEjectCookedFood={EasyLivingConfig.AutoEjectCookedFoodEnabled.Value}, " + $"ItemSorting={EasyLivingConfig.ItemSortingEnabled.Value}")); } private void OnDestroy() { SessionConfiguration.Dispose(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { EasyLivingText.Update(); SessionConfiguration.Update(); WorkbenchRangeUtility.UpdateSessionRange(); AutoRepairPatches.Update(); QuickDepositPatches.Update(); VeinMiningPatches.Update(); } } [HarmonyPatch(typeof(ItemData), "GetWeight")] internal static class ItemWeightPatch { private static void Postfix(ref float __result) { __result *= SessionConfiguration.Active.WeightMultiplier; } } [HarmonyPatch(typeof(Game), "UpdateWorldRates")] internal static class WorldRatesPatch { private static void Postfix() { float consumableMultiplier = SessionConfiguration.Active.ConsumableMultiplier; if (consumableMultiplier > 0f) { Game.m_foodRate /= consumableMultiplier; } float durabilityMultiplier = SessionConfiguration.Active.DurabilityMultiplier; if (durabilityMultiplier > 0f) { Game.m_durabilityRate /= durabilityMultiplier; } if (SessionConfiguration.Active.PreventSkillLoss) { Game.m_skillReductionRate = 0f; } } } [HarmonyPatch(typeof(Player), "CanConsumeItem")] internal static class PotionCooldownEligibilityPatch { private static readonly MethodInfo HaveEffectMethod = AccessTools.Method(typeof(SEMan), "HaveStatusEffect", new Type[1] { typeof(int) }, (Type[])null); private static readonly MethodInfo HaveCategoryMethod = AccessTools.Method(typeof(SEMan), "HaveStatusEffectCategory", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo BlockEffectMethod = AccessTools.Method(typeof(PotionCooldownEligibilityPatch), "ShouldBlockEffect", (Type[])null, (Type[])null); private static readonly MethodInfo BlockCategoryMethod = AccessTools.Method(typeof(PotionCooldownEligibilityPatch), "ShouldBlockCategory", (Type[])null, (Type[])null); private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); int num = 0; int num2 = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, HaveEffectMethod) || CodeInstructionExtensions.Calls(instruction, HaveCategoryMethod)) { list.Add(CodeInstructionExtensions.MoveBlocksFrom(CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Ldarg_1, (object)null), instruction), instruction)); bool flag = CodeInstructionExtensions.Calls(instruction, HaveEffectMethod); list.Add(new CodeInstruction(OpCodes.Call, (object)(flag ? BlockEffectMethod : BlockCategoryMethod))); if (flag) { num++; } else { num2++; } } else { list.Add(instruction); } } if (num != 1 || num2 != 1) { throw new InvalidOperationException("Expected one effect and one category cooldown check in Player.CanConsumeItem."); } return list; } private static bool ShouldBlockEffect(SEMan seman, int hash, ItemData item) { StatusEffect val = item?.m_shared?.m_consumeStatusEffect; if ((Object)(object)val == (Object)null || !val.m_cooldownIcon) { return seman.HaveStatusEffect(hash); } return IsBlocking(seman.GetStatusEffect(hash), SessionConfiguration.Active.PotionCooldownMultiplier); } private static bool ShouldBlockCategory(SEMan seman, string category, ItemData item) { StatusEffect val = item?.m_shared?.m_consumeStatusEffect; if ((Object)(object)val == (Object)null || !val.m_cooldownIcon) { return seman.HaveStatusEffectCategory(category); } if (string.IsNullOrEmpty(category)) { return false; } float potionCooldownMultiplier = SessionConfiguration.Active.PotionCooldownMultiplier; foreach (StatusEffect statusEffect in seman.GetStatusEffects()) { if ((Object)(object)statusEffect != (Object)null && statusEffect.m_category == category && IsBlocking(statusEffect, potionCooldownMultiplier)) { return true; } } return false; } internal static bool IsBlocking(StatusEffect active, float multiplier) { if ((Object)(object)active == (Object)null) { return false; } if (!active.m_cooldownIcon || active.m_ttl <= 0f) { return true; } return active.m_ttl - active.GetRemaningTime() < active.m_ttl * multiplier; } internal static void RemoveExpiredBlockers(Player player, ItemData item) { StatusEffect val = item?.m_shared?.m_consumeStatusEffect; if ((Object)(object)player == (Object)null || (Object)(object)val == (Object)null || !val.m_cooldownIcon) { return; } float potionCooldownMultiplier = SessionConfiguration.Active.PotionCooldownMultiplier; if (potionCooldownMultiplier >= 1f) { return; } int num = val.NameHash(); string category = val.m_category; foreach (StatusEffect item2 in new List<StatusEffect>(((Character)player).GetSEMan().GetStatusEffects())) { if (!((Object)(object)item2 == (Object)null) && item2.m_cooldownIcon) { bool num2 = item2.NameHash() == num; bool flag = !string.IsNullOrEmpty(category) && item2.m_category == category; if ((num2 || flag) && !IsBlocking(item2, potionCooldownMultiplier)) { ((Character)player).GetSEMan().RemoveStatusEffect(item2, true); } } } } } [HarmonyPatch(typeof(StatusEffect), "GetIconText")] internal static class PotionCooldownIconTextPatch { private static bool Prefix(StatusEffect __instance, ref string __result) { if ((Object)(object)__instance == (Object)null || !__instance.m_cooldownIcon) { return true; } float potionCooldownMultiplier = SessionConfiguration.Active.PotionCooldownMultiplier; if (potionCooldownMultiplier >= 1f) { return true; } float num = __instance.m_ttl * potionCooldownMultiplier - __instance.GetDuration(); __result = ((num > 0f) ? StatusEffect.GetTimeString(num, false, false) : string.Empty); return false; } } [HarmonyPatch(typeof(SEMan), "GetHUDStatusEffects")] internal static class PotionCooldownHudListPatch { private static void Postfix(List<StatusEffect> effects) { if (effects != null && !(SessionConfiguration.Active.PotionCooldownMultiplier >= 1f)) { float multiplier = SessionConfiguration.Active.PotionCooldownMultiplier; effects.RemoveAll((StatusEffect effect) => (Object)(object)effect != (Object)null && effect.m_cooldownIcon && !PotionCooldownEligibilityPatch.IsBlocking(effect, multiplier)); } } } [HarmonyPatch(typeof(Player), "ConsumeItem")] internal static class ConsumableStatusEffectPatch { private struct State { internal StatusEffect Effect; internal float OriginalTtl; internal bool Changed; } private static void Prefix(Player __instance, ItemData item, out State __state) { __state = default(State); PotionCooldownEligibilityPatch.RemoveExpiredBlockers(__instance, item); StatusEffect val = item?.m_shared?.m_consumeStatusEffect; if (!((Object)(object)val == (Object)null) && !val.m_cooldownIcon) { float consumableMultiplier = SessionConfiguration.Active.ConsumableMultiplier; if (consumableMultiplier != 1f && !(val.m_ttl <= 0f)) { __state.Effect = val; __state.OriginalTtl = val.m_ttl; __state.Changed = true; val.m_ttl = __state.OriginalTtl * consumableMultiplier; } } } private static void Postfix(State __state) { Restore(__state); } private static Exception Finalizer(Exception __exception, State __state) { Restore(__state); return __exception; } private static void Restore(State state) { if (state.Changed && (Object)(object)state.Effect != (Object)null) { state.Effect.m_ttl = state.OriginalTtl; } } } [HarmonyPatch(typeof(Player), "ActivateGuardianPower")] internal static class BossPowerDurationPatch { private struct State { internal StatusEffect Effect; internal float OriginalTtl; internal bool Changed; } private static readonly FieldInfo GuardianEffectField = AccessTools.Field(typeof(Player), "m_guardianSE"); private static void Prefix(Player __instance, out State __state) { __state = default(State); if (!(GuardianEffectField == null) && !((Object)(object)__instance == (Object)null)) { object? value = GuardianEffectField.GetValue(__instance); StatusEffect val = (StatusEffect)((value is StatusEffect) ? value : null); float bossPowerMultiplier = SessionConfiguration.Active.BossPowerMultiplier; if (!((Object)(object)val == (Object)null) && !(val.m_ttl <= 0f) && bossPowerMultiplier != 1f) { __state.Effect = val; __state.OriginalTtl = val.m_ttl; __state.Changed = true; val.m_ttl = __state.OriginalTtl * bossPowerMultiplier; } } } private static void Postfix(State __state) { Restore(__state); } private static Exception Finalizer(Exception __exception, State __state) { Restore(__state); return __exception; } private static void Restore(State state) { if (state.Changed && (Object)(object)state.Effect != (Object)null) { state.Effect.m_ttl = state.OriginalTtl; } } } [HarmonyPatch] internal static class ConsumableTooltipDurationPatch { private struct State { internal ItemData Item; internal float OriginalFoodBurnTime; internal StatusEffect Effect; internal float OriginalEffectTtl; internal bool FoodChanged; internal bool EffectChanged; } private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(ItemData).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (!(methodInfo.Name != "GetTooltip") && !(methodInfo.ReturnType != typeof(string))) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 0 && parameters[0].ParameterType == typeof(ItemData)) { yield return methodInfo; } } } } private static void Prefix(object[] __args, out State __state) { __state = default(State); if (__args == null || __args.Length == 0) { return; } object obj = __args[0]; ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val == null || val.m_shared == null) { return; } float consumableMultiplier = SessionConfiguration.Active.ConsumableMultiplier; float potionCooldownMultiplier = SessionConfiguration.Active.PotionCooldownMultiplier; __state.Item = val; if (consumableMultiplier != 1f && val.m_shared.m_foodBurnTime > 0f) { __state.OriginalFoodBurnTime = val.m_shared.m_foodBurnTime; __state.FoodChanged = true; val.m_shared.m_foodBurnTime = __state.OriginalFoodBurnTime * consumableMultiplier; } StatusEffect consumeStatusEffect = val.m_shared.m_consumeStatusEffect; if ((Object)(object)consumeStatusEffect != (Object)null && consumeStatusEffect.m_ttl > 0f) { float num = (consumeStatusEffect.m_cooldownIcon ? potionCooldownMultiplier : consumableMultiplier); if (num != 1f) { __state.Effect = consumeStatusEffect; __state.OriginalEffectTtl = consumeStatusEffect.m_ttl; __state.EffectChanged = true; consumeStatusEffect.m_ttl = __state.OriginalEffectTtl * num; } } } private static void Postfix(State __state) { Restore(__state); } private static Exception Finalizer(Exception __exception, State __state) { Restore(__state); return __exception; } private static void Restore(State state) { if (state.FoodChanged && state.Item != null && state.Item.m_shared != null) { state.Item.m_shared.m_foodBurnTime = state.OriginalFoodBurnTime; } if (state.EffectChanged && (Object)(object)state.Effect != (Object)null) { state.Effect.m_ttl = state.OriginalEffectTtl; } } } [HarmonyPatch] internal static class ItemWeightTooltipPatch { private static readonly Regex NumberRegex = new Regex("-?\\d+(?:[\\.,]\\d+)?", RegexOptions.Compiled); private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(ItemData).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (!(methodInfo.Name != "GetTooltip") && !(methodInfo.ReturnType != typeof(string))) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 0 && parameters[0].ParameterType == typeof(ItemData)) { yield return methodInfo; } } } } private static void Postfix(object[] __args, ref string __result) { if (__args == null || __args.Length == 0 || string.IsNullOrEmpty(__result)) { return; } object obj = __args[0]; ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val == null || val.m_shared == null) { return; } float multiplier = SessionConfiguration.Active.WeightMultiplier; if (multiplier == 1f) { return; } int num = __result.IndexOf("$item_weight: <color=orange>", StringComparison.Ordinal); if (num < 0) { return; } int num2 = num + "$item_weight: <color=orange>".Length; int num3 = __result.IndexOf("</color>", num2, StringComparison.Ordinal); if (num3 < 0) { return; } string input = __result.Substring(num2, num3 - num2); Match match = NumberRegex.Match(input); if (!match.Success || !TryParseFlexible(match.Value, out var result)) { return; } float num4 = val.m_shared.m_weight * multiplier; if (!(Math.Abs(result - num4) < 0.01f)) { float result2; string text = NumberRegex.Replace(input, (Match match2) => (!TryParseFlexible(match2.Value, out result2)) ? match2.Value : (result2 * multiplier).ToString("0.0", CultureInfo.InvariantCulture)); __result = __result.Substring(0, num2) + text + __result.Substring(num3); } } private static bool TryParseFlexible(string value, out float result) { return float.TryParse(value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out result); } } [HarmonyPatch(typeof(Skills), "LowerAllSkills")] internal static class PreventDeathSkillLossPatch { private static bool Prefix() { return !SessionConfiguration.Active.PreventSkillLoss; } } } namespace EasyLiving.UI { internal sealed class EasyLivingKeyboardMouseSettings : MonoBehaviour { private sealed class Bind { internal string Name; internal string TextKey; internal ConfigEntry<string> Entry; internal RectTransform Row; internal Button Button; internal TMP_Text Label; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static PopupButtonCallback <>9__38_0; internal void <AfterBindingsUpdated>b__38_0() { UnifiedPopup.Pop(); } } private const string Prefix = "EasyLiving_"; private static readonly FieldInfo KeysField = AccessTools.Field(typeof(KeyboardMouseSettings), "m_keys"); private static readonly FieldInfo ButtonsField = AccessTools.Field(typeof(ZInput), "m_buttons"); private static readonly MethodInfo AddButtonMethod = AccessTools.Method(typeof(ZInput), "AddButton", new Type[7] { typeof(string), typeof(string), typeof(bool), typeof(bool), typeof(bool), typeof(float), typeof(float) }, (Type[])null); private static readonly MethodInfo KeyPathMethod = AccessTools.Method(typeof(ZInput), "KeyCodeToPath", new Type[2] { typeof(KeyCode), typeof(bool) }, (Type[])null); private static readonly MethodInfo UnsubscribeMethod = AccessTools.Method(typeof(ZInput), "UnsubscribeButton", (Type[])null, (Type[])null); private static readonly MethodInfo OpenDialogMethod = AccessTools.Method(typeof(KeyboardMouseSettings), "OpenBindDialog", (Type[])null, (Type[])null); private static readonly MethodInfo UpdateBindingsMethod = AccessTools.Method(typeof(KeyboardMouseSettings), "UpdateBindings", (Type[])null, (Type[])null); private readonly List<Bind> binds = new List<Bind>(3); private KeyboardMouseSettings page; private List<KeySetting> keys; private string selectedName; private string previousPath; private bool handling; private readonly List<GameObject> vanillaRows = new List<GameObject>(); private readonly List<bool> vanillaVisibility = new List<bool>(); private Button resetButton; private Navigation resetNavigation; private GameObject modeButtonObject; private bool easyLivingMode; private ScrollRect scroll; private float vanillaScrollPosition; private bool conflictPopupOpen; private string conflictName; private string conflictOldPath; private KeyCode conflictKey; internal bool ConflictPopupOpen => conflictPopupOpen; internal static void Install(KeyboardMouseSettings owner) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || (Object)(object)((Component)owner).GetComponent<EasyLivingKeyboardMouseSettings>() != (Object)null) { return; } EasyLivingKeyboardMouseSettings panel = ((Component)owner).gameObject.AddComponent<EasyLivingKeyboardMouseSettings>(); try { panel.Build(owner); } catch (Exception ex) { panel.keys?.RemoveAll((KeySetting k) => panel.binds.Exists((Bind b) => (Object)(object)b.Row != (Object)null && (Object)(object)b.Row == (Object)(object)k.m_keyTransform)); panel.RestoreVanillaRows(); if ((Object)(object)panel.resetButton != (Object)null) { ((Selectable)panel.resetButton).navigation = panel.resetNavigation; } panel.RemoveTemporaryButtons(); foreach (Bind bind in panel.binds) { if ((Object)(object)bind.Row != (Object)null) { Object.Destroy((Object)(object)((Component)bind.Row).gameObject); } } if ((Object)(object)panel.modeButtonObject != (Object)null) { Object.Destroy((Object)(object)panel.modeButtonObject); } Object.Destroy((Object)(object)panel); ManualLogSource modLog = EasyLivingPlugin.ModLog; if (modLog != null) { modLog.LogError((object)("EasyLiving keybind UI could not be added: " + ex)); } } } private void Build(KeyboardMouseSettings owner) { //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Expected O, but got Unknown //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_035d: 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_054f: Unknown result type (might be due to invalid IL or missing references) //IL_0554: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Expected O, but got Unknown //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Expected O, but got Unknown //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Expected O, but got Unknown //IL_05c2: Unknown result type (might be due to invalid IL or missing references) page = owner; keys = KeysField?.GetValue(owner) as List<KeySetting>; if (keys == null || keys.Count < 2 || AddButtonMethod == null || KeyPathMethod == null || ButtonsField == null || UnsubscribeMethod == null || OpenDialogMethod == null || UpdateBindingsMethod == null) { throw new InvalidOperationException("Native keyboard settings bindings are unavailable."); } ZInput instance = ZInput.instance; if (instance == null) { throw new InvalidOperationException("Native input is unavailable."); } AddTemporaryButton(instance, "QuickDeposit", EasyLivingConfig.QuickDepositKey, (KeyCode)106); AddTemporaryButton(instance, "VeinMining", EasyLivingConfig.VeinMiningKey, (KeyCode)104); AddTemporaryButton(instance, "AutoRepair", EasyLivingConfig.AutoRepairKey, (KeyCode)112); KeySetting val = FirstActiveKey(); RectTransform keyTransform = val.m_keyTransform; if ((Object)(object)((Component)keyTransform).GetComponentInChildren<Button>(true) == (Object)null) { throw new InvalidOperationException("Native keybind row has no button."); } GridLayoutGroup component = ((Component)((Transform)keyTransform).parent).GetComponent<GridLayoutGroup>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Native keybind Grid is unavailable."); } scroll = ((Component)owner).GetComponentInChildren<ScrollRect>(true); if ((Object)(object)scroll == (Object)null || (Object)(object)scroll.content != (Object)(object)((Transform)keyTransform).parent) { throw new InvalidOperationException("Native keybind scroll area is unavailable."); } foreach (Transform item in ((Transform)keyTransform).parent) { Transform val2 = item; vanillaRows.Add(((Component)val2).gameObject); vanillaVisibility.Add(((Component)val2).gameObject.activeSelf); } Transform val3 = ((Component)owner).transform.Find("List/Settings/ResetControls"); resetButton = ((val3 != null) ? ((Component)val3).GetComponent<Button>() : null); RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null); if ((Object)(object)resetButton == (Object)null || (Object)(object)val4 == (Object)null) { throw new InvalidOperationException("Native Reset Controls button is unavailable."); } resetNavigation = ((Selectable)resetButton).navigation; modeButtonObject = Object.Instantiate<GameObject>(((Component)val3).gameObject, val3.parent, false); ((Object)modeButtonObject).name = "EasyLiving"; Button component2 = modeButtonObject.GetComponent<Button>(); RectTransform component3 = modeButtonObject.GetComponent<RectTransform>(); TMP_Text componentInChildren = modeButtonObject.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null || (Object)(object)componentInChildren == (Object)null) { throw new InvalidOperationException("Cloned Reset Controls button is incomplete."); } component2.onClick = new ButtonClickedEvent(); componentInChildren.text = "EasyLiving"; Vector2 anchoredPosition = val4.anchoredPosition; Vector2 right = Vector2.right; Rect rect = val4.rect; component3.anchoredPosition = anchoredPosition + right * (((Rect)(ref rect)).width + component.spacing.y); ((UnityEvent)component2.onClick).AddListener(new UnityAction(ToggleMode)); Navigation navigation = ((Selectable)resetButton).navigation; Navigation navigation2 = ((Selectable)component2).navigation; ((Navigation)(ref navigation)).mode = (Mode)4; ((Navigation)(ref navigation2)).mode = (Mode)4; ((Navigation)(ref navigation)).selectOnRight = (Selectable)(object)component2; ((Navigation)(ref navigation2)).selectOnLeft = (Selectable)(object)resetButton; ((Navigation)(ref navigation2)).selectOnRight = null; ((Selectable)resetButton).navigation = navigation; ((Selectable)component2).navigation = navigation2; for (int i = 0; i < binds.Count; i++) { Bind bind = binds[i]; GameObject val5 = Object.Instantiate<GameObject>(((Component)keyTransform).gameObject, ((Transform)keyTransform).parent, false); ((Object)val5).name = "EasyLiving_" + bind.TextKey; bind.Row = val5.GetComponent<RectTransform>(); bind.Button = val5.GetComponentInChildren<Button>(true); if ((Object)(object)bind.Row == (Object)null || (Object)(object)bind.Button == (Object)null) { throw new InvalidOperationException("Cloned native keybind row is incomplete."); } ((Transform)bind.Row).SetSiblingIndex(i); TMP_Text componentInChildren2 = ((Component)bind.Button).GetComponentInChildren<TMP_Text>(true); TMP_Text[] componentsInChildren = val5.GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val6 in componentsInChildren) { if ((Object)(object)val6 != (Object)(object)componentInChildren2) { bind.Label = val6; break; } } if ((Object)(object)bind.Label == (Object)null || (Object)(object)componentInChildren2 == (Object)null) { throw new InvalidOperationException("Native keybind row labels are unavailable."); } bind.Label.text = EasyLivingText.Panel(bind.TextKey); bind.Button.onClick = new ButtonClickedEvent(); KeySetting setting = new KeySetting { m_keyName = bind.Name, m_keyTransform = bind.Row, m_blockedButtons = val.m_blockedButtons }; keys.Add(setting); ((UnityEvent)bind.Button.onClick).AddListener((UnityAction)delegate { OpenDialogMethod.Invoke(page, new object[1] { setting }); }); ((Component)bind.Row).gameObject.SetActive(false); } for (int num = 0; num < binds.Count; num++) { Navigation navigation3 = ((Selectable)binds[num].Button).navigation; ((Navigation)(ref navigation3)).mode = (Mode)4; ((Navigation)(ref navigation3)).selectOnUp = (Selectable)(object)((num == 0) ? component2 : binds[num - 1].Button); ((Navigation)(ref navigation3)).selectOnDown = (Selectable)(object)((num + 1 < binds.Count) ? binds[num + 1].Button : null); ((Selectable)binds[num].Button).navigation = navigation3; } UpdateBindingsMethod.Invoke(page, null); } private void AddTemporaryButton(ZInput input, string id, ConfigEntry<string> entry, KeyCode fallback) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) string text = "EasyLiving_" + id; KeyCode result = (KeyCode)0; if (entry != null) { Enum.TryParse<KeyCode>(entry.Value, ignoreCase: true, out result); } string text2 = Path(fallback); if (string.IsNullOrEmpty(text2)) { throw new InvalidOperationException("Native key path is unavailable."); } if (input.GetButtonDef(text) == null) { AddButtonMethod.Invoke(input, new object[7] { text, text2, false, false, true, 0f, 0f }); } ButtonDef buttonDef = input.GetButtonDef(text); string text3 = Path(result); if (!string.IsNullOrEmpty(text3)) { buttonDef.Rebind(text3); } binds.Add(new Bind { Name = text, TextKey = id, Entry = entry }); } private KeySetting FirstActiveKey() { foreach (KeySetting key in keys) { if ((Object)(object)key?.m_keyTransform != (Object)null && ((Component)key.m_keyTransform).gameObject.activeSelf) { return key; } } throw new InvalidOperationException("Active native keybind row is unavailable."); } private void ToggleMode() { easyLivingMode = !easyLivingMode; if (easyLivingMode) { vanillaScrollPosition = scroll.verticalNormalizedPosition; for (int i = 0; i < vanillaRows.Count; i++) { if ((Object)(object)vanillaRows[i] != (Object)null) { vanillaRows[i].SetActive(false); } } foreach (Bind bind in binds) { if ((Object)(object)bind.Row != (Object)null) { ((Component)bind.Row).gameObject.SetActive(true); } } scroll.verticalNormalizedPosition = 1f; } else { foreach (Bind bind2 in binds) { if ((Object)(object)bind2.Row != (Object)null) { ((Component)bind2.Row).gameObject.SetActive(false); } } RestoreVanillaRows(); scroll.verticalNormalizedPosition = vanillaScrollPosition; } if ((Object)(object)EventSystem.current != (Object)null && (Object)(object)modeButtonObject != (Object)null) { EventSystem.current.SetSelectedGameObject(modeButtonObject); } } private void RestoreVanillaRows() { for (int i = 0; i < vanillaRows.Count; i++) { if ((Object)(object)vanillaRows[i] != (Object)null) { vanillaRows[i].SetActive(vanillaVisibility[i]); } } } private static string Path(KeyCode key) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) return KeyPathMethod?.Invoke(null, new object[2] { key, false }) as string; } private static KeyCode KeyFromPath(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(path)) { foreach (KeyCode value in Enum.GetValues(typeof(KeyCode))) { if ((int)value != 0 && string.Equals(Path(value), path, StringComparison.OrdinalIgnoreCase)) { return value; } } return (KeyCode)0; } return (KeyCode)0; } internal void BeforeBind(KeySetting setting) { selectedName = setting?.m_keyName; object obj; if (selectedName != null) { ZInput instance = ZInput.instance; if (instance == null) { obj = null; } else { ButtonDef buttonDef = instance.GetButtonDef(selectedName); obj = ((buttonDef != null) ? buttonDef.GetActionPath(true) : null); } } else { obj = null; } previousPath = (string)obj; } internal unsafe void AfterBindingsUpdated() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00ac: 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_00b7: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_0168: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown if (handling || selectedName == null) { return; } string text = selectedName; string text2 = previousPath; selectedName = null; previousPath = null; ZInput instance = ZInput.instance; string text3 = SafeActionPath((instance != null) ? instance.GetButtonDef(text) : null); if (string.IsNullOrEmpty(text3) || string.Equals(text3, text2, StringComparison.OrdinalIgnoreCase)) { return; } bool flag = text.StartsWith("EasyLiving_", StringComparison.Ordinal); KeyCode val = KeyFromPath(text3); if (flag && (int)val == 0) { Restore(text, text2); string text4 = EasyLivingText.Choose("Esta tecla não pode ser usada aqui.", "This key cannot be used here.", "Эту клавишу нельзя использовать здесь."); object obj = <>c.<>9__38_0; if (obj == null) { PopupButtonCallback val2 = delegate { UnifiedPopup.Pop(); }; <>c.<>9__38_0 = val2; obj = (object)val2; } UnifiedPopup.Push((PopupBase)new WarningPopup("EasyLiving", text4, (PopupButtonCallback)obj, false)); return; } string text5 = ConflictName(text, text3, flag); if (text5 == null) { if (flag) { Commit(text, val, text2); } return; } string text6 = (flag ? ((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString() : instance.GetBoundKeyString(text, true)); string text7 = EasyLivingText.Format("A tecla {0} já está sendo usada por {1}.\nDeseja usá-la mesmo assim?", "{0} is already assigned to {1}.\nDo you want to use it anyway?", "Клавиша {0} уже назначена действию «{1}».\nВсё равно использовать её?", text6, text5); conflictName = text; conflictOldPath = text2; conflictKey = val; conflictPopupOpen = true; UnifiedPopup.Push((PopupBase)new YesNoPopup("EasyLiving", text7, (PopupButtonCallback)delegate { CloseConflict(accept: true); }, (PopupButtonCallback)delegate { CloseConflict(accept: false); }, false, false)); } private void CloseConflict(bool accept) { //IL_001f: 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_004b: Unknown result type (might be due to invalid IL or missing references) if (!conflictPopupOpen) { return; } conflictPopupOpen = false; string text = conflictName; string oldPath = conflictOldPath; KeyCode key = conflictKey; conflictName = null; conflictOldPath = null; UnifiedPopup.Pop(); if (accept) { if (text.StartsWith("EasyLiving_", StringComparison.Ordinal)) { Commit(text, key, oldPath); } } else { Restore(text, oldPath); } } private void Update() { if (conflictPopupOpen && ZInput.GetKeyDown((KeyCode)27, true)) { CloseConflict(accept: false); } } private static string SafeActionPath(ButtonDef definition) { if (definition == null) { return null; } try { return definition.GetActionPath(true); } catch (ArgumentOutOfRangeException) { return null; } } private string ConflictName(string target, string candidate, bool customTarget) { ZInput instance = ZInput.instance; if (!(ButtonsField?.GetValue(instance) is Dictionary<string, ButtonDef> dictionary)) { return null; } if (customTarget) { foreach (KeySetting key in keys) { if (key.m_keyName != target && string.Equals(dictionary.ContainsKey(key.m_keyName) ? SafeActionPath(dictionary[key.m_keyName]) : null, candidate, StringComparison.OrdinalIgnoreCase)) { return ActionLabel(key); } } } foreach (KeyValuePair<string, ButtonDef> pair in dictionary) { if (!(pair.Key == target) && (customTarget || pair.Key.StartsWith("EasyLiving_", StringComparison.Ordinal)) && string.Equals(SafeActionPath(pair.Value), candidate, StringComparison.OrdinalIgnoreCase)) { Bind bind = binds.Find((Bind b) => b.Name == pair.Key); if (bind != null) { return EasyLivingText.Panel(bind.TextKey); } KeySetting val = keys.Find((KeySetting k) => k.m_keyName == pair.Key); return (val == null) ? pair.Key : ActionLabel(val); } } return null; } private static string ActionLabel(KeySetting setting) { RectTransform val = setting?.m_keyTransform; Button obj = ((val != null) ? ((Component)val).GetComponentInChildren<Button>(true) : null); TMP_Text val2 = ((obj != null) ? ((Component)obj).GetComponentInChildren<TMP_Text>(true) : null); if ((Object)(object)val != (Object)null) { TMP_Text[] componentsInChildren = ((Component)val).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)(object)val2) { return EasyLivingText.Vanilla(val3.text); } } } return setting?.m_keyName ?? string.Empty; } private unsafe void Commit(string name, KeyCode key, string oldPath) { Bind bind = binds.Find((Bind b) => b.Name == name); if (bind == null || bind.Entry == null) { return; } string value = bind.Entry.Value; try { bind.Entry.Value = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); ((ConfigEntryBase)bind.Entry).ConfigFile.Save(); } catch (Exception ex) { bind.Entry.Value = value; Restore(name, oldPath); ManualLogSource modLog = EasyLivingPlugin.ModLog; if (modLog != null) { modLog.LogError((object)("EasyLiving keybind could not be saved: " + ex)); } } } private void Restore(string name, string oldPath) { if (string.IsNullOrEmpty(oldPath)) { return; } handling = true; try { ZInput instance = ZInput.instance; if (instance != null) { ButtonDef buttonDef = instance.GetButtonDef(name); if (buttonDef != null) { buttonDef.Rebind(oldPath); } } UpdateBindingsMethod?.Invoke(page, null); } finally { handling = false; } } internal void ResetDefaults() { //IL_0007: 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_003b: Unknown result type (might be due to invalid IL or missing references) EasyLivingConfig.QuickDepositKey.Value = ((object)(KeyCode)106/*cast due to .constrained prefix*/).ToString(); EasyLivingConfig.VeinMiningKey.Value = ((object)(KeyCode)104/*cast due to .constrained prefix*/).ToString(); EasyLivingConfig.AutoRepairKey.Value = ((object)(KeyCode)112/*cast due to .constrained prefix*/).ToString(); ((ConfigEntryBase)EasyLivingConfig.QuickDepositKey).ConfigFile.Save(); UpdateBindingsMethod?.Invoke(page, null); } internal void RefreshLabels() { foreach (Bind bind in binds) { if ((Object)(object)bind.Label != (Object)null) { bind.Label.text = EasyLivingText.Panel(bind.TextKey); } } } internal void RemoveTemporaryButtons() { ZInput instance = ZInput.instance; Dictionary<string, ButtonDef> dictionary = ((instance == null) ? null : (ButtonsField?.GetValue(instance) as Dictionary<string, ButtonDef>)); if (dictionary == null) { return; } foreach (Bind bind in binds) { if (dictionary.TryGetValue(bind.Name, out var value)) { UnsubscribeMethod?.Invoke(instance, new object[1] { value }); dictionary.Remove(bind.Name); } } } private void OnDestroy() { RemoveTemporaryButtons(); } } [HarmonyPatch(typeof(KeyboardMouseSettings), "Initialize")] internal static class EasyLivingKeyboardInitializePatch { private static void Postfix(KeyboardMouseSettings __instance) { EasyLivingKeyboardMouseSettings.Install(__instance); } } [HarmonyPatch(typeof(KeyboardMouseSettings), "OpenBindDialog")] internal static class EasyLivingKeyboardBindStartPatch { private static void Prefix(KeyboardMouseSettings __instance, KeySetting __0) { ((Component)__instance).GetComponent<EasyLivingKeyboardMouseSettings>()?.BeforeBind(__0); } } [HarmonyPatch(typeof(KeyboardMouseSettings), "UpdateBindings")] internal static class EasyLivingKeyboardBindFinishedPatch { private static void Postfix(KeyboardMouseSettings __instance) { ((Component)__instance).GetComponent<EasyLivingKeyboardMouseSettings>()?.AfterBindingsUpdated(); } } [HarmonyPatch(typeof(KeyboardMouseSettings), "ResetBindings")] internal static class EasyLivingKeyboardResetPatch { private static void Postfix(KeyboardMouseSettings __instance) { ((Component)__instance).GetComponent<EasyLivingKeyboardMouseSettings>()?.ResetDefaults(); } } [HarmonyPatch(typeof(KeyboardMouseSettings), "OnTabOpen")] internal static class EasyLivingKeyboardTabOpenPatch { private static void Postfix(KeyboardMouseSettings __instance) { ((Component)__instance).GetComponent<EasyLivingKeyboardMouseSettings>()?.RefreshLabels(); } } [HarmonyPatch(typeof(Settings), "ApplyAndClose")] internal static class EasyLivingKeyboardSettingsClosePatch { private static void Prefix(Settings __instance) { ((Component)__instance).GetComponentInChildren<EasyLivingKeyboardMouseSettings>(true)?.RemoveTemporaryButtons(); } } [HarmonyPatch(typeof(Settings), "Update")] internal static class EasyLivingKeyboardConflictSettingsUpdatePatch { private static bool Prefix(Settings __instance) { return !(((Component)__instance).GetComponentInChildren<EasyLivingKeyboardMouseSettings>(true)?.ConflictPopupOpen ?? false); } } internal sealed class EasyLivingPanel : MonoBehaviour { private sealed class Entry { internal string Id; internal Selectable Control; internal Slider Slider; internal Toggle Toggle; internal TMP_Text Label; internal TMP_Text ValueLabel; internal string[] Choices; internal Func<string> ReadChoice; internal Func<bool> ReadToggle; } private const int ToggleColumnCount = 2; private const float ToggleColumnWidth = 0.5f; private const float ToggleRowStep = 48f; private const float ToggleHorizontalInset = 4f; private const float ToggleHeight = 42f; private readonly List<Entry> entries = new List<Entry>(); private readonly List<GameObject> vanilla = new List<GameObject>(); private readonly List<bool> previousStates = new List<bool>(); private GameObject root; private GameObject returnButton; private ServerOptionsGUI options; private ScrollRectEnsureVisible ensureVisible; private GameObject lastSelected; private static readonly FieldInfo SelectedWorldField = AccessTools.Field(typeof(FejdStartup), "m_world"); private long openedWorldUid; private string openedWorldName; internal bool IsOpen { get { if ((Object)(object)root != (Object)null) { return root.activeSelf; } return false; } } internal static EasyLivingPanel GetOrCreate(ServerOptionsGUI options, GameObject button) { EasyLivingPanel componentInChildren = ((Component)options).GetComponentInChildren<EasyLivingPanel>(true); if ((Object)(object)componentInChildren != (Object)null) { return componentInChildren; } componentInChildren = ((Component)options).gameObject.AddComponent<EasyLivingPanel>(); try { componentInChildren.Build(options, button); return componentInChildren; } catch { Object.Destroy((Object)(object)componentInChildren); throw; } } private void Build(ServerOptionsGUI owner, GameObject button) { //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Expected O, but got Unknown //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Expected O, but got Unknown //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Expected O, but got Unknown //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Expected O, but got Unknown //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: 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_0405: Expected O, but got Unknown //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Expected O, but got Unknown //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_086d: Unknown result type (might be due to invalid IL or missing references) options = owner; returnButton = button; Transform parent = owner.m_presetsRoot.transform.parent; Transform transform = owner.m_modifiersRoot.transform; Transform sliderSource = transform.Find("Combat"); Transform val = transform.Find("Death"); Transform toggleSource = transform.Find("Nomap"); Transform val2 = parent.Find("Cancel"); Transform val3 = parent.Find("Done"); Transform val4 = parent.Find("topic"); if ((Object)(object)sliderSource == (Object)null || (Object)(object)val == (Object)null || (Object)(object)toggleSource == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null) { throw new InvalidOperationException("World Modifiers prefab controls unavailable."); } Transform obj = sliderSource; RectTransform val5 = (RectTransform)(object)((obj is RectTransform) ? obj : null); Transform obj2 = sliderSource.Find("label"); RectTransform nativeLabel = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null); Transform obj3 = sliderSource.Find("slider"); RectTransform nativeSlider = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null); Transform obj4 = sliderSource.Find("value_label"); RectTransform nativeValue = (RectTransform)(object)((obj4 is RectTransform) ? obj4 : null); if ((Object)(object)val5 == (Object)null || (Object)(object)nativeLabel == (Object)null || (Object)(object)nativeSlider == (Object)null || (Object)(object)nativeValue == (Object)null) { throw new InvalidOperationException("Native slider geometry unavailable."); } Rect rect = val5.rect; float nativeRowWidth = ((Rect)(ref rect)).width; rect = val5.rect; float nativeRowHeight = ((Rect)(ref rect)).height; float nativeStep = Mathf.Abs(val5.anchoredPosition.y - ((RectTransform)val).anchoredPosition.y); if (nativeRowWidth <= 0f || nativeRowHeight <= 0f || nativeStep <= 0f) { throw new InvalidOperationException("Native slider dimensions are not resolved."); } float num = NativeCenterX(nativeLabel, nativeRowWidth); rect = nativeLabel.rect; float num2 = num - ((Rect)(ref rect)).width * 0.5f; float num3 = NativeCenterX(nativeValue, nativeRowWidth); rect = nativeValue.rect; float num4 = num3 + ((Rect)(ref rect)).width * 0.5f; float nativeCenterShift = (0f - (num2 + num4)) * 0.5f; root = new GameObject("EasyLivingRoot", new Type[1] { typeof(RectTransform) }); root.transform.SetParent(parent, false); Stretch((RectTransform)root.transform, Vector2.zero, Vector2.zero); root.SetActive(false); SetText(Clone(((Component)val4).gameObject, root.transform, "EasyLivingTitle"), "EasyLiving"); GameObject val6 = new GameObject("SettingsScroll", new Type[2] { typeof(RectTransform), typeof(ScrollRect) }); val6.transform.SetParent(root.transform, false); Stretch((RectTransform)val6.transform, new Vector2(4f, 84f), new Vector2(-4f, -55f)); GameObject val7 = new GameObject("Viewport", new Type[3] { typeof(RectTransform), typeof(Image), typeof(RectMask2D) }); val7.transform.SetParent(val6.transform, false); RectTransform val8 = (RectTransform)val7.transform; Stretch(val8, Vector2.zero, Vector2.zero); ((Graphic)val7.GetComponent<Image>()).color = Color.clear; GameObject val9 = new GameObject("Content", new Type[1] { typeof(RectTransform) }); val9.transform.SetParent(val7.transform, false); RectTransform contentRect = (RectTransform)val9.transform; contentRect.anchorMin = new Vector2(0f, 1f); contentRect.anchorMax = new Vector2(1f, 1f); contentRect.pivot = new Vector2(0.5f, 1f); contentRect.anchoredPosition = Vector2.zero; contentRect.sizeDelta = new Vector2(0f, 650f); ScrollRect component = val6.GetComponent<ScrollRect>(); component.viewport = val8; component.content = contentRect; component.horizontal = false; component.vertical = true; component.scrollSensitivity = 34f; ensureVisible = val6.AddComponent<ScrollRectEnsureVisible>(); float y = -12f; AddSlider("ItemWeight", EasyLivingConfig.WeightMode, new string[4] { "Normal", "Half", "Quarter", "Zero" }); AddSlider("StackSize", EasyLivingConfig.StackSize, new string[5] { "Normal", "2x", "3x", "5x", "10x" }); AddSlider("ConsumableDuration", EasyLivingConfig.ConsumableDuration, new string[4] { "Normal", "2x", "3x", "5x" }); AddSlider("PotionCooldown", EasyLivingConfig.PotionCooldown, new string[5] { "100%", "75%", "50%", "25%", "Off" }); AddSlider("BossPowerDuration", EasyLivingConfig.BossPowerDuration, new string[3] { "Normal", "2x", "3x" }); AddSlider("ItemDurability", EasyLivingConfig.ItemDurability, new string[4] { "Normal", "2x", "3x", "5x" }); AddSliderValue("StructureDamage", () => EasyLivingConfig.DamageMode.Value.ToString(), new string[3] { "Vanilla", "Protected", "PvP" }); AddSlider("WorkbenchRange", EasyLivingConfig.WorkbenchRange, new string[4] { "Normal", "1.5x", "2x", "3x" }); AddSlider("BoatSpeed", EasyLivingConfig.BoatSpeed, new string[4] { "Normal", "1.25x", "1.5x", "2x" }); AddSlider("MapDiscovery", EasyLivingConfig.MapDiscoveryRadius, new string[4] { "Normal", "2x", "3x", "5x" }); y -= 10f; float num5 = y; List<RectTransform> toggleRows = new List<RectTransform>(); AddToggle("PreventSkillLoss", EasyLivingConfig.PreventSkillLoss); AddToggle("KeepInventoryOnDeath", EasyLivingConfig.KeepInventoryOnDeath); AddToggle("FireControl", EasyLivingConfig.FireControlEnabled); AddToggle("QuickDeposit", EasyLivingConfig.QuickDepositEnabled); AddToggle("CraftFromChests", EasyLivingConfig.CraftFromChestsEnabled); AddToggle("AutoRepair", EasyLivingConfig.AutoRepairEnabled); AddToggle("AllowVeinMining", EasyLivingConfig.AllowVeinMining); AddToggle("ManualStationResources", EasyLivingConfig.ManualStationResourcesEnabled); AddToggle("AutoEjectCookedFood", EasyLivingConfig.AutoEjectCookedFoodEnabled); AddToggle("ToolStamina", EasyLivingConfig.ToolStaminaEnabled); AddToggle("PreventRainDamage", EasyLivingConfig.PreventRainDamage); LayoutToggleGrid(toggleRows, num5); y = num5 - (float)ToggleRowCount(toggleRows.Count) * 48f; contentRect.sizeDelta = new Vector2(0f, 0f - y + 18f); GameObject val10 = Clone(((Component)val2).gameObject, root.transform, "Back"); GameObject val11 = Clone(((Component)val3).gameObject, root.transform, "Done"); PrepareButton(val10, "back"); PrepareButton(val11, "done"); ConnectNavigation(val10.GetComponent<Selectable>(), val11.GetComponent<Selectable>()); vanilla.Add(owner.m_presetsRoot); vanilla.Add(owner.m_modifiersRoot); vanilla.Add(((Component)val2).gameObject); vanilla.Add(((Component)val3).gameObject); vanilla.Add(((Component)val4).gameObject); void AddSlider(string id, ConfigEntry<string> config, params string[] choices) { AddSliderValue(id, () => config.Value, choices); } void AddSliderValue(string id, Func<string> read, params string[] choices) { //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown GameObject obj5 = Clone(((Component)sliderSource).gameObject, (Transform)(object)contentRect, "Setting_" + id); Place(obj5.GetComponent<RectTransform>(), y, nativeRowHeight); Transform obj6 = obj5.transform.Find("label"); SetText((obj6 != null) ? ((Component)obj6).gameObject : null, EasyLivingText.Panel(id)); Transform obj7 = obj5.transform.Find("label"); TMP_Text val12 = ((obj7 != null) ? ((Component)obj7).GetComponent<TMP_Text>() : null); if ((Object)(object)val12 != (Object)null) { ApplyNativeGeometry(val12.rectTransform, nativeLabel, nativeRowWidth, nativeRowHeight, nativeCenterShift); } Slider componentInChildren = obj5.GetComponentInChildren<Slider>(true); Transform obj8 = obj5.transform.Find("value_label"); TMP_Text val13 = ((obj8 != null) ? ((Component)obj8).GetComponent<TMP_Text>() : null); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)val13 == (Object)null) { throw new InvalidOperationException("Native slider missing: " + id); } Transform transform2 = ((Component)componentInChildren).transform; ApplyNativeGeometry((RectTransform)(object)((transform2 is RectTransform) ? transform2 : null), nativeSlider, nativeRowWidth, nativeRowHeight, nativeCenterShift); ApplyNativeGeometry(val13.rectTransform, nativeValue, nativeRowWidth, nativeRowHeight, nativeCenterShift); KeySlider componentInChildren2 = obj5.GetComponentInChildren<KeySlider>(true); if ((Object)(object)componentInChildren2 != (Object)null) { Object.DestroyImmediate((Object)(object)componentInChildren2); } componentInChildren.onValueChanged = new SliderEvent(); componentInChildren.wholeNumbers = true; componentInChildren.minValue = 0f; componentInChildren.maxValue = choices.Length - 1; Entry entry = new Entry { Id = id, Control = (Selectable)(object)componentInChildren, Slider = componentInChildren, Label = val12, ValueLabel = val13, Choices = choices, ReadChoice = read }; entries.Add(entry); ((UnityEvent<float>)(object)componentInChildren.onValueChanged).AddListener((UnityAction<float>)delegate { UpdateValue(entry); }); if (id == "StructureDamage") { EasyLivingStructureDamageTooltip tooltip = ((Component)componentInChildren).gameObject.AddComponent<EasyLivingStructureDamageTooltip>(); tooltip.Initialize(options.m_toolTipText, componentInChildren, choices); ((UnityEvent<float>)(object)componentInChildren.onValueChanged).AddListener((UnityAction<float>)delegate { tooltip.Refresh(); }); } else { AddTooltip(((Component)componentInChildren).gameObject, id); } y -= nativeStep; } void AddToggle(string id, ConfigEntry<bool> config) { //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown GameObject val12 = Clone(((Component)toggleSource).gameObject, (Transform)(object)contentRect, "Setting_" + id); toggleRows.Add(val12.GetComponent<RectTransform>()); Transform obj5 = val12.transform.Find("Label"); SetText((obj5 != null) ? ((Component)obj5).gameObject : null, EasyLivingText.Panel(id)); Transform obj6 = val12.transform.Find("Label"); TMP_Text val13 = ((obj6 != null) ? ((Component)obj6).GetComponent<TMP_Text>() : null); if ((Object)(object)val13 != (Object)null) { SetRelativeBox(val13.rectTransform, 0.02f, 0.82f, 0f, 2f, 40f); ConfigureModuleLabel(val13); } Transform obj7 = val12.transform.Find("Background"); RectTransform val14 = (RectTransform)(object)((obj7 is RectTransform) ? obj7 : null); if ((Object)(object)val14 != (Object)null) { SetRelativeBox(val14, 0.85f, 0.97f, 0f, 0f); } Toggle component2 = val12.GetComponent<Toggle>(); if ((Object)(object)component2 == (Object)null) { throw new InvalidOperationException("Native toggle missing: " + id); } KeyToggle component3 = val12.GetComponent<KeyToggle>(); if ((Object)(object)component3 != (Object)null) { Object.DestroyImmediate((Object)(object)component3); } component2.onValueChanged = new ToggleEvent(); entries.Add(new Entry { Id = id, Control = (Selectable)(object)component2, Toggle = component2, Label = val13, ReadToggle = () => config.Value }); AddTooltip(((Component)component2).gameObject, id); } } private static GameObject Clone(GameObject source, Transform parent, string name) { GameObject obj = Object.Instantiate<GameObject>(source, source.transform.parent, false); ((Object)obj).name = name; obj.transform.SetParent(parent, false); return obj; } private static void Stretch(RectTransform rect, Vector2 min, Vector2 max) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = min; rect.offsetMax = max; } private static void Place(RectTransform rect, float top, float height) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = new Vector2(0f, 1f); rect.anchorMax = new Vector2(1f, 1f); rect.pivot = new Vector2(0.5f, 1f); rect.anchoredPosition = new Vector2(0f, top); rect.sizeDelta = new Vector2(0f, height); } private static int ToggleRowCount(int toggleCount) { return (toggleCount + 2 - 1) / 2; } private static void LayoutToggleGrid(IList<RectTransform> rows, float top) { bool flag = rows.Count % 2 != 0; for (int i = 0; i < rows.Count; i++) { int num = i / 2; int column = i % 2; bool centered = flag && i == rows.Count - 1; PlaceToggle(rows[i], top - (float)num * 48f, column, centered); } } private static void PlaceToggle(RectTransform rect, float top, int column, bool centered) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) float num = (centered ? 0.25f : ((float)column * 0.5f)); rect.anchorMin = new Vector2(num, 1f); rect.anchorMax = new Vector2(num + 0.5f, 1f); rect.pivot = new Vector2(0f, 1f); rect.anchoredPosition = new Vector2(4f, top); rect.sizeDelta = new Vector2(-8f, 42f); } private static float NativeCenterX(RectTransform child, float rowWidth) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) return (child.anchorMin.x - 0.5f) * rowWidth + child.anchoredPosition.x; } private static void ApplyNativeGeometry(RectTransform target, RectTransform source, float rowWidth, float rowHeight, float centerShift) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) target.anchorMin = new Vector2(0.5f, 0.5f); target.anchorMax = target.anchorMin; target.pivot = source.pivot; target.anchoredPosition = new Vector2(NativeCenterX(source, rowWidth) + centerShift, (source.anchorMin.y - 0.5f) * rowHeight + source.anchoredPosition.y); Rect rect = source.rect; target.sizeDelta = ((Rect)(ref rect)).size; } private static void SetRelativeBox(RectTransform rect, float leftAnchor, float rightAnchor, float leftPadding, float rightPadding, float minHeight = 28f) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Rect rect2 = rect.rect; float num = Mathf.Max(minHeight, ((Rect)(ref rect2)).height); rect.anchorMin = new Vector2(leftAnchor, 0.5f); rect.anchorMax = new Vector2(rightAnchor, 0.5f); rect.pivot = new Vector2(0.5f, 0.5f); rect.offsetMin = new Vector2(leftPadding, (0f - num) * 0.5f); rect.offsetMax = new Vector2(0f - rightPadding, num * 0.5f); } private static void ConfigureModuleLabel(TMP_Text label) { label.alignment = (TextAlignmentOptions)4097; label.textWrappingMode = (TextWrappingModes)1; label.maxVisibleLines = 2; label.enableAutoSizing = true; label.fontSizeMin = 16f; label.fontSizeMax = 18f; } private static void SetText(GameObject obj, string value) { TMP_Text val = (((Object)(object)obj == (Object)null) ? null : obj.GetComponent<TMP_Text>()); if ((Object)(object)val == (Object)null && (Object)(object)obj != (Object)null) { val = obj.GetComponentInChildren<TMP_Text>(true); } if ((Object)(object)val != (Object)null) { val.text = value; } } private void PrepareButton(GameObject obj, string textKey) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Button component = obj.GetComponent<Button>(); KeyButton component2 = obj.GetComponent<KeyButton>(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Native panel button missing."); } component.onClick = new ButtonClickedEvent(); if (textKey == "done") { ((UnityEvent)component.onClick).AddListener(new UnityAction(SaveAndClose)); } else { ((UnityEvent)component.onClick).AddListener(new UnityAction(Close)); } SetText(obj, EasyLivingText.Panel(textKey)); } private string SelectedChoice(string id) { Entry entry = entries.Find((Entry e) => e.Id == id); if ((Object)(object)entry?.Slider == (Object)null) { throw new InvalidOperationException("Missing slider: " + id); } return entry.Choices[Mathf.Clamp(Mathf.RoundToInt(entry.Slider.value), 0, entry.Choices.Length - 1)]; } private bool SelectedToggle(string id) { Entry? entry = entries.Find((Entry e) => e.Id == id); if ((Object)(object)entry?.Toggle == (Object)null) { throw new InvalidOperationException("Missing toggle: " + id); } return entry.Toggle.isOn; } private void SaveAndClose() { try { GameplaySnapshot value = new GameplaySnapshot(SelectedChoice("ItemWeight"), SelectedChoice("ConsumableDuration"), SelectedChoice("BossPowerDuration"), SelectedChoice("ItemDurability"), SelectedToggle("PreventSkillLoss"), (StructureDamageMode)Enum.Parse(typeof(StructureDamageMode), SelectedChoice("StructureDamage")), SelectedChoice("StackSize"), SelectedToggle("FireControl"), SelectedChoice("BoatSpeed"), SelectedChoice("WorkbenchRange"), SelectedChoice("MapDiscovery"), SelectedToggle("QuickDeposit"), SelectedToggle("CraftFromChests"), SelectedToggle("AutoRepair"), SelectedToggle("AllowVeinMining"), SelectedToggle("ManualStationResources"), SelectedToggle("AutoEjectCookedFood"), SelectedToggle("KeepInventoryOnDeath"), SelectedToggle("ToolStamina"), SelectedToggle("PreventRainDamage"), SelectedChoice("PotionCooldown")); World val = SelectedWorld(); if (openedWorldUid != 0L) { if (val == null || val.m_uid != openedWorldUid) { throw new InvalidOperationException("Selected world changed while EasyLiving settings were open."); } WorldProfiles.Save(openedWorldUid, openedWorldName, value); } Close(); } catch (Exception ex) { ManualLogSource modLog = EasyLivingPlugin.ModLog; if (modLog != null) { modLog.LogError((object)("EasyLiving settings could not be saved: " + ex)); } } } private void ConnectNavigation(Selectable back, Selectable done) { //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_00b0: 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_00f3: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < entries.Count; i++) { Navigation navigation = entries[i].Control.navigation; ((Navigation)(ref navigation)).mode = (Mode)4; ((Navigation)(ref navigation)).selectOnUp = ((i == 0) ? back : entries[i - 1].Control); ((Navigation)(ref navigation)).selectOnDown = ((i == entries.Count - 1) ? back : entries[i + 1].Control); ((Navigation)(ref navigation)).selectOnLeft = null; ((Navigation)(ref navigation)).selectOnRight = null; entries[i].Control.navigation = navigation; } Navigation navigation2 = back.navigation; ((Navigation)(ref navigation2)).mode = (Mode)4; ((Navigation)(ref navigation2)).selectOnLeft = done; ((Navigation)(ref navigation2)).selectOnRight = done; ((Navigation)(ref navigation2)).selectOnUp = entries[entries.Count - 1].Control; back.navigation = navigation2; Navigation navigation3 = done.navigation; ((Navigation)(ref navigation3)).mode = (Mode)4; ((Navigation)(ref navigation3)).selectOnLeft = back; ((Navigation)(ref navigation3)).selectOnRight = back; ((Navigation)(ref navigation3)).selectOnUp = entries[entries.Count - 1].Control; done.navigation = navigation3; } private void AddTooltip(GameObject obj, string id) { obj.AddComponent<EasyLivingPanelTooltip>().Initialize(options.m_toolTipText, "tip." + id); } private static void UpdateValue(Entry entry) { int num = Mathf.Clamp(Mathf.RoundToInt(entry.Slider.value), 0, entry.Choices.Length - 1); entry.ValueLabel.text = EasyLivingText.PanelValue(entry.Id, entry.Choices[num]); } internal void Open() { if ((Object)(object)root == (Object)null || root.activeSelf) { return; } World val = SelectedWorld(); openedWorldUid = val?.m_uid ?? 0; openedWorldName = ((openedWorldUid != 0L) ? val.m_worldName : null); GameplaySnapshot value = WorldProfiles.Load(openedWorldUid, EasyLivingConfig.Configured()); foreach (Entry entry in entries) { if ((Object)(object)entry.Label != (Object)null) { entry.Label.text = EasyLivingText.Panel(entry.Id); } if ((Object)(object)entry.Slider != (Object)null) { int num = Array.IndexOf(entry.Choices, ProfileChoice(value, entry.Id)); entry.Slider.SetValueWithoutNotify((float)Mathf.Max(0, num)); UpdateValue(entry); } else { entry.Toggle.SetIsOnWithoutNotify(ProfileToggle(value, entry.Id)); } } previousStates.Clear(); foreach (GameObject item in vanilla) { previousStates.Add(item.activeSelf); item.SetActive(false); } root.SetActive(true); root.GetComponentInChildren<ScrollRect>(true).verticalNormalizedPosition = 1f; EventSystem current3 = EventSystem.current; if (current3 != null) { current3.SetSelectedGameObject(((Component)entries[0].Control).gameObject); } } private static World SelectedWorld() { object? obj = SelectedWorldField?.GetValue(FejdStartup.instance); return (World)((obj is World) ? obj : null); } private static string ProfileChoice(GameplaySnapshot value, string id) { return id switch { "ItemWeight" => value.WeightMode, "StackSize" => value.StackSize, "ConsumableDuration" => value.ConsumableDuration, "PotionCooldown" => value.PotionCooldown, "BossPowerDuration" => value.BossPowerDuration, "ItemDurability" => value.ItemDurability, "StructureDamage" => value.DamageMode.ToString(), "WorkbenchRange" => value.WorkbenchRange, "BoatSpeed" => value.BoatSpeed, "MapDiscovery" => value.MapDiscoveryRadius, _ => throw new InvalidOperationException("Unknown profile choice: " + id), }; } private static bool ProfileToggle(GameplaySnapshot value, string id) { return id switch { "PreventSkillLoss" => value.PreventSkillLoss, "KeepInventoryOnDeath" => value.KeepInventoryOnDeath, "FireControl" => value.FireControlEnabled, "QuickDeposit" => value.QuickDepositEnabled, "CraftFromChests" => value.CraftFromChestsEnabled, "AutoRepair" => value.AutoRepairEnabled, "AllowVeinMining" => value.AllowVeinMining, "ManualStationResources" => value.ManualStationResourcesEnabled, "AutoEjectCookedFood" => value.AutoEjectCookedFoodEnabled, "ToolStamina" => value.ToolStaminaEnabled, "PreventRainDamage" => value.PreventRainDamage, _ => throw new InvalidOperationException("Unknown profile toggle: " + id), }; } internal void Close() { if (!((Object)(object)root == (Object)null) && root.activeSelf) { root.SetActive(false); for (int i = 0; i < vanilla.Count; i++) { vanilla[i].SetActive(previousStates[i]); } if ((Object)(object)options.m_toolTipText != (Object)null) { options.m_toolTipText.text = string.Empty; } EventSystem current = EventSystem.current; if (current != null) { current.SetSelectedGameObject(returnButton); } } } private void Update() { if ((Object)(object)root == (Object)null || !root.activeSelf || (Object)(object)EventSystem.current == (Object)null) { return; } GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject; if ((Object)(object)currentSelectedGameObject == (Object)null || (Object)(object)currentSelectedGameObject == (Object)(object)lastSelected) { return; } lastSelected = currentSelectedGameObject; foreach (Entry entry in entries) { if ((Object)(object)((Component)entry.Control).gameObject == (Object)(object)currentSelectedGameObject) { ? val = ensureVisible; Transform transform = ((Component)entry.Control).transform; ((ScrollRectEnsureVisible)val).CenterOnItem((RectTransform)(object)((transform is RectTransform) ? transform : null)); break; } } } private void OnDestroy() { Close(); if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } } } internal sealed class EasyLivingPanelTooltip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler { private TMP_Text target; private string key; internal void Initialize(TMP_Text text, string textKey) { target = text; key = textKey; } public void OnPointerEnter(PointerEventData eventData) { if ((Object)(object)target != (Object)null) { target.text = EasyLivingText.Panel(key); } } public void OnPointerExit(PointerEventData eventData) { if ((Object)(object)target != (Object)null) { target.text = string.Empty; } } public void OnSelect(BaseEventData eventData) { if ((Object)(object)target != (Object)null) { target.text = EasyLivingText.Panel(key); } } public void OnDeselect(BaseEventData eventData) { if ((Object)(object)target != (Object)null) { target.text = string.Empty; } } } internal sealed class EasyLivingStructureDamageTooltip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler { private TMP_Text target; private Slider slider; private string[] choices; private bool hovered; private bool focused; internal void Initialize(TMP_Text text, Slider control, string[] modes) { target = text; slider = control; choices = modes; } internal void Refresh() { if (!((Object)(object)target == (Object)null) && !((Object)(object)slider == (Object)null) && choices != null && (hovered || focused)) { int num = Mathf.Clamp(Mathf.RoundToInt(slider.value), 0, choices.Length - 1); string text = choices[num]; target.text = EasyLivingText.Panel("StructureDamage") + "\n" + EasyLivingText.Panel("structure.mode." + text) + "\n" + EasyLivingText.Panel("structure.description." + text); } } public