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 RestlessCore v0.1.12
RestlessCore.dll
Decompiled 42 minutes 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.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GUIFramework; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using RestlessQoL.Api; using RestlessQoL.Building; using RestlessQoL.Core; using RestlessQoL.HudTweaks; using RestlessQoL.PlayerTweaks; using RestlessQoL.Production; using RestlessQoL.Storage; using RestlessQoL.World; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RestlessCore")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.12.0")] [assembly: AssemblyInformationalVersion("0.1.12+a156afa192f778cf994f791f325d336d8a464aa4")] [assembly: AssemblyProduct("RestlessCore")] [assembly: AssemblyTitle("RestlessCore")] [assembly: InternalsVisibleTo("RestlessPiles")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.12.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RestlessQoL { [BepInPlugin("restless.core", "RestlessCore", "0.1.12")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "restless.core"; public const string PluginName = "RestlessCore"; public const string PluginVersion = "0.1.12"; private readonly FeatureModule[] _modules = new FeatureModule[40] { new StorageSync(), new CraftFromStorage(), new BuildFromStorage(), new QuickStack(), new Restock(), new PetPantry(), new GroundVacuum(), new StationPull(), new AreaRepair(), new WorkbenchTweaks(), new DeathPins(), new SwimWield(), new CrossbowState(), new FriendlyFire(), new AxeCombo(), new AutoRepair(), new StackSizes(), new HonestItems(), new EternalFire(), new DigDeeper(), new NetworkUncap(), new FloatingItems(), new Ledger(), new SettingsUi(), new MenuScreen(), new BuffList(), new MapChrome(), new MapScreen(), new MapDots(), new Notices(), new Hotbar(), new InventoryScreen(), new ItemTooltip(), new ExtraSlots(), new SlotLock(), new Vitals(), new EquipHint(), new BuildMenu(), new ActionHints(), new LookHints() }; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); Kit.Warm(); FeatureModule[] modules = _modules; for (int i = 0; i < modules.Length; i++) { modules[i].TryLoad(); } Log.LogInfo((object)string.Format("{0} {1} loaded ({2} modules registered).", "RestlessCore", "0.1.12", _modules.Length)); } private void Update() { if (Console.IsVisible()) { return; } if (SettingsUi.IsOpen) { FeatureModule[] modules = _modules; foreach (FeatureModule featureModule in modules) { if (featureModule is SettingsUi) { featureModule.Tick(); } } } else { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } bool flag = InventoryGui.IsVisible(); FeatureModule[] modules = _modules; foreach (FeatureModule featureModule2 in modules) { if (!flag || featureModule2.TickInMenus) { featureModule2.Tick(); } } } } } } namespace RestlessQoL.World { public sealed class DigDeeper : FeatureModule { [HarmonyPatch] private static class Patches { private const float CapEpsilon = 0.05f; private static float VanillaCap() { return 8f; } private static float MaxDelta() { if (!ModConfig.DigDeeperEnabled.Value) { return VanillaCap(); } return ModConfig.DigMaxDelta.Value; } private static float MinDelta() { return 0f - MaxDelta(); } [HarmonyPrefix] [HarmonyPatch(typeof(Heightmap), "AtMaxWorldLevelDepth")] private static bool AtMaxWorldLevelDepth(Heightmap __instance, Vector3 worldPos, ref bool __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.DigDeeperEnabled.Value) { return true; } float num = default(float); __instance.GetWorldHeight(worldPos, ref num); float num2 = default(float); __instance.GetWorldBaseHeight(worldPos, ref num2); __result = Mathf.Max(num2 - num, 0f) >= MaxDelta() - 0.05f; return false; } [HarmonyTranspiler] [HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")] private static IEnumerable<CodeInstruction> RaiseTerrain(IEnumerable<CodeInstruction> instructions) { return ReplaceLevelClamp(instructions, "RaiseTerrain"); } [HarmonyTranspiler] [HarmonyPatch(typeof(TerrainComp), "LevelTerrain")] private static IEnumerable<CodeInstruction> LevelTerrain(IEnumerable<CodeInstruction> instructions) { return ReplaceLevelClamp(instructions, "LevelTerrain"); } [HarmonyTranspiler] [HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")] private static IEnumerable<CodeInstruction> ApplyToHeightmap(IEnumerable<CodeInstruction> instructions) { return ReplaceLevelClamp(instructions, "ApplyToHeightmap"); } private static IEnumerable<CodeInstruction> ReplaceLevelClamp(IEnumerable<CodeInstruction> instructions, string method) { float vanilla = VanillaCap(); int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num) { if (Math.Abs(num - vanilla) < 0.001f) { replaced++; yield return Retarget(instruction, "MaxDelta"); continue; } if (Math.Abs(num + vanilla) < 0.001f) { replaced++; yield return Retarget(instruction, "MinDelta"); continue; } } yield return instruction; } if (replaced == 0) { Plugin.Log.LogWarning((object)$"world.digdeeper: {method} has no ±{vanilla} clamps — 1.0 moved the cap, this feature is a no-op there."); } } private static CodeInstruction Retarget(CodeInstruction from, string method) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_003f: Expected O, but got Unknown CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Patches), method, (Type[])null, (Type[])null)); val.labels.AddRange(from.labels); val.blocks.AddRange(from.blocks); return val; } } public override string Id => "world.digdeeper"; public override bool Enabled => true; } public sealed class FloatingItems : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(ItemDrop), "Awake")] private static void Awake(ItemDrop __instance) { if (ModConfig.FloatingItemsEnabled.Value) { Apply(__instance); } } } private static HashSet<string>? _sink; private static HashSet<string>? _extra; private static Floating? _template; public override string Id => "world.floating"; public override bool Enabled => true; private static HashSet<string> Sink => _sink ?? (_sink = Parse(ModConfig.FloatingSinkList.Value)); private static HashSet<string> Extra => _extra ?? (_extra = Parse(ModConfig.FloatingExtraList.Value)); protected override void OnLoaded() { ModConfig.FloatingSinkList.SettingChanged += Invalidate; ModConfig.FloatingExtraList.SettingChanged += Invalidate; } private static void Invalidate(object sender, EventArgs e) { _sink = null; _extra = null; } private static HashSet<string> Parse(string raw) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(raw)) { return hashSet; } string[] array = raw.Split(new char[3] { ',', ';', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { hashSet.Add(text); } } return hashSet; } private static string PrefabName(ItemDrop drop) { string prefabName = Utils.GetPrefabName(((Component)drop).gameObject); if (!string.IsNullOrEmpty(prefabName)) { return prefabName; } return ((Object)((Component)drop).gameObject).name; } private static bool ForceSink(string prefab) { return Sink.Contains(prefab); } private static bool ForceFloat(string prefab) { if (!ModConfig.FloatingEverything.Value) { return Extra.Contains(prefab); } return true; } private static Floating? Template() { if ((Object)(object)_template != (Object)null) { return _template; } ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab("Wood") : null); _template = (((Object)(object)val != (Object)null) ? val.GetComponent<Floating>() : null); return _template; } private static void Apply(ItemDrop drop) { if ((Object)(object)drop == (Object)null) { return; } string prefab = PrefabName(drop); if (ForceSink(prefab)) { if (!((Object)(object)drop.m_floating == (Object)null)) { Object.Destroy((Object)(object)drop.m_floating); drop.m_floating = null; } } else if (ForceFloat(prefab) && !((Object)(object)drop.m_floating != (Object)null)) { Floating val = ((Component)drop).gameObject.AddComponent<Floating>(); Floating val2 = Template(); if ((Object)(object)val2 != (Object)null) { val.m_waterLevelOffset = val2.m_waterLevelOffset; val.m_forceDistance = val2.m_forceDistance; val.m_force = val2.m_force; val.m_balanceForceFraction = val2.m_balanceForceFraction; val.m_damping = val2.m_damping; } drop.m_floating = val; } } } public sealed class NetworkUncap : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyTranspiler] [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] private static IEnumerable<CodeInstruction> SendWindow(IEnumerable<CodeInstruction> instructions) { MethodInfo call = AccessTools.Method(typeof(NetworkUncap), "Window", (Type[])null, (Type[])null); int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_I4 && instruction.operand is int num && num == 10240) { replaced++; CodeInstruction val = new CodeInstruction(OpCodes.Call, (object)call); val.labels.AddRange(instruction.labels); val.blocks.AddRange(instruction.blocks); yield return val; } else { yield return instruction; } } if (replaced == 0) { Plugin.Log.LogWarning((object)"net.uncap: SendZDOs has no 10240 window — 1.0 moved the cap, this feature is a no-op there."); } } [HarmonyPostfix] [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] private static void AfterSteam() { ApplySteam(); } } private const int VanillaWindow = 10240; private const int VanillaRate = 153600; public override string Id => "net.uncap"; public override bool Enabled => true; protected override void OnLoaded() { ModConfig.NetworkUncapEnabled.SettingChanged += delegate { ApplySteam(); }; } private static int Window() { if (!ModConfig.NetworkUncapEnabled.Value) { return 10240; } return 32768; } private static int Rate() { if (!ModConfig.NetworkUncapEnabled.Value) { return 153600; } return 524288; } private static void ApplySteam() { GCHandle gCHandle = GCHandle.Alloc(Rate(), GCHandleType.Pinned); try { SteamNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)11, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle.AddrOfPinnedObject()); } catch (Exception ex) { if (ex.Message.IndexOf("not initialized", StringComparison.OrdinalIgnoreCase) < 0) { Plugin.Log.LogWarning((object)("net.uncap steam: " + ex.Message)); } } finally { gCHandle.Free(); } } } } namespace RestlessQoL.Storage { public sealed class GroundVacuum : FeatureModule { private float _next; public override string Id => "storage.vacuum"; public override bool Enabled { get { if (ModConfig.StorageEnabled.Value) { return ModConfig.VacuumEnabled.Value; } return false; } } public override bool TickInMenus => true; public override void Tick() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || Time.time < _next) { return; } _next = Time.time + ModConfig.VacuumInterval.Value; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float value = ModConfig.StorageRange.Value; Vector3 position = ((Component)localPlayer).transform.position; ItemDrop[] array = ItemDrop.s_instances.ToArray(); foreach (ItemDrop val in array) { if (!((Object)(object)val == (Object)null) && val.m_itemData?.m_shared != null && !val.m_itemData.m_shared.m_questItem) { Vector3 val2 = ((Component)val).transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > value * value)) { NearbyStorage.TryDepositDrop(localPlayer, val); } } } } } public static class NearbyStorage { private sealed class Pop : IDisposable { private readonly Action _pop; public Pop(Action pop) { _pop = pop; } public void Dispose() { _pop(); } } [ThreadStatic] private static int _skipPatches; [ThreadStatic] private static int _directTake; private static readonly List<Container> Cache = new List<Container>(); private static int _cacheFrame = -1; private static int _cachePlayer; private static float _cacheRange; private static readonly HashSet<ZDOID> Depositing = new HashSet<ZDOID>(); internal static bool SkipPatches => _skipPatches > 0; internal static bool DirectTake => _directTake > 0; internal static IDisposable SuppressPatches() { _skipPatches++; return new Pop(delegate { _skipPatches--; }); } internal static IDisposable BeginDirectTake() { _directTake++; return new Pop(delegate { _directTake--; }); } private static bool Ready(Container container) { if ((Object)(object)container == (Object)null || !((Behaviour)container).isActiveAndEnabled) { return false; } ZNetView nview = container.m_nview; if ((Object)(object)nview != (Object)null) { return nview.IsValid(); } return false; } internal static bool CanWrite(Container container) { if (Ready(container)) { return container.IsOwner(); } return false; } public static bool IsLocalPlayerInventory(Inventory inventory) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && inventory != null) { return ((Humanoid)localPlayer).GetInventory() == inventory; } return false; } public static int CountVanilla(Inventory inventory, string sharedName, int quality = -1, bool worldLevel = false) { using (SuppressPatches()) { return inventory.CountItems(sharedName, quality, worldLevel); } } public static IEnumerable<Container> ForPlayer(Player player, float range) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || range <= 0f) { return Array.Empty<Container>(); } int frameCount = Time.frameCount; int instanceID = ((Object)player).GetInstanceID(); if (frameCount == _cacheFrame && instanceID == _cachePlayer && Mathf.Approximately(_cacheRange, range)) { return Cache; } Cache.Clear(); _cacheFrame = frameCount; _cachePlayer = instanceID; _cacheRange = range; foreach (Container item in NearbyQuery.UniqueInSphere<Container>(((Component)player).transform.position, range)) { if (Ready(item) && item.CheckAccess(player.GetPlayerID())) { if (item.GetInventory() == null) { item.Load(); } if (item.GetInventory() != null) { Cache.Add(item); } } } return Cache; } public static IEnumerable<Container> ForLocalPlayer() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !ModConfig.StorageEnabled.Value) { return Array.Empty<Container>(); } return ForPlayer(localPlayer, ModConfig.StorageRange.Value); } public static IEnumerable<Container> Around(Vector3 origin, float range, long playerId) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (range <= 0f) { return Array.Empty<Container>(); } List<Container> list = new List<Container>(); foreach (Container item in NearbyQuery.UniqueInSphere<Container>(origin, range)) { if (Ready(item) && (playerId == 0L || item.CheckAccess(playerId))) { if (item.GetInventory() == null) { item.Load(); } if (item.GetInventory() != null) { list.Add(item); } } } return list; } public static int TryConsumeAround(Vector3 origin, float range, long playerId, string sharedName, int amount, bool honorLeaveOne = true, int quality = -1, bool worldLevel = false) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0) { return 0; } int num = 0; foreach (Container item in Around(origin, range, playerId)) { num += StorageSync.RequestPull(item, playerId, sharedName, amount - num, honorLeaveOne, quality, worldLevel, null); if (num >= amount) { break; } } return num; } public static int Count(string sharedName, int quality = -1, bool worldLevel = false) { int num = 0; foreach (Container item in ForLocalPlayer()) { num += Pullable(item.GetInventory().CountItems(sharedName, quality, worldLevel), honorLeaveOne: true); } return num; } internal static int Pullable(int have, bool honorLeaveOne) { if (have <= 0) { return 0; } if (honorLeaveOne && ModConfig.LeaveOne.Value) { return Mathf.Max(0, have - 1); } return have; } public static bool Has(string sharedName, int quality = -1, bool worldLevel = false) { return Count(sharedName, quality, worldLevel) > 0; } public static bool TryCloneIfPresent(ItemDrop drop, out ItemData item) { item = null; if (drop?.m_itemData?.m_shared == null) { return false; } string name = drop.m_itemData.m_shared.m_name; ItemData val = null; foreach (Container item2 in ForLocalPlayer()) { val = item2.GetInventory().GetItem(name, -1, false); if (val != null) { break; } } if (val == null) { return false; } item = val.Clone(); item.m_stack = 1; return EnsureDropPrefab(item, drop); } internal static bool EnsureDropPrefab(ItemData? item, ItemDrop? from = null) { if (item == null) { return false; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return true; } if ((Object)(object)from != (Object)null && (Object)(object)((Component)from).gameObject != (Object)null) { item.m_dropPrefab = ((Component)from).gameObject; return true; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || item.m_shared == null) { return false; } GameObject itemPrefab = instance.GetItemPrefab(item.m_shared); if ((Object)(object)itemPrefab == (Object)null) { return false; } item.m_dropPrefab = itemPrefab; return true; } public static int TryConsume(string sharedName, int amount, bool honorLeaveOne = true, int quality = -1, bool worldLevel = false) { if (amount <= 0) { return 0; } long playerId = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); int num = 0; foreach (Container item in ForLocalPlayer()) { num += StorageSync.RequestPull(item, playerId, sharedName, amount - num, honorLeaveOne, quality, worldLevel, null); if (num >= amount) { break; } } return num; } public static void RequestConsume(string sharedName, int amount, Action<int> done, bool honorLeaveOne = true, int quality = -1, bool worldLevel = false) { if (amount <= 0) { done(0); return; } long playerId = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); RequestConsumeFrom(new List<Container>(ForLocalPlayer()), playerId, sharedName, amount, honorLeaveOne, quality, worldLevel, 0, done); } public static bool HasRequirements(Player player, Requirement[] requirements, int qualityLevel, int amount) { if ((Object)(object)player == (Object)null || requirements == null) { return false; } foreach (Requirement val in requirements) { if (!((Object)(object)val.m_resItem == (Object)null)) { int num = val.GetAmount(qualityLevel) * Mathf.Max(1, amount); string name = val.m_resItem.m_itemData.m_shared.m_name; if (CountVanilla(((Humanoid)player).GetInventory(), name, -1, worldLevel: true) + Count(name, -1, worldLevel: true) < num) { return false; } } } return true; } public static void TakeShortfall(Inventory inventory, string sharedName, ref int amount, int quality = -1, bool worldLevel = false) { if (!SkipPatches && IsLocalPlayerInventory(inventory) && amount > 0) { int num = CountVanilla(inventory, sharedName, quality, worldLevel); if (num < amount) { amount -= TryConsume(sharedName, amount - num, honorLeaveOne: true, quality, worldLevel); } } } public static int TryDeposit(Player player, ItemData item) { if ((Object)(object)player == (Object)null || item?.m_shared == null) { return 0; } Inventory inventory = ((Humanoid)player).GetInventory(); int num = 0; foreach (Container item2 in ForPlayer(player, ModConfig.StorageRange.Value)) { if (!CanWrite(item2)) { continue; } Inventory inventory2 = item2.GetInventory(); if (inventory2 == null || inventory2 == inventory || !inventory2.HaveItem(item.m_shared.m_name, true)) { continue; } int num2 = MergeInto(inventory2, item, item.m_stack); if (item.m_stack - num2 > 0) { num2 += PlaceNewStacks(inventory2, item, item.m_stack - num2); } if (num2 > 0) { inventory2.Changed(true, false); item.m_stack -= num2; num += num2; if (item.m_stack <= 0) { break; } } } return num; } private static int MergeInto(Inventory dest, ItemData source, int amount) { int num = 0; foreach (ItemData allItem in dest.GetAllItems()) { if (num < amount && allItem?.m_shared != null && !(allItem.m_shared.m_name != source.m_shared.m_name) && allItem.m_quality == source.m_quality && allItem.m_worldLevel == source.m_worldLevel) { int num2 = allItem.m_shared.m_maxStackSize - allItem.m_stack; if (num2 > 0) { int num3 = Mathf.Min(num2, amount - num); allItem.m_stack += num3; num += num3; } } } return num; } private static int PlaceNewStacks(Inventory dest, ItemData source, int amount) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) int i; int num2; for (i = 0; i < amount; i += num2) { Vector2i val = dest.FindEmptySlot(true); if (val.x < 0) { break; } int stack = Mathf.Min(source.m_shared.m_maxStackSize, amount - i); ItemData val2 = source.Clone(); val2.m_stack = stack; val2.m_equipped = false; val2.m_gridPos = val; int num = dest.CountItems(source.m_shared.m_name, -1, true); dest.AddItem(val2); num2 = dest.CountItems(source.m_shared.m_name, -1, true) - num; if (num2 <= 0) { break; } } return i; } public static int TryDepositDrop(Player player, ItemDrop drop) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || drop?.m_itemData?.m_shared == null || (Object)(object)drop.m_nview == (Object)null || !drop.m_nview.IsValid()) { return 0; } if (!drop.CanPickup(true)) { return 0; } ZDOID id = drop.m_nview.GetZDO().m_uid; if (!BeginDeposit(id)) { return 0; } ItemData item = drop.m_itemData; int result = TryDeposit(player, item); if (item.m_stack <= 0) { FinishDrop(drop, item); EndDeposit(id); return result; } RequestDeposit(player, item, drop, delegate { //IL_0012: Unknown result type (might be due to invalid IL or missing references) FinishDrop(drop, item); EndDeposit(id); }); return result; } public static void RequestDeposit(Player player, ItemData item, ItemDrop? drop, Action<int> done) { if ((Object)(object)player == (Object)null || item?.m_shared == null || item.m_stack <= 0) { done(0); return; } long playerID = player.GetPlayerID(); List<Container> list = new List<Container>(); foreach (Container item2 in ForPlayer(player, ModConfig.StorageRange.Value)) { if (!CanWrite(item2)) { Inventory inventory = item2.GetInventory(); if (inventory != null && inventory.HaveItem(item.m_shared.m_name, true)) { list.Add(item2); } } } PushWalk(list, 0, playerID, item, drop, 0, done); } internal static int PullOwned(Container container, string sharedName, int amount, bool honorLeaveOne, int quality, bool worldLevel) { if (!CanWrite(container) || amount <= 0) { return 0; } Inventory inventory = container.GetInventory(); if (inventory == null) { return 0; } int num = Mathf.Min(Pullable(inventory.CountItems(sharedName, quality, worldLevel), honorLeaveOne), amount); if (num <= 0) { return 0; } inventory.RemoveItem(sharedName, num, quality, worldLevel); return num; } internal static int PushOwned(Container container, ItemData item, ItemDrop? drop) { if (!CanWrite(container) || item?.m_shared == null || item.m_stack <= 0) { return 0; } Inventory inventory = container.GetInventory(); if (inventory == null || !inventory.HaveItem(item.m_shared.m_name, true)) { return 0; } int num = MergeInto(inventory, item, item.m_stack); if (item.m_stack - num > 0) { num += PlaceNewStacks(inventory, item, item.m_stack - num); } if (num <= 0) { return 0; } inventory.Changed(true, false); item.m_stack -= num; if ((Object)(object)drop != (Object)null) { FinishDrop(drop, item); } return num; } private static void RequestConsumeFrom(List<Container> chests, long playerId, string sharedName, int amount, bool honorLeaveOne, int quality, bool worldLevel, int moved, Action<int> done) { if (amount <= 0 || chests.Count == 0) { done(moved); return; } Container container = chests[0]; chests.RemoveAt(0); StorageSync.RequestPull(container, playerId, sharedName, amount, honorLeaveOne, quality, worldLevel, delegate(int taken) { RequestConsumeFrom(chests, playerId, sharedName, amount - taken, honorLeaveOne, quality, worldLevel, moved + taken, done); }); } private static void PushWalk(List<Container> chests, int index, long playerId, ItemData item, ItemDrop? drop, int moved, Action<int> done) { if (item.m_stack <= 0 || index >= chests.Count) { done(moved); return; } Container container = chests[index]; bool local = CanWrite(container); StorageSync.RequestPush(container, playerId, item, drop, delegate(int taken) { if (taken > 0 && !local) { item.m_stack = Mathf.Max(0, item.m_stack - taken); } PushWalk(chests, index + 1, playerId, item, drop, moved + taken, done); }); } private static void FinishDrop(ItemDrop drop, ItemData item) { if (!((Object)(object)drop?.m_nview == (Object)null) && drop.m_nview.IsValid() && drop.m_nview.IsOwner()) { if (item.m_stack <= 0) { drop.m_nview.Destroy(); } else { drop.SetStack(item.m_stack); } } } public static bool BeginDeposit(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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) if (id != ZDOID.None) { return Depositing.Add(id); } return false; } public static void EndDeposit(ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Depositing.Remove(id); } } public sealed class PetPantry : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")] private static void UpdateConsumeItem(MonsterAI __instance, Humanoid humanoid, ref bool __result) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) if (__result || !ModConfig.PetPantryEnabled.Value || !ModConfig.StorageEnabled.Value || __instance.m_consumeSearchTimer > 0.0001f || (Object)(object)((BaseAI)__instance).m_nview == (Object)null || !((BaseAI)__instance).m_nview.IsOwner()) { return; } Tameable tamable = ((BaseAI)__instance).m_tamable; if ((Object)(object)tamable == (Object)null || !tamable.IsTamed() || !tamable.IsHungry() || __instance.m_consumeItems == null || __instance.m_consumeItems.Count == 0 || (Object)(object)Player.m_localPlayer == (Object)null) { return; } long playerID = Player.m_localPlayer.GetPlayerID(); Vector3 position = ((Component)__instance).transform.position; float value = ModConfig.StorageRange.Value; foreach (ItemDrop consumeItem in __instance.m_consumeItems) { if (consumeItem?.m_itemData?.m_shared != null && NearbyStorage.TryConsumeAround(position, value, playerID, consumeItem.m_itemData.m_shared.m_name, 1) > 0) { __instance.m_onConsumedItem?.Invoke(consumeItem); EffectList consumeItemEffects = humanoid.m_consumeItemEffects; if (consumeItemEffects != null) { consumeItemEffects.Create(position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } ZSyncAnimation animator = ((BaseAI)__instance).m_animator; if (animator != null) { animator.SetTrigger("consume"); } __result = true; break; } } } } public override string Id => "storage.petpantry"; public override bool Enabled => true; } public sealed class CraftFromStorage : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "CountItems", new Type[] { typeof(string), typeof(int), typeof(bool) })] private static void CountItems(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { if (On && !NearbyStorage.SkipPatches && NearbyStorage.IsLocalPlayerInventory(__instance)) { __result += NearbyStorage.Count(name, quality, matchWorldLevel); } } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] private static void HaveItem(Inventory __instance, string name, ref bool __result) { if (!__result && On && !NearbyStorage.SkipPatches && NearbyStorage.IsLocalPlayerInventory(__instance)) { __result = NearbyStorage.Has(name); } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] private static void RemoveItem(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased) { if (On) { NearbyStorage.TakeShortfall(__instance, name, ref amount, itemQuality, worldLevelBased); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Recipe), typeof(bool), typeof(int), typeof(int) })] private static void HaveRequirementsRecipe(Player __instance, Recipe recipe, bool discover, int qualityLevel, int amount, ref bool __result) { if (!(__result || !On || discover) && recipe?.m_resources != null && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && StationReady(__instance, recipe, qualityLevel) && NearbyStorage.HasRequirements(__instance, recipe.m_resources, qualityLevel, amount)) { __result = true; } } private static bool StationReady(Player player, Recipe recipe, int qualityLevel) { if ((Object)(object)recipe.m_craftingStation == (Object)null) { return true; } CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); if ((Object)(object)currentCraftingStation == (Object)null || currentCraftingStation.m_name != recipe.m_craftingStation.m_name) { return false; } if (!currentCraftingStation.CheckUsable(player, false)) { return false; } return currentCraftingStation.GetLevel(true) >= recipe.GetRequiredStationLevel(qualityLevel); } } public override string Id => "storage.crafting"; public override bool Enabled => true; private static bool On { get { if (ModConfig.StorageEnabled.Value) { return ModConfig.CraftFromStorageEnabled.Value; } return false; } } protected override void OnLoaded() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown MethodBase methodBase = FindSetupRequirement(typeof(InventoryGui)) ?? FindSetupRequirement(typeof(Hud)); if (methodBase == null) { Plugin.Log.LogError((object)(Id + ": SetupRequirement not found — recipe counts stay need-only")); } else { base.Harmony.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(CraftFromStorage), "ShowHaveNeed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static MethodBase? FindSetupRequirement(Type type) { Type[] array = new Type[6] { typeof(Transform), typeof(Requirement), typeof(Player), typeof(bool), typeof(int), typeof(int) }; Type[] array2 = new Type[5] { typeof(Transform), typeof(Requirement), typeof(Player), typeof(bool), typeof(int) }; return AccessTools.DeclaredMethod(type, "SetupRequirement", array, (Type[])null) ?? AccessTools.Method(type, "SetupRequirement", array, (Type[])null) ?? AccessTools.DeclaredMethod(type, "SetupRequirement", array2, (Type[])null) ?? AccessTools.Method(type, "SetupRequirement", array2, (Type[])null); } private static void ShowHaveNeed(object[] __args) { if (__args == null || __args.Length < 3) { return; } object obj = __args[0]; Transform val = (Transform)((obj is Transform) ? obj : null); object obj2 = __args[1]; Requirement val2 = (Requirement)((obj2 is Requirement) ? obj2 : null); object obj3 = __args[2]; Player val3 = (Player)((obj3 is Player) ? obj3 : null); if ((Object)(object)val == (Object)null || val2?.m_resItem?.m_itemData?.m_shared == null || (Object)(object)val3 == (Object)null) { return; } Transform obj4 = val.Find("res_amount"); TMP_Text val4 = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null); if (!((Object)(object)val4 == (Object)null) && ((Component)val4).gameObject.activeSelf) { string text = RestlessUi.Bare(val4.text); if (!string.IsNullOrEmpty(text) && text.IndexOf('/') < 0 && int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0) { val4.text = ((Humanoid)val3).GetInventory().CountItems(val2.m_resItem.m_itemData.m_shared.m_name, -1, true) + "/" + result; } } } } public sealed class BuildFromStorage : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] private static void HaveRequirements(Player __instance, Piece piece, RequirementMode mode, ref bool __result) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if (!__result && On && piece?.m_resources != null && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (int)mode != 1 && NearbyStorage.HasRequirements(__instance, piece.m_resources, 1, 1)) { __result = true; } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] private static void RemoveItem(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased) { if (On) { NearbyStorage.TakeShortfall(__instance, name, ref amount, itemQuality, worldLevelBased); } } } public override string Id => "storage.building"; public override bool Enabled => true; private static bool On { get { if (ModConfig.StorageEnabled.Value) { return ModConfig.BuildFromStorageEnabled.Value; } return false; } } } public sealed class QuickStack : FeatureModule { public override string Id => "storage.quickstack"; public override bool Enabled { get { if (ModConfig.StorageEnabled.Value) { return ModConfig.QuickStackEnabled.Value; } return false; } } public override void Tick() { //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) if (!Enabled) { return; } KeyboardShortcut value = ModConfig.QuickStackHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Run(localPlayer); } } } public static void Run(Player player) { Inventory inventory = ((Humanoid)player).GetInventory(); ItemData[] items = inventory.GetAllItems().ToArray(); int moved = 0; Next(0); void Next(int index) { while (index < items.Length) { ItemData[] array = items; int num = index; index = num + 1; ItemData item = array[num]; if (item != null && !item.m_equipped && !ExtraSlots.SkipDeposit(item) && !SlotLock.Held(item)) { moved += NearbyStorage.TryDeposit(player, item); if (item.m_stack > 0) { NearbyStorage.RequestDeposit(player, item, null, delegate(int extra) { moved += extra; if (item.m_stack <= 0) { inventory.RemoveItem(item); } Next(index); }); return; } inventory.RemoveItem(item); } } if (moved > 0) { inventory.Changed(true, false); } ((Character)player).Message((MessageType)2, (moved > 0) ? $"Stacked {moved}" : "Nothing to stack", 0, (Sprite)null, false); } } } public sealed class Restock : FeatureModule { public override string Id => "storage.restock"; public override bool Enabled { get { if (ModConfig.StorageEnabled.Value) { return ModConfig.RestockEnabled.Value; } return false; } } public override void Tick() { //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) if (!Enabled) { return; } KeyboardShortcut value = ModConfig.RestockHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Run(localPlayer); } } } public static void Run(Player player) { Inventory inventory = ((Humanoid)player).GetInventory(); ItemData[] items = inventory.GetAllItems().ToArray(); int filled = 0; Next(0); void Next(int index) { while (index < items.Length) { ItemData[] array = items; int num = index; index = num + 1; ItemData item = array[num]; if (item != null && !SlotLock.Held(item)) { int maxStackSize = item.m_shared.m_maxStackSize; if (item.m_stack < maxStackSize) { NearbyStorage.RequestConsume(item.m_shared.m_name, maxStackSize - item.m_stack, delegate(int taken) { if (taken > 0) { ItemData obj = item; obj.m_stack += taken; filled += taken; } Next(index); }, honorLeaveOne: true, item.m_quality, worldLevel: true); return; } } } if (filled > 0) { inventory.Changed(true, false); } ((Character)player).Message((MessageType)2, (filled > 0) ? $"Restocked {filled}" : "Nothing to restock", 0, (Sprite)null, false); } } } public sealed class StorageSync : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Container), "Awake")] private static void AfterAwake(Container __instance) { ZNetView nview = __instance.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && !((Object)(object)((Component)__instance).GetComponent<Hook>() != (Object)null)) { ((Component)__instance).gameObject.AddComponent<Hook>(); nview.Register<ZPackage>("RestlessPull", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg) { OnPull(__instance, sender, pkg); }); nview.Register<ZPackage>("RestlessPush", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg) { OnPush(__instance, sender, pkg); }); nview.Register<int, int>("RestlessPulled", (Action<long, int, int>)delegate(long _, int id, int taken) { Finish(id, taken); }); nview.Register<int, int>("RestlessPushed", (Action<long, int, int>)delegate(long _, int id, int taken) { Finish(id, taken); }); } } } private sealed class Hook : MonoBehaviour { } private const string PullRpc = "RestlessPull"; private const string PushRpc = "RestlessPush"; private const string PulledRpc = "RestlessPulled"; private const string PushedRpc = "RestlessPushed"; private static int _nextId = 1; private static readonly Dictionary<int, Action<int>> Waiting = new Dictionary<int, Action<int>>(); public override string Id => "storage.sync"; public override bool Enabled => true; internal static int RequestPull(Container container, long playerId, string sharedName, int amount, bool honorLeaveOne, int quality, bool worldLevel, Action<int>? done) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if ((Object)(object)container == (Object)null || amount <= 0) { done?.Invoke(0); return 0; } if (NearbyStorage.CanWrite(container)) { int num = NearbyStorage.PullOwned(container, sharedName, amount, honorLeaveOne, quality, worldLevel); done?.Invoke(num); return num; } int num2 = PredictedPull(container, sharedName, amount, honorLeaveOne, quality, worldLevel); if (num2 <= 0) { done?.Invoke(0); return 0; } int num3 = ((done != null) ? NextId() : 0); if (done != null) { Waiting[num3] = done; ((MonoBehaviour)Plugin.Instance).StartCoroutine(Expire(num3)); } ZPackage val = new ZPackage(); val.Write(playerId); val.Write(num3); val.Write(sharedName); val.Write(num2); val.Write(quality); val.Write(worldLevel); val.Write(honorLeaveOne); container.m_nview.InvokeRPC("RestlessPull", new object[1] { val }); return num2; } internal static void RequestPush(Container container, long playerId, ItemData item, ItemDrop? drop, Action<int> done) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_009e: 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) if ((Object)(object)container == (Object)null || item?.m_shared == null || item.m_stack <= 0) { done(0); return; } if (NearbyStorage.CanWrite(container)) { done(NearbyStorage.PushOwned(container, item, drop)); return; } int num = NextId(); Waiting[num] = done; ((MonoBehaviour)Plugin.Instance).StartCoroutine(Expire(num)); ZPackage val = new ZPackage(); val.Write(playerId); val.Write(num); val.Write(((Object)(object)drop != (Object)null && (Object)(object)drop.m_nview != (Object)null && drop.m_nview.IsValid()) ? drop.m_nview.GetZDO().m_uid : ZDOID.None); val.Write(WriteItem(item)); container.m_nview.InvokeRPC("RestlessPush", new object[1] { val }); } private static int NextId() { int result = _nextId++; if (_nextId <= 0) { _nextId = 1; } return result; } private static int PredictedPull(Container container, string sharedName, int amount, bool honorLeaveOne, int quality, bool worldLevel) { Inventory inventory = container.GetInventory(); if (inventory == null) { return 0; } int have = inventory.CountItems(sharedName, quality, worldLevel); return Mathf.Min(amount, NearbyStorage.Pullable(have, honorLeaveOne)); } private static void Finish(int id, int taken) { if (id != 0 && Waiting.TryGetValue(id, out Action<int> value)) { Waiting.Remove(id); value(taken); } } private static IEnumerator Expire(int id) { yield return (object)new WaitForSeconds(3f); Finish(id, 0); } private static void OnPull(Container container, long sender, ZPackage pkg) { if (container.IsOwner()) { pkg.SetPos(0); long num = pkg.ReadLong(); int id = pkg.ReadInt(); string sharedName = pkg.ReadString(); int amount = pkg.ReadInt(); int quality = pkg.ReadInt(); bool worldLevel = pkg.ReadBool(); bool honorLeaveOne = pkg.ReadBool(); int taken = 0; if (ModConfig.StorageEnabled.Value && container.CheckAccess(num)) { taken = NearbyStorage.PullOwned(container, sharedName, amount, honorLeaveOne, quality, worldLevel); } Reply(container, sender, "RestlessPulled", id, taken); } } private static void OnPush(Container container, long sender, ZPackage pkg) { //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_004e: Unknown result type (might be due to invalid IL or missing references) if (container.IsOwner()) { pkg.SetPos(0); long num = pkg.ReadLong(); int id = pkg.ReadInt(); ZDOID id2 = pkg.ReadZDOID(); ItemData val = ReadItem(pkg.ReadPackage()); int taken = 0; if (ModConfig.StorageEnabled.Value && val != null && container.CheckAccess(num)) { taken = NearbyStorage.PushOwned(container, val, FindDrop(id2)); } Reply(container, sender, "RestlessPushed", id, taken); } } private static void Reply(Container container, long sender, string rpc, int id, int taken) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (id == 0) { return; } ZNetView nview = container.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid()) { ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.ForceSendZDO(sender, nview.GetZDO().m_uid); } nview.InvokeRPC(sender, rpc, new object[2] { id, taken }); } } private static ItemDrop? FindDrop(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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) if (id == ZDOID.None || (Object)(object)ZNetScene.instance == (Object)null) { return null; } GameObject val = ZNetScene.instance.FindInstance(id); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<ItemDrop>(); } private static ZPackage WriteItem(ItemData item) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0032: Expected O, but got Unknown Inventory val = new Inventory("RestlessSync", (Sprite)null, 1, 1); ItemData val2 = item.Clone(); val2.m_equipped = false; val.AddItem(val2, val2.m_stack, 0, 0, false); ZPackage val3 = new ZPackage(); val.Save(val3); return val3; } private static ItemData? ReadItem(ZPackage pkg) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (pkg == null) { return null; } pkg.SetPos(0); Inventory val = new Inventory("RestlessSync", (Sprite)null, 1, 1); val.Load(pkg); foreach (ItemData allItem in val.GetAllItems()) { if (allItem != null) { return allItem; } } return null; } } } namespace RestlessQoL.Production { public sealed class EternalFire : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Fireplace), "Awake")] private static void Awake(Fireplace __instance) { if (ModConfig.EternalFireEnabled.Value) { __instance.m_infiniteFuel = true; } } [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "DrainEquipedItemDurability")] private static bool KeepTorch(ItemData item) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if (!ModConfig.EternalFireEnabled.Value || item?.m_shared == null) { return true; } return (int)item.m_shared.m_itemType != 15; } } public override string Id => "production.eternalfire"; public override bool Enabled => true; } public sealed class StationPull : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPrefix] [HarmonyPatch(typeof(Smelter), "OnAddOre")] private static void BeginOre(ref ItemData item, ref IDisposable __state) { if (On) { __state = NearbyStorage.BeginDirectTake(); } NearbyStorage.EnsureDropPrefab(item); } [HarmonyFinalizer] [HarmonyPatch(typeof(Smelter), "OnAddOre")] private static void EndOre(IDisposable __state) { __state?.Dispose(); } [HarmonyPrefix] [HarmonyPatch(typeof(CookingStation), "OnUseItem")] private static void BeginCook(ref ItemData item, ref IDisposable __state) { if (On) { __state = NearbyStorage.BeginDirectTake(); } NearbyStorage.EnsureDropPrefab(item); } [HarmonyFinalizer] [HarmonyPatch(typeof(CookingStation), "OnUseItem")] private static void EndCook(IDisposable __state) { __state?.Dispose(); } [HarmonyPrefix] [HarmonyPatch(typeof(Fermenter), "AddItem")] private static void BeginFerment(ref ItemData item, ref IDisposable __state) { if (On) { __state = NearbyStorage.BeginDirectTake(); } NearbyStorage.EnsureDropPrefab(item); } [HarmonyFinalizer] [HarmonyPatch(typeof(Fermenter), "AddItem")] private static void EndFerment(IDisposable __state) { __state?.Dispose(); } [HarmonyPostfix] [HarmonyPatch(typeof(Smelter), "FindCookableItem")] private static void SmelterFind(Smelter __instance, Inventory inventory, ref ItemData __result) { TryFind(inventory, From(__instance.m_conversion, (ItemConversion c) => c.m_from), ref __result); NearbyStorage.EnsureDropPrefab(__result); } [HarmonyPostfix] [HarmonyPatch(typeof(CookingStation), "FindCookableItem")] private static void CookFind(CookingStation __instance, Inventory inventory, ref ItemData __result) { TryFind(inventory, From(__instance.m_conversion, (ItemConversion c) => c.m_from), ref __result); NearbyStorage.EnsureDropPrefab(__result); } [HarmonyPostfix] [HarmonyPatch(typeof(Fermenter), "FindCookableItem")] private static void FermentFind(Fermenter __instance, Inventory inventory, ref ItemData __result) { TryFind(inventory, From(__instance.m_conversion, (ItemConversion c) => c.m_from), ref __result); NearbyStorage.EnsureDropPrefab(__result); } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "RemoveOneItem")] private static void RemoveOneItem(Inventory __instance, ItemData item, ref bool __result) { if (!__result && On && NearbyStorage.DirectTake && NearbyStorage.IsLocalPlayerInventory(__instance) && item?.m_shared != null && NearbyStorage.TryConsume(item.m_shared.m_name, 1, honorLeaveOne: false) > 0) { __result = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData), typeof(int) })] private static void RemoveItemData(Inventory __instance, ItemData item, int amount, ref bool __result) { if (!__result && On && NearbyStorage.DirectTake && NearbyStorage.IsLocalPlayerInventory(__instance) && item?.m_shared != null && amount > 0 && NearbyStorage.TryConsume(item.m_shared.m_name, amount, honorLeaveOne: false) == amount) { __result = true; } } private static void TryFind(Inventory inventory, IEnumerable<ItemDrop> sources, ref ItemData result) { if (result != null || !On || !NearbyStorage.IsLocalPlayerInventory(inventory)) { return; } foreach (ItemDrop source in sources) { if (NearbyStorage.TryCloneIfPresent(source, out ItemData item)) { result = item; break; } } } private static IEnumerable<ItemDrop> From<T>(IEnumerable<T> conversions, Func<T, ItemDrop> from) { if (conversions != null) { return Enumerate(conversions, from); } return Array.Empty<ItemDrop>(); } private static IEnumerable<ItemDrop> Enumerate<T>(IEnumerable<T> conversions, Func<T, ItemDrop> from) { foreach (T conversion in conversions) { yield return from(conversion); } } } public override string Id => "production.pull"; public override bool Enabled => true; private static bool On { get { if (ModConfig.StorageEnabled.Value) { return ModConfig.StationPullEnabled.Value; } return false; } } } } namespace RestlessQoL.PlayerTweaks { public sealed class HonestItems : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "Changed")] private static void InventoryChanged(Inventory __instance) { if (!ModConfig.HonestItemsEnabled.Value || __instance == null) { return; } foreach (ItemData allItem in __instance.GetAllItems()) { Honest(allItem); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Load")] private static void PlayerLoad(Player __instance) { if (!ModConfig.HonestItemsEnabled.Value || ((__instance != null) ? ((Humanoid)__instance).GetInventory() : null) == null) { return; } foreach (ItemData allItem in ((Humanoid)__instance).GetInventory().GetAllItems()) { Honest(allItem); } } [HarmonyPostfix] [HarmonyPatch(typeof(ItemDrop), "Awake")] private static void DropAwake(ItemDrop __instance) { if (ModConfig.HonestItemsEnabled.Value) { Honest(__instance?.m_itemData); } } } public override string Id => "inventory.honest"; public override bool Enabled => true; private static void Honest(ItemData? item) { if (item != null && item.m_cheated) { item.m_cheated = false; } } } public sealed class DeathPins : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(TombStone), "OnTakeAllSuccess")] private static void OnTakeAllSuccess(TombStone __instance) { RemovePin(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(TombStone), "EasyFitInInventory")] private static void EasyFitInInventory(TombStone __instance, bool __result) { if (__result) { RemovePin(__instance); } } private static void RemovePin(TombStone tomb) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.DeathPinsEnabled.Value && !((Object)(object)Minimap.instance == (Object)null) && !((Object)(object)tomb == (Object)null)) { Minimap.instance.RemovePin(((Component)tomb).transform.position, 1f); } } } public override string Id => "player.deathpins"; public override bool Enabled => true; } public sealed class SwimWield : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "HideHandItems")] private static bool HideHandItems(Humanoid __instance) { if (!ModConfig.SwimWieldEnabled.Value) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { return !((Character)val).IsSwimming(); } return true; } } public override string Id => "player.swimwield"; public override bool Enabled => true; } public sealed class CrossbowState : FeatureModule { [HarmonyPatch] private static class Patches { [ThreadStatic] private static bool _unequipping; [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "UnequipItem")] private static void UnequipPrefix() { _unequipping = true; } [HarmonyFinalizer] [HarmonyPatch(typeof(Humanoid), "UnequipItem")] private static void UnequipFinalizer() { _unequipping = false; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "ResetLoadedWeapon")] private static bool ResetLoadedWeapon() { if (_unequipping) { return !ModConfig.CrossbowStateEnabled.Value; } return true; } } public override string Id => "player.crossbow"; public override bool Enabled => true; } public sealed class FriendlyFire : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Turret), "Awake")] private static void Awake(Turret __instance) { if (ModConfig.FriendlyFireEnabled.Value) { __instance.m_targetTamed = false; __instance.m_targetTamedConfig = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "RPC_Damage")] private static bool BeforeDamage(Character __instance, HitData hit) { if (!ModConfig.FriendlyFireEnabled.Value || hit == null) { return true; } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker == (Object)null || (Object)(object)attacker == (Object)(object)__instance) { return true; } return !Allied(attacker, __instance); } } public override string Id => "player.friendlyfire"; public override bool Enabled => true; private static bool Allied(Character a, Character b) { if (a.IsTamed() && b.IsTamed()) { return true; } if (a.IsTamed() && b.IsPlayer()) { return true; } if (a.IsPlayer()) { return b.IsTamed(); } return false; } } public sealed class AxeCombo : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Attack), "Start", new Type[] { typeof(Humanoid), typeof(Rigidbody), typeof(ZSyncAnimation), typeof(CharacterAnimEvent), typeof(VisEquipment), typeof(ItemData), typeof(Attack), typeof(float), typeof(float) })] private static void Start(Attack __instance, ItemData weapon) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.AxeComboEnabled.Value && weapon?.m_shared != null && (int)weapon.m_shared.m_skillType == 7 && (int)__instance.m_resetChainIfHit == 2) { __instance.m_resetChainIfHit = (DestructibleType)0; } } } public override string Id => "player.axecombo"; public override bool Enabled => true; } public sealed class AutoRepair : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "Show")] private static void AfterShow(InventoryGui __instance) { RepairAll(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(CraftingStation), "Interact")] private static void AfterUse(Humanoid user, bool __result) { if (__result && !((Object)(object)user != (Object)(object)Player.m_localPlayer)) { RepairAll(InventoryGui.instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "UpdateRepair")] private static bool SkipButton(InventoryGui __instance) { if (!ModConfig.AutoRepairEnabled.Value) { return true; } HideChrome(__instance); return false; } } public override string Id => "player.auto_repair"; public override bool Enabled => true; public static bool HidesButton => ModConfig.AutoRepairEnabled.Value; public static void HideChrome(InventoryGui gui) { if ((Object)(object)gui.m_repairPanel != (Object)null) { ((Component)gui.m_repairPanel).gameObject.SetActive(false); } if ((Object)(object)gui.m_repairPanelSelection != (Object)null) { ((Component)gui.m_repairPanelSelection).gameObject.SetActive(false); } if ((Object)(object)gui.m_repairButton != (Object)null) { ((Component)gui.m_repairButton).gameObject.SetActive(false); } if ((Object)(object)gui.m_repairButtonGlow != (Object)null) { ((Behaviour)gui.m_repairButtonGlow).enabled = false; } } private static void RepairAll(InventoryGui? gui) { if (!ModConfig.AutoRepairEnabled.Value || (Object)(object)gui == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); if (!((Object)(object)currentCraftingStation == (Object)null) && currentCraftingStation.m_canRepair && currentCraftingStation.CheckUsable(localPlayer, false)) { int num = 0; while (gui.HaveRepairableItems() && num++ < 64) { gui.RepairOneItem(); } } } } public sealed class StackSizes : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(ObjectDB), "Awake")] private static void AfterAwake() { Apply(); } [HarmonyPostfix] [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static void AfterCopy() { Apply(); } } private static readonly Dictionary<string, int> Vanilla = new Dictionary<string, int>(); public override string Id => "inventory.stack_size"; public override bool Enabled => true; protected override void OnLoaded() { ModConfig.StackSizeMultiplier.SettingChanged += delegate { Apply(); }; Apply(); } private static void Apply() { ObjectDB instance = ObjectDB.instance; if (instance?.m_items == null) { return; } float num = Mathf.Max(1f, ModConfig.StackSizeMultiplier.Value); foreach (GameObject item in instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } SharedData val = item.GetComponent<ItemDrop>()?.m_itemData?.m_shared; if (val != null) { if (!Vanilla.ContainsKey(((Object)item).name)) { Vanilla[((Object)item).name] = val.m_maxStackSize; } int num2 = Vanilla[((Object)item).name]; if (num2 > 1) { val.m_maxStackSize = Mathf.Max(num2, Mathf.RoundToInt((float)num2 * num)); } } } } } } namespace RestlessQoL.HudTweaks { public sealed class ActionHints : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(KeyHints), "UpdateHints")] private static void AfterHints(KeyHints __instance) { if (!ModConfig.ActionHintsEnabled.Value) { _stack?.Hide(); if (!AnyVanilla(__instance)) { RestoreVanilla(__instance); } return; } bool flag = Live(__instance.m_combatHints); bool flag2 = Live(__instance.m_fishingHints); bool flag3 = Live(__instance.m_buildHints); bool flag4 = Live(__instance.m_inventoryHints) || Live(__instance.m_inventoryWithContainerHints) || RestlessUi.InventoryOpen(); bool num = Live(__instance.m_barberHints) || Live(__instance.m_radialHints); HideVanilla(__instance); if (num || Hud.IsUserHidden() || RestlessUi.MapOpen()) { _stack?.Hide(); return; } Player localPlayer = Player.m_localPlayer; if (flag4) { Show(InventoryRows()); } else if ((Object)(object)localPlayer == (Object)null) { _stack?.Hide(); } else if (flag3) { Show(BuildRows()); } else if (flag2) { Show(("Hook", new string[2] { "Attack", "JoyAttack" })); } else if (flag) { Show(CombatRows(localPlayer)); } else { _stack?.Hide(); } } } private static RestlessUi.KeyStack? _stack; private static float _mapRightX; public override string Id => "ui.hints"; public override bool Enabled => true; protected override void OnLoaded() { GUIManager.OnCustomGUIAvailable += TearDown; } public override void Tick() { if (!ModConfig.ActionHintsEnabled.Value) { _stack?.Hide(); } } private static bool Live(GameObject? go) { if ((Object)(object)go != (Object)null) { return go.activeSelf; } return false; } private static bool AnyVanilla(KeyHints hints) { if (!Live(hints.m_combatHints) && !Live(hints.m_fishingHints) && !Live(hints.m_buildHints) && !Live(hints.m_inventoryHints)) { return Live(hints.m_inventoryWithContainerHints); } return true; } private static void RestoreVanilla(KeyHints hints) { Show(hints.m_combatHints); Show(hints.m_fishingHints); Show(hints.m_buildHints); Show(hints.m_inventoryHints); Show(hints.m_inventoryWithContainerHints); Show(hints.m_primaryAttackGP); Show(hints.m_primaryAttackKB); Show(hints.m_secondaryAttackGP); Show(hints.m_secondaryAttackKB); Show(hints.m_bowDrawGP); Show(hints.m_bowDrawKB); } private static void HideVanilla(KeyHints hints) { Quiet(hints.m_combatHints); Quiet(hints.m_fishingHints); Quiet(hints.m_buildHints); Quiet(hints.m_inventoryHints); Quiet(hints.m_inventoryWithContainerHints); Quiet(hints.m_primaryAttackGP); Quiet(hints.m_primaryAttackKB); Quiet(hints.m_secondaryAttackGP); Quiet(hints.m_secondaryAttackKB); Quiet(hints.m_bowDrawGP); Quiet(hints.m_bowDrawKB); } private static void Quiet(GameObject? go) { if ((Object)(object)go != (Object)null) { go.SetActive(false); } } private static void Show(GameObject? go) { if ((Object)(object)go != (Object)null) { go.SetActive(true); } } private static (string verb, string[] buttons)[] InventoryRows() { return new(string, string[])[3] { ("Use", new string[2] { "Use", "JoyUse" }), ("Split", new string[2] { "JoyLTrigger", "AltPlace" }), ("Inventory", new string[2] { "Inventory", "JoyInventory" }) }; } private static (string verb, string[] buttons)[] BuildRows() { return new(string, string[])[6] { ("Place", new string[3] { "Attack", "JoyPlace", "JoyAttack" }), ("Remove", new string[4] { "Remove", "JoyRemove", "SecondaryAttack", "SecondAttack" }), ("Snap", new string[2] { "AltPlace", "JoyAltPlace" }), ("Cycle", new string[2] { "NextSnap", "PrevSnap" }), ("Rotate", new string[1] { "JoyRotate" }), ("Menu", new string[1] { "BuildMenu" }) }; } private static (string verb, string[] buttons)[] CombatRows(Player player) { List<(string, string[])> list = new List<(string, string[])>(); list.Add((PrimaryVerb(player), new string[3] { "Attack", "JoyAttack", "JoyPlace" })); List<(string, string[])> list2 = list; if (CanBlock(player)) { list2.Add(("Block", new string[2] { "Block", "JoyBlock" })); } list2.Add(("Dodge", new string[2] { "Dodge", "JoyDodge" })); return list2.ToArray(); } private static void Show(params (string verb, string[] buttons)[] rows) { Transform val = (((Object)(object)Hud.instance?.m_rootObject != (Object)null) ? Hud.instance.m_rootObject.transform : null); if ((Object)(object)val == (Object)null) { return; } if (_stack == null) { _stack = RestlessUi.KeyStack.BottomRight(val); } List<(string, string[])> list = new List<(string, string[])>(); for (int i = 0; i < rows.Length; i++) { (string, string[]) item = rows[i]; if (item.Item1 == "Rotate" || RestlessUi.Bound(item.Item2)) { list.Add(item); } } if (list.Count == 0) { _stack.Hide(); return; } _stack.Set(list); Park(); } private static void Park() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0147: Unknown result type (might be due to invalid IL or missing references) if (_stack == null) { return; } RectTransform component = _stack.Root.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(196f, component.sizeDelta.y); Transform parent = ((Transform)component).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (val != null) { RectTransform val2 = (((Object)(object)Minimap.instance?.m_mapImageSmall != (Object)null) ? ((Graphic)Minimap.instance.m_mapImageSmall).rectTransform : null); if ((Object)(object)val2 != (Object)null && RestlessUi.HudTuck.Amount < 0.02f) { Vector3[] array = (Vector3[])(object)new Vector3[4]; val2.GetWorldCorners(array); _mapRightX = array[3].x; } float num = _mapRightX; if (num == 0f) { Vector3[] array2 = (Vector3[])(object)new Vector3[4]; val.GetWorldCorners(array2); num = array2[2].x; } float num2 = ((Transform)val).TransformPoint(new Vector3(0f, 8f, 0f)).y; if (Hotbar.TrySpan(out var left, out var right, out var midY, out var height) || Hotbar.Measure(Object.FindFirstObjectByType<HotkeyBar>(), out right, out left, out midY, out height)) { num2 = midY - height * 0.5f; } component.pivot = new Vector2(1f, 0f); ((Transform)component).position = new Vector3(num, num2, ((Transform)component).position.z); } } private static string PrimaryVerb(Player player) { //IL_002b: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 ItemData val = ((Humanoid)player).GetRightItem() ?? ((Humanoid)player).GetCurrentWeapon(); if (val?.m_shared == null) { return "Attack"; } ItemType itemType = val.m_shared.m_itemType; if ((int)itemType == 4) { return "Draw"; } if (((int)itemType == 15 || (int)itemType == 19) ? true : false) { return "Use"; } if ((int)val.m_shared.m_skillType == 104) { return "Hook"; } return "Attack"; } private static bool CanBlock(Player player) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 if (((Humanoid)player).GetLeftItem() != null) { return true; } ItemData val = ((Humanoid)player).GetRightItem() ?? ((Humanoid)player).GetCurrentWeapon(); if (val?.m_shared == null) { return true; } ItemType itemType = val.m_shared.m_itemType; if (((int)itemType == 4 || (int)itemType == 15 || (int)itemType == 19) ? true : false) { return false; } return (int)val.m_shared.m_skillType != 104; } private static void TearDown() { if (_stack != null) { Object.Destroy((Object)(object)_stack.Root); } _stack = null; } } public sealed class BuffList : FeatureModule { private sealed class Row { private RestlessUi.HudRow _row; public GameObject Root => _row.Root; public static Row Create(Transform parent) { return new Row { _row = RestlessUi.HudRow.Buff(parent) }; } public void Place(float y) { //IL_0011: 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) _row.Rect.anchoredPosition = new Vector2(0f, y); _row.Rect.sizeDelta = new Vector2(196f, 36f); } public void Bind(Sprite? icon, string name, string? extra, float fill = 0f, Color? title = null) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) _row.SetIcon(icon); ((Graphic)_row.Icon).color = Color.white; _row.SetCopy(name, extra); _row.SetFill(fill); ((Graphic)_row.Title).color = (Color)(((??)title) ?? RestlessUi.Text); } } [HarmonyPatch] private static class Patches { [HarmonyPrefix] [HarmonyPatch(typeof(Hud), "UpdateStatusEffects")] private static bool UpdateStatusEffects(Hud __instance) { if (!ModConfig.BuffListEnabled.Value) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } RestoreVanilla(); return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)__instance.m_rootObject == (Object)null || !__instance.m_rootObject.activeInHierarchy) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } return false; } if (RestlessUi.MapOpen()) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } HideVanilla(__instance); return false; } RestlessUi.HudTuck.Tick(); HideVanilla(__instance); EnsureRoot(__instance); PlaceUnderMap(__instance); Sync(localPlayer); RestlessUi.HudTuck.Fade(_root); _root.SetActive(RestlessUi.HudTuck.Amount < 0.98f); return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateGuardianPower")] private static void AfterGp(Hud __instance) { if (ModConfig.BuffListEnabled.Value && (Object)(object)__instance.m_gpRoot != (Object)null) { ((Component)__instance.m_gpRoot).gameObject.SetActive(false); } } } private static readonly List<StatusEffect> Effects = new List<StatusEffect>(); private static readonly Dictionary<string, Row> Rows = new Dictionary<string, Row>(); private static readonly Dictionary<string, float> FoodSpan = new Dictionary<string, float>(); private static GameObject? _root; private static bool _vanillaHidden; public override string Id => "ui.buffs"; public override bool Enabled => true; protected override void OnLoaded() { GUIManager.OnCustomGUIAvailable += TearDown; } public override void Tick() { if (!ModConfig.BuffListEnabled.Value) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } RestoreVanilla(); } } private static void HideVanilla(Hud hud) { if (!((Object)(object)hud.m_statusEffectListRoot == (Object)null)) { ((Component)hud.m_statusEffectListRoot).gameObject.SetActive(false); if ((Object)(object)hud.m_gpRoot != (Object)null) { ((Component)hud.m_gpRoot).gameObject.SetActive(false); } _vanillaHidden = true; } } private static void RestoreVanilla() { if (_vanillaHidden && !((Object)(object)Hud.instance?.m_statusEffectListRoot == (Object)null)) { ((Component)Hud.instance.m_statusEffectListRoot).gameObject.SetActive(true); if ((Object)(object)Hud.instance.m_gpRoot != (Object)null) { ((Component)Hud.instance.m_gpRoot).gameObject.SetActive(true); } _vanillaHidden = false; } } private static RectTransform? MapImage() { if (!((Object)(object)Minimap.instance?.m_mapImageSmall != (Object)null)) { return null; } return ((Graphic)Minimap.instance.m_mapImageSmall).rectTransform; } private static Transform HudRoot(Hud hud) { if (!((Object)(object)hud.m_rootObject != (Object)null)) { return ((Component)hud).transform; } return hud.m_rootObject.transform; } private static void TearDown() { foreach (KeyValuePair<string, Row> row in Rows) { Object.Destroy((Object)(object)row.Value.Root); } Rows.Clear(); FoodSpan.Clear(); if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; } private static bool IsCurrentLayout() { if ((Object)(object)_root != (Object)null) { if (_root.transform.childCount != 0) { return (Object)(object)_root.transform.GetChild(0).Find("strip") != (Object)null; } return true; } return false; } private static void EnsureRoot(Hud hud) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null && !IsCurrentLayout()) { TearDown(); } if (!((Object)(object)_root != (Object)null)) { _root = RestlessUi.Node(HudRoot(hud), "RestlessBuffs"); RectTransform component = _root.GetComponent<RectTransform>(); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(1f, 1f); component.anchorMax = val; component.anchorMin = val; component.pivot = new Vector2(1f, 1f); component.sizeDelta = new Vector2(196f, 0f); } } private static void PlaceUnderMap(Hud hud) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root == (Object)null) { return; } RectTransform val = MapImage(); if (!((Object)(object)val == (Object)null)) { Transform val2 = HudRoot(hud); if ((Object)(object)_root.transform.parent != (Object)(object)val2) { _root.transform.SetParent(val2, false); } RectTransform component = _root.GetComponent<RectTransform>(); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); component.anchorMax = val3; component.anchorMin = val3; RestlessUi.HangUnder(component, val, new Vector2(0f, -8f)); } } private static void Sync(Player player) { //IL_023c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root == (Object)null) { return; } HashSet<string> hashSet = new HashSet<string>(); List<string> list = new List<string>(); BindGuardian(player, hashSet, list); if (ModConfig.BuffListFood.Value) { BindFood(player, hashSet, list); } Effects.Clear(); ((Character)player).GetSEMan().GetHUDStatusEffects(Effects); StatusEffect val = default(StatusEffect); float num = default(float); player.GetGuardianPowerHUD(ref val, ref num); int num2 = (((Object)(object)val != (Object)null) ? val.NameHash() : 0); foreach (StatusEffect effect in Effects) { if (!((Object)(object)effect == (Object)null) && (num2 == 0 || effect.NameHash() != num2)) { string text = "se:" + effect.NameHash(); hashSet.Add(text); list.Add(text); string name = ((Localization.instance != null) ? Localization.instance.Localize(effect.m_name) : effect.m_name); GetOrCreate(text).Bind(effect.m_icon, name, Extra(effect), FillOf(effect)); } } List<string> list2 = new List<string>(); foreach (KeyValuePair<string, Row> row in Rows) { if (!hashSet.Contains(row.Key)) { list2.Add(row.Key); } } foreach (string item in list2) { Object.Destroy((Object)(object)Rows[item].Root); Rows.Remove(item); FoodSpan.Remove(item); } float num3 = 0f; for (int i = 0; i < list.Count; i++) { Rows[list[i]].Place(num3); num3 -= 40f; } _root.GetComponent<RectTransform>().sizeDelta = new Vector2(196f, 0f - num3); } private static void BindFood(Player player, HashSet<string> wanted, List<string> order) { //IL_00a4: 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) List<Food> foods = player.GetFoods(); int num = FoodSlots(); if (!ModConfig.BuffListFoodEmpty.Value) { num = foods?.Count ?? 0; } for (int i = 0; i < num; i++) { string text = "food:" + i; wanted.Add(text); order.Add(text); Food val = ((foods != null && i < foods.Count) ? foods[i] : null); if (val?.m_item?.m_shared == null) { FoodSpan.Remove(text); GetOrCreate(text).Bind(RestlessUi.BowlIcon(), "Eat", null, 0f, RestlessUi.Muted); continue; } if (!FoodSpan.TryGetValue(text, out var value) || val.m_time > value) { value = (FoodSpan[text] = val.m_time); } float fill = ((value > 1f) ? (val.m_time / value) : 0f); string name = ((Localization.instance != null) ? Localization.instance.Localize(val.m_item.m_shared.m_name) : val.m_item.m_shared.m_name); GetOrCreate(text).Bind(RestlessUi.IconOf(val.m_item), name, Clock(val.m_time), fill, RestlessUi.Text); } } private static int FoodSlots() { Image[] array = Hud.instance?.m_foodIcons; if (array == null || array.Length == 0) { return 3; } return array.Length; } private static void BindGuardian(Player player, HashSet<string> wanted, List<string> order) { StatusEffect val = default(StatusEffect); float num = default(float); player.GetGuardianPowerHUD(ref val, ref num); if (!((Object)(object)val == (Object)null)) { wanted.Add("gp"); order.Add("gp"); StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(val.NameHash()); string name = ((Localization.instance != null) ? Localization.instance.Localize(val.m_name) : val.m_name); float fill = 0f; string extra; if (!((Object)(object)statusEffect != (Object)null) || !(statusEffect.m_ttl > 0.5f)) { extra = ((!(num > 0.5f)) ? "Ready" : Clock(num)); } else { float remaningTime = statusEffect.GetRemaningTime(); fill = Mathf.Clamp01(remaningTime / statusEffect.m_ttl); extra = Clock(remaningTime); } GetOrCreate("gp").Bind(val.m_icon, name, extra, fill); } } private static Row GetOrCreate(string key) { if (Rows.TryGetValue(key, out Row value)) { return value; } value = Row.Create(_root.transform); Rows[key] = value; return value; } private static float FillOf(StatusEffect effect) { if (effect.m_ttl > 0.5f) { return Mathf.Clamp01(effect.GetRemaningTime() / effect.m_ttl); } return 0f; } private static string Extra(StatusEffect effect) { string iconText = effect.GetIconText(); if (!string.IsNullOrWhiteSpace(iconText)) { return iconText.Trim(); } SE_Stats val = (SE_Stats)(object)((effect is SE_Stats) ? effect : null); if (val != null && Mathf.Abs(val.m_addMaxCarryWeight) >= 1f) { return "+" + Mathf.RoundToInt(val.m_addMaxCarryWeight); } return ""; } private static string Clock(float seconds) { if (seconds <= 0f) { return ""; } if (seconds >= 90f) { return Mathf.CeilToInt(seconds / 60f) + "m"; } return Mathf.CeilToInt(seconds) + "s"; } } public sealed class BuildMenu : FeatureModule { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateBuild")] private static void AfterBuild(Hud __instance) { if (!ModConfig.BuildMenuEnabled.Value) { if (_dressed) { Undress(); } return; } if (!Open(__instance)) { ClearHover(); _syncStamp = int.MinValue; return; } DumpOnce(__instance); if (!_dressed) { _dressed = true; } if (NeedsSync(__instance)) { Sync(__instance); } else { RefreshHoverLive(__instance); } KeepQuiet(); } } private static readonly List<GameObject> Ours = new List<GameObject>(); private static readonly List<Behaviour> Hidden = new List<Behaviour>(); private static readonly HashSet<GameObject> Silenced = new HashSet<GameObject>(); private static readonly HashSet<Object> Remembered = new HashSet<Object>(); private static readonly List<Action> Restore = new List<Action>(); private static readonly List<RestlessControlFeedback> Feedback = new List<RestlessControlFeedback>(); private static bool _dressed; private static bool _dumped; private static int _syncStamp = int.MinValue; private static GameObject? _hoverPaper; private static Text? _detailTitle; private static Text? _detailBody; private static Image? _detailIcon; private static RectTransform? _bodyContent; private static RectTransform? _costContent; private static ScrollRect? _bodyScroll; private static ScrollRect? _costScroll; private static readonly List<GameObject> CostRows = new List<GameObject>(); private static readonly Dictionary<Graphic, float> DetailAlpha = new Dictionary<Graphic, float>(); private static readonly Dictionary<RectTransform, (Vector3 scale, Vector3 position)> MenuGeometry = new Dictionary<RectTransform, (Vector3, Vector3)>(); private static readonly Dictionary<RectTransform, (Vector2 min, Vector2 max, Vector2 pivot, Vector2 size, Vector3 position)> BarGeometry = new Dictionary<RectTransform, (Vector2, Vector2, Vector2, Vector2, Vector3)>(); private static string _detailKey = ""; private static string _costScanKey = ""; private static readonly List<Transform> CostSlots = new List<Transform>(); private static readonly List<Graphic> NativeDetails = new List<Graphic>(); private static Vector2 _fitSize; private static float _fitFooter; private static float _fitBottom; private static float _fitWidth; public override string Id => "ui.build"; public override bool Enabled => true; protected override void OnLoaded() { GUIManager.OnCustomGUIAvailable += TearDown; } public override void Tick() { if (!ModConfig.BuildMenuEnabled.Value && _dressed) { Undress(); } } private static bool Open(Hud hud) { if (!Hud.IsPieceSelectionVisible() && !Live(hud.m_buildUi)) { return Live(hud.m_pieceSelectionWindow); } return true; } private static bool Live(object? node) { GameObject val = (GameObject)((node is GameObject) ? node : null); if (val == null || !val.activeInHierarchy) { Component val2 = (Component)((node is Component) ? node : null); if (val2 != null) { return val2.gameObject.activeInHierarchy; } return false; } return true; } private static Transform? RootOf(object? node) { object obj = ((node is Transform) ? node : null); if (obj == null) { object? obj2 = ((node is Component) ? node : null); obj = ((obj2 != null) ? ((Component)obj2).transform : null); if (obj == null) { object? obj3 = ((node is GameObject) ? node : null); if (obj3 == null) { return null; } obj = ((GameObject)obj3).transform; } } return (Transform?)obj; } private static void DumpOnce(Hud hud) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if (_dumped) { return; } Transform val = RootOf(hud.m_buildUi) ?? RootOf(hud.m_pieceSelectionWindow); if (!((Object)(object)val == (Object)null)) { _dumped = true; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("ui.build dump"); Graphic[] componentsInChildren = ((Component)val).GetComponentsInChildren<Graphic>(true); foreach (Graphic val2 in componentsInChildren) { RectTransform rectTransform = val2.rectTransform; StringBuilder stringBuilder2 = stringBuilder.Append(" ").Append(((object)val2).GetType().Name).Append(' ') .Append(Trail(((Component)val2).transform, val)) .Append(' '); Rect rect = rectTransform.rect; StringBuilder stringBuilder3 = stringBuilder2.Append(((Rect)(ref rect)).width.ToString("0")).Append('x'); rect = rectTransform.rect; stringBuilder3.Append(((Rect)(ref rect)).height.ToString("0")).AppendLine(); } Plugin.Log.LogInfo((object)stringBuilder.ToString()); } } private static string Trail(Transform node, Transform root) { List<string> list = new List<string>(); Transform val = node; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } list.Reverse(); return string.Join("/", list); } private static bool NeedsSync(Hud hud) { int num = Stamp(hud); if (num == _syncStamp) { return false; } _syncStamp = num; return true; } private static int Stamp(Hud hud) { int num = 17; num = num * 31 + Screen.width; num = num * 31 + Screen.height; num = MixCopy(num, ((Object)(object)hud.m_buildSelection != (Object)null) ? hud.m_buildSelection.text : null); num = MixCopy(num, ((Object)(object)hud.m_pieceDescription != (Object)null) ? hud.m_pieceDescription.text : null); BuildUi buildUi = hud.m_buildUi; if ((Object)(object)buildUi == (Object)null) { return num; } num = num * 31 + (((Object)(object)buildUi.m_lastSelectedPieceBtn != (Object)null) ? ((Object)buildUi.m_lastSelectedPieceBtn).GetInstanceID() : 0); num = num * 31 + (((Object)(object)buildUi.m_currentHoveredPieceButton != (Object)null) ? ((Object)buildUi.m_currentHoveredPieceButton).GetInstanceID() : 0); num = num * 31 + buildUi.m_currentTagId; Component searchField = (Component)(object)buildUi.m_searchField; if (searchField != null) { TMP_InputField component = searchField.GetComponent<TMP_InputField>(); if ((Object)(object)component != (Object)null) { num = MixCopy(num, component.text); } else { InputField component2 = searchField.GetComponent<InputField>(); if ((Object)(object)component2 != (Object)null) { num = MixCopy(num, component2.text); } } } int num2 = 0; if (buildUi.m_pieceButtons != null) { foreach (BuildUiPieceButton pieceButton in buildUi.m_pieceButtons) { if ((Object)(object)pieceButton != (Object)null && ((Component)pieceButton).gameObject.activeInHierarchy) { num2++; } } } num = num * 31 + num2; if ((Object)(object)buildUi.m_tabContainer != (Object)null) { for (int i = 0; i < ((Transform)buildUi.m_tabContainer).childCount; i++) { Transform child = ((Transform)buildUi.m_tabContainer).GetChild(i); if (!((Object)(object)child == (Object)null)) { Transform val = child.Find("Selected"); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy) { num = num * 31 + ((Object)child).GetInstanceID(); } } } } return num; } private static int MixCopy(int h, string? text) { return h * 31 + ((!string.IsNullOrEmpty(text)) ? text.GetHashCode() : 0); } private static void Sync(Hud hud) { Transform? root = RootOf(hud.m_buildUi); Quiet(root); Quiet(RootOf(hud.m_pieceSelectionWindow)); DressScroll(root); BuildUi buildUi = hud.m_buildUi; if (!((Object)(object)buildUi == (Object)null)) { DressPieces(buildUi); DressTags(buildUi); DressTabs(buildUi); DressSearch(buildUi); DressKeys(buildUi); DressHover(hud); } } private static void KeepQuiet() { foreach (Behaviour item in Hidden) { if ((Object)(object)item != (Object)null) { item.enabled = false; } } foreach (GameObject item2 in Silenced) { if (!((Object)(object)item2 == (Object)null)) { RestlessUi.SilenceTmp(item2.GetComponent<TMP_Text>()); } } } private static void Quiet(Transform? root) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { if (Owned(((Component)val).transform) || LeaveMask(((Component)val).transform) || (Object)(object)((Component)val).GetComponentInParent<Scrollbar>() != (Object)null) { continue; } string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); Rect rect = ((Graphic)val).rectTransform.rect; if (((Rect)(ref rect)).width >= 800f && ((Rect)(ref rect)).height >= 800f) { Hide(val); continue; } bool flag = ((text == "background" || text == "tabborder") ? true : false); bool flag2 = flag || text.Contains("wood"); if (!flag2) { bool flag3 = ((text == "darken" || text == "blur") ? true : false); flag2 = flag3; } bool flag4 = flag2; if (!flag4) { bool flag3 = ((text == "panel-back" || text == "bkg") ? true : false); flag4 = flag3; } if (flag4 || text.Contains("bkg")) { Hide(val); } } } private static void DressScroll(Transform? root) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; }