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 EvuMagnets v0.4.0
EvuMagnets.Core.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("evu")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 imevul")] [assembly: AssemblyDescription("Craftable magnets that pull nearby items from farther away.")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: AssemblyInformationalVersion("0.4.0+f10db697f00271bee4eca874a2c89cdc8728c21d")] [assembly: AssemblyProduct("EvuMagnets")] [assembly: AssemblyTitle("EvuMagnets.Core")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/EvuMods/EvuMagnets")] [assembly: AssemblyVersion("0.4.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.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 EvuMagnets.Core { public readonly struct Ingredient { public string Item { get; } public int Amount { get; } public Ingredient(string item, int amount) { Item = item; Amount = amount; } } public sealed class MagnetTierInfo { public string Id { get; } public string PrefabName => "evu_magnet_" + Id; public string Token => "item_" + PrefabName; public string EnglishName { get; } public string EnglishDescription { get; } public string Station { get; } public int StationLevel { get; } public float[] Ranges { get; } public string Craft { get; } public string Upgrades { get; } public bool Forged { get; } public MagnetTierInfo(string id, string englishName, string englishDescription, string station, int stationLevel, float[] ranges, string craft, string upgrades, bool forged = true) { Id = id; EnglishName = englishName; EnglishDescription = englishDescription; Station = station; StationLevel = stationLevel; Ranges = ranges; Craft = craft; Upgrades = upgrades; Forged = forged; } } public static class MagnetCast { public const string Id = "cast"; public const string PrefabName = "evu_cast_bloodgold"; public const string Token = "item_evu_cast_bloodgold"; public const string EnglishName = "Magnet Cast"; public const string EnglishDescription = "A black-forged mold. Set it in the frost foundry with liquid frost, and a bloodgold magnet comes out."; public const string Station = "blackforge"; public const int StationLevel = 1; public const string Craft = "Iron:10,Thunderstone:1,Gold:10,FrostCore:5"; public const string Foundry = "piece_FrostFoundry"; public const string OutputPrefab = "evu_magnet_bloodgold"; public const float CookTime = 50f; } public static class MagnetCatalog { public const string PreviousFlametalCraft = "Iron:10,Flametal:10,Thunderstone:1,Eitr:5"; public const string PreviousFlametalUpgrades = "Flametal:10,Thunderstone:1;Flametal:20,Thunderstone:2;Flametal:40,Thunderstone:4"; public static IReadOnlyList<MagnetTierInfo> All { get; } = new MagnetTierInfo[5] { new MagnetTierInfo("iron", "Iron Magnet", "A rough iron lodestone. It draws loose items in from a short way off.", "forge", 1, new float[4] { 4f, 5f, 6f, 8f }, "Iron:20,Thunderstone:1,Ectoplasm:5", "Iron:10,Thunderstone:1;Iron:20,Thunderstone:2;Iron:40,Thunderstone:4"), new MagnetTierInfo("silver", "Silver Magnet", "Cold silver around a thunder stone. The pull reaches farther than iron.", "forge", 2, new float[4] { 8f, 10f, 12f, 14f }, "Iron:10,Silver:10,Thunderstone:1,Obsidian:5", "Silver:10,Thunderstone:1;Silver:20,Thunderstone:2;Silver:40,Thunderstone:4"), new MagnetTierInfo("blackmetal", "Black Metal Magnet", "Dark green plains metal. It gathers drops from across a camp.", "forge", 3, new float[4] { 14f, 16f, 18f, 20f }, "Iron:10,BlackMetal:10,Thunderstone:1,Crystal:10", "BlackMetal:10,Thunderstone:1;BlackMetal:20,Thunderstone:2;BlackMetal:40,Thunderstone:4"), new MagnetTierInfo("flametal", "Flametal Magnet", "Hot orange flametal. It pulls in everything nearby.", "blackforge", 1, new float[4] { 20f, 22f, 24f, 28f }, "Iron:10,FlametalNew:10,Thunderstone:1,Eitr:5", "FlametalNew:10,Thunderstone:1;FlametalNew:20,Thunderstone:2;FlametalNew:40,Thunderstone:4"), new MagnetTierInfo("bloodgold", "Bloodgold Magnet", "Gold rimmed with frost. The frost foundry casts it, and it draws items in from a long way across the snow.", "", 1, new float[1] { 36f }, "", "", forged: false) }; public static bool TryGet(string? prefabName, out MagnetTierInfo? tier) { tier = null; if (prefabName == null || !PickupRules.IsMagnet(prefabName)) { return false; } string text = prefabName.Substring("evu_magnet_".Length); for (int i = 0; i < All.Count; i++) { if (All[i].Id == text) { tier = All[i]; return true; } } return false; } public static string KeepEdited(string saved, string previous, string current) { if (!(saved == previous)) { return saved; } return current; } } public static class PickupRules { public readonly struct ClaimDistance { public float Distance { get; } public long PlayerId { get; } public ClaimDistance(float distance, long playerId) { Distance = distance; PlayerId = playerId; } } public const float VanillaRange = 2f; public const float VanillaPickupDistance = 0.3f; public const float PickupDistance = 1f; public const float HandoffMargin = 0.5f; public const float ClaimMargin = 0.75f; public const float PullSpeed = 15f; public const string PrefabPrefix = "evu_magnet_"; public static bool IsMagnet(string? prefabName) { return prefabName?.StartsWith("evu_magnet_", StringComparison.Ordinal) ?? false; } public static float RangeForQuality(IReadOnlyList<float> radii, int quality) { if (radii == null || radii.Count == 0) { return 2f; } int num = quality - 1; if (num < 0) { num = 0; } else if (num >= radii.Count) { num = radii.Count - 1; } return radii[num]; } public static bool FitsCarry(float carried, float incoming, float maxCarry) { if (incoming >= 0f) { return carried + incoming <= maxCarry; } return false; } public static bool ShouldMove(int stack, bool fitsInventory, float carried, float incoming, float maxCarry) { if (stack > 0 && fitsInventory) { return FitsCarry(carried, incoming, maxCarry); } return false; } public static bool GridFits(int stack, int freeStackSpace, int freeCells, int maxStack) { if (stack <= 0 || freeStackSpace < 0 || freeCells < 0) { return false; } int num = ((maxStack <= 0) ? 1 : maxStack); return freeStackSpace + (long)freeCells * (long)num >= stack; } public static bool InExtraRing(float distance, float vanillaRange, float magnetRange) { if (distance > vanillaRange) { return distance <= magnetRange; } return false; } public static bool NeedsPull(float distanceToOrigin, float vanillaRange, float magnetRange, float handoff) { float num = vanillaRange - handoff; if (num < 0f) { num = 0f; } if (distanceToOrigin > num) { return distanceToOrigin <= magnetRange; } return false; } public static bool AllowInWard(bool pullThroughAllWards, bool playerHasAccess) { return pullThroughAllWards || playerHasAccess; } public static float Reach(float publishedRange) { if (!(publishedRange > 2f)) { return 2f; } return publishedRange; } public static bool CanReach(float distance, float reach) { return distance <= reach; } public static string? ActivePrefab(bool slotExists, string? slotPrefab, IReadOnlyList<string>? equippedPrefabs) { string text = null; int num = 0; bool flag = false; if (equippedPrefabs != null) { for (int i = 0; i < equippedPrefabs.Count; i++) { string text2 = equippedPrefabs[i]; if (IsMagnet(text2)) { num++; if (text == null) { text = text2; } if (slotPrefab != null && string.Equals(text2, slotPrefab, StringComparison.Ordinal)) { flag = true; } } } } if (slotExists) { if (slotPrefab == null || !IsMagnet(slotPrefab)) { return null; } if (!flag) { num++; } if (num != 1) { return null; } return slotPrefab; } if (num != 1) { return null; } return text; } public static bool TryExchangeMagnetSlot(bool magnetEquipped, int magnetX, int magnetY, int slotX, int slotY, out int magnetToX, out int magnetToY, out int occupantToX, out int occupantToY) { magnetToX = slotX; magnetToY = slotY; occupantToX = magnetX; occupantToY = magnetY; if (!magnetEquipped) { return false; } if (magnetX == slotX) { return magnetY != slotY; } return true; } public static bool IsBestClaim(float myDistance, long myId, IReadOnlyList<ClaimDistance> others, float margin) { if (others == null) { return true; } for (int i = 0; i < others.Count; i++) { ClaimDistance claimDistance = others[i]; float num = claimDistance.Distance - myDistance; if (num < 0f - margin) { return false; } if (num <= margin && claimDistance.PlayerId < myId) { return false; } } return true; } public static void PullOffset(float itemX, float itemY, float itemZ, float playerX, float playerY, float playerZ, float speed, float dt, out float offsetX, out float offsetY, out float offsetZ) { float num = playerX - itemX; float num2 = playerY - itemY; float num3 = playerZ - itemZ; double num4 = Math.Sqrt(num * num + num2 * num2 + num3 * num3); if (num4 < 0.0001 || speed <= 0f || dt <= 0f) { offsetX = 0f; offsetY = 0f; offsetZ = 0f; return; } double num5 = (double)speed * (double)dt; if (num4 <= num5) { offsetX = num; offsetY = num2; offsetZ = num3; } else { double num6 = num5 / num4; offsetX = (float)((double)num * num6); offsetY = (float)((double)num2 * num6); offsetZ = (float)((double)num3 * num6); } } } public static class RecipeText { public static bool TryParseList(string text, out IReadOnlyList<Ingredient> items, out string error) { items = Array.Empty<Ingredient>(); error = ""; if (string.IsNullOrWhiteSpace(text)) { error = "Recipe is empty."; return false; } string[] array = text.Split(new char[1] { ',' }); List<Ingredient> list = new List<Ingredient>(array.Length); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (!TryParseOne(array2[i], out var ingredient, out error)) { return false; } list.Add(ingredient); } items = list; return true; } public static bool TryParseUpgrades(string text, out IReadOnlyList<IReadOnlyList<Ingredient>> steps, out string error) { steps = Array.Empty<IReadOnlyList<Ingredient>>(); error = ""; if (string.IsNullOrWhiteSpace(text)) { error = "Upgrades are empty."; return false; } string[] array = text.Split(new char[1] { ';' }); if (array.Length != 3) { error = "Upgrades need three groups, separated by semicolons."; return false; } List<IReadOnlyList<Ingredient>> list = new List<IReadOnlyList<Ingredient>>(3); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (!TryParseList(array2[i], out IReadOnlyList<Ingredient> items, out error)) { return false; } list.Add(items); } steps = list; return true; } public static int AmountFor(int quality, string item, IReadOnlyList<Ingredient> craft, IReadOnlyList<IReadOnlyList<Ingredient>> upgrades) { if (string.IsNullOrEmpty(item)) { return 0; } if (quality <= 1) { return Sum(craft, item); } int num = quality - 2; if (upgrades == null || num < 0 || num >= upgrades.Count) { return 0; } return Sum(upgrades[num], item); } public static IReadOnlyList<Ingredient> Requirements(IReadOnlyList<Ingredient> craft, IReadOnlyList<IReadOnlyList<Ingredient>> upgrades) { List<string> list = new List<string>(); AddNames(list, craft); if (upgrades != null) { for (int i = 0; i < upgrades.Count; i++) { AddNames(list, upgrades[i]); } } Ingredient[] array = new Ingredient[list.Count]; for (int j = 0; j < list.Count; j++) { array[j] = new Ingredient(list[j], Sum(craft, list[j])); } return array; } private static void AddNames(List<string> names, IReadOnlyList<Ingredient> items) { if (items == null) { return; } for (int i = 0; i < items.Count; i++) { if (!names.Contains(items[i].Item)) { names.Add(items[i].Item); } } } private static int Sum(IReadOnlyList<Ingredient> items, string item) { if (items == null) { return 0; } int num = 0; for (int i = 0; i < items.Count; i++) { if (string.Equals(items[i].Item, item, StringComparison.Ordinal)) { num += items[i].Amount; } } return num; } private static bool TryParseOne(string part, out Ingredient ingredient, out string error) { ingredient = default(Ingredient); error = ""; string text = part.Trim(); int num = text.IndexOf(':'); if (num <= 0 || num == text.Length - 1) { error = "Each ingredient must look like Item:Amount."; return false; } string text2 = text.Substring(0, num).Trim(); string s = text.Substring(num + 1).Trim(); if (text2.Length == 0 || !int.TryParse(s, out var result) || result <= 0) { error = "Each ingredient needs a name and a positive amount."; return false; } ingredient = new Ingredient(text2, result); return true; } } }
EvuMagnets.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EvuMagnets.Core; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("evu")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 imevul")] [assembly: AssemblyDescription("Craftable magnets that pull nearby items from farther away.")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: AssemblyInformationalVersion("0.4.0+f10db697f00271bee4eca874a2c89cdc8728c21d")] [assembly: AssemblyProduct("EvuMagnets")] [assembly: AssemblyTitle("EvuMagnets")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/EvuMods/EvuMagnets")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.0.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 EvuMagnets { internal sealed class AdventureBackpackStore : IExtraStore { private const BindingFlags StaticMethod = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static bool _resolved; private static bool _logged; private static MethodInfo? _shouldStore; public bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor) { weightFactor = 1f; try { if (!Ensure() || _shouldStore == null) { return false; } object[] parameters = new object[3] { player, item, null }; return (bool)_shouldStore.Invoke(null, parameters); } catch (Exception ex) { ExtraStores.LogOnce(ref _logged, "Adventure Backpacks store check failed: " + Message(ex)); return false; } } private static bool Ensure() { if (_resolved) { return _shouldStore != null; } _resolved = true; _shouldStore = ExtraStores.FindType("AdventureBackpacks.Features.StoreToBackpack")?.GetMethod("ShouldStoreToBackpack", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3] { typeof(Player), typeof(ItemData), typeof(Inventory).MakeByRefType() }, null); if (_shouldStore == null && ExtraStores.AssemblyLoaded("AdventureBackpacks")) { ExtraStores.LogOnce(ref _logged, "Adventure Backpacks is loaded, but its store check was not found. A full inventory will not pull into that backpack."); } return _shouldStore != null; } private static string Message(Exception ex) { if (ex.InnerException == null) { return ex.Message; } return ex.InnerException.Message; } } internal static class AzuMagnetSlot { private sealed class CachedCall { public MethodInfo Method { get; } public ParameterInfo[] Parameters { get; } public object[] Args { get; } private CachedCall(MethodInfo method) { Method = method; Parameters = method.GetParameters(); Args = new object[Parameters.Length]; } public static CachedCall For(Type api, string name) { MethodInfo method = api.GetMethod(name, BindingFlags.Static | BindingFlags.Public); if (!(method != null)) { return null; } return new CachedCall(method); } } private const string SlotName = "Magnet"; private const string ApiTypeName = "AzuEPI.API, AzuExtendedPlayerInventory"; private static bool _loggedFailure; private static Type _api; private static CachedCall _slotIndex; private static CachedCall _equippedItem; private static CachedCall _gridPos; private static int _cachedIndex = -1; public static bool Exists { get; private set; } public static bool Loaded { get { Type type = Type.GetType("AzuEPI.API, AzuExtendedPlayerInventory"); if (type == null) { return false; } MethodInfo method = type.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public); if (method != null) { return (bool)method.Invoke(null, null); } return false; } } public static bool TryGetFakeItemType(out ItemType itemType) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected I4, but got Unknown itemType = (ItemType)24; Type type = Type.GetType("AzuEPI.API, AzuExtendedPlayerInventory"); if (type == null) { return false; } MethodInfo method = type.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public); if (method == null || !(bool)method.Invoke(null, null)) { return false; } MethodInfo method2 = type.GetMethod("GetFakeItemType", BindingFlags.Static | BindingFlags.Public); if (method2 == null) { return false; } itemType = (ItemType)(int)(ItemType)method2.Invoke(null, null); return true; } public static void Register(IReadOnlyList<string> prefabs) { Exists = false; _api = null; _cachedIndex = -1; Type type = Type.GetType("AzuEPI.API, AzuExtendedPlayerInventory"); if (type == null) { return; } MethodInfo method = type.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public); if (!(method == null) && (bool)method.Invoke(null, null)) { string[] array = new string[prefabs.Count]; for (int i = 0; i < prefabs.Count; i++) { array[i] = prefabs[i]; } if (!TryAdd(type, array)) { Plugin.Log.LogWarning((object)"AzuEPI is loaded, but EvuMagnets could not add the Magnet slot."); return; } _api = type; _slotIndex = CachedCall.For(type, "TryGetSlotIndexByName"); _equippedItem = CachedCall.For(type, "TryGetEquippedItem"); _gridPos = CachedCall.For(type, "GetSlotGridPos"); Exists = true; Plugin.Log.LogInfo((object)"AzuEPI Magnet slot registered."); } } public static bool TryGetEquippedPrefab(out string prefabName) { prefabName = null; if (!Exists || !TrySlotIndex(out var index)) { return false; } if (!TryEquippedItem(index, out var item) || item == null) { return false; } prefabName = PrefabName(item); return PickupRules.IsMagnet(prefabName); } public static bool TryMoveToSlot(Player player, ItemData item) { if (!Exists || (Object)(object)player == (Object)null || item == null) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null || !TryGetSlotGrid(inventory, out var x, out var y)) { return false; } ItemData itemAt = inventory.GetItemAt(x, y); if (itemAt != null && itemAt != item) { return false; } if (item.m_gridPos.x == x && item.m_gridPos.y == y) { return true; } bool num = inventory.MoveItemToThis(inventory, item, item.m_stack, x, y); if (!num && !_loggedFailure) { _loggedFailure = true; Plugin.Log.LogWarning((object)"Could not move a magnet into the AzuEPI Magnet slot."); } return num; } public static bool TryGetSlotGrid(Inventory inventory, out int x, out int y) { x = -1; y = -1; if (!Exists || inventory == null || !TrySlotIndex(out var index)) { return false; } return TryGrid(inventory, index, out x, out y); } private static bool TryAdd(Type api, string[] prefabs) { MethodInfo methodInfo = null; MethodInfo methodInfo2 = null; MethodInfo[] methods = api.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo3 in methods) { if (methodInfo3.Name != "AddSlot") { continue; } ParameterInfo[] parameters = methodInfo3.GetParameters(); if (parameters.Length >= 2 && !(parameters[0].ParameterType != typeof(string))) { Type parameterType = parameters[1].ParameterType; if (parameterType == typeof(string)) { methodInfo2 = methodInfo3; } else if (parameterType == typeof(string[]) || AcceptsStrings(parameterType)) { methodInfo = methodInfo3; } } } if (methodInfo != null) { return InvokeAdd(methodInfo, prefabs); } if (methodInfo2 == null) { return false; } for (int j = 0; j < prefabs.Length; j++) { if (!InvokeAdd(methodInfo2, prefabs[j])) { return false; } } return true; } private static bool InvokeAdd(MethodInfo method, object prefabs) { ParameterInfo[] parameters = method.GetParameters(); object[] array = new object[parameters.Length]; array[0] = "Magnet"; array[1] = prefabs; for (int i = 2; i < parameters.Length; i++) { array[i] = ((parameters[i].ParameterType == typeof(int)) ? ((object)(-1)) : Default(parameters[i].ParameterType)); } object obj = method.Invoke(null, array); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = ((1 == 0) ? 1 : 0); } else { num = 1; } return (byte)((uint)num | (flag ? 1u : 0u)) != 0; } private static bool TrySlotIndex(out int index) { index = _cachedIndex; if (index >= 0) { return true; } if (_api == null || _slotIndex == null) { return false; } ParameterInfo[] parameters = _slotIndex.Parameters; object[] args = _slotIndex.Args; args[0] = "Magnet"; for (int i = 1; i < parameters.Length; i++) { args[i] = Default(parameters[i].ParameterType); } bool flag = (bool)_slotIndex.Method.Invoke(null, args); for (int j = 0; j < parameters.Length; j++) { if (parameters[j].ParameterType == typeof(int).MakeByRefType()) { index = (int)args[j]; } } if (flag && index >= 0) { _cachedIndex = index; } return flag; } private static bool TryEquippedItem(int index, out ItemData item) { item = null; if (_equippedItem == null) { return false; } ParameterInfo[] parameters = _equippedItem.Parameters; object[] args = _equippedItem.Args; int num = -1; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; if (parameterType == typeof(int)) { args[i] = index; } else if (parameterType.IsByRef && parameterType.GetElementType() == typeof(ItemData)) { num = i; args[i] = null; } else { args[i] = Default(parameterType); } } bool num2 = (bool)_equippedItem.Method.Invoke(null, args); if (num >= 0) { object obj = args[num]; item = (ItemData)((obj is ItemData) ? obj : null); args[num] = null; } if (num2) { return item != null; } return false; } private static bool TryGrid(Inventory inventory, int index, out int x, out int y) { x = -1; y = -1; if (_gridPos == null) { return false; } ParameterInfo[] parameters = _gridPos.Parameters; object[] args = _gridPos.Args; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; if (parameterType == typeof(int)) { args[i] = index; } else if (typeof(Inventory).IsAssignableFrom(parameterType)) { args[i] = inventory; } else { args[i] = Default(parameterType); } } object obj = _gridPos.Method.Invoke(null, args); bool flag = false; if (obj != null) { Type type = obj.GetType(); FieldInfo field = type.GetField("x"); FieldInfo field2 = type.GetField("y"); if (field != null && field2 != null) { x = Convert.ToInt32(field.GetValue(obj)); y = Convert.ToInt32(field2.GetValue(obj)); flag = true; } } if (!flag) { for (int j = 0; j < parameters.Length; j++) { if (parameters[j].ParameterType == typeof(int).MakeByRefType()) { if (x < 0) { x = (int)args[j]; } else { y = (int)args[j]; } } } } for (int k = 0; k < args.Length; k++) { args[k] = null; } if (x >= 0 && y >= 0 && x < inventory.GetWidth()) { return y < inventory.GetHeight(); } return false; } private static bool AcceptsStrings(Type type) { if (!type.IsGenericType) { return false; } Type[] genericArguments = type.GetGenericArguments(); if (genericArguments.Length == 1) { return genericArguments[0] == typeof(string); } return false; } private static object Default(Type type) { Type type2 = (type.IsByRef ? type.GetElementType() : type); if (type2 == typeof(string)) { return ""; } if (!type2.IsValueType) { return null; } return Activator.CreateInstance(type2); } private static string PrefabName(ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } return null; } } internal readonly struct StoreHit { public bool WouldStore { get; } public float WeightFactor { get; } public static StoreHit None => new StoreHit(wouldStore: false, 1f); public StoreHit(bool wouldStore, float weightFactor) { WouldStore = wouldStore; WeightFactor = weightFactor; } } internal interface IExtraStore { bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor); } internal static class ExtraStores { private static readonly IExtraStore[] Stores = new IExtraStore[3] { new AdventureBackpackStore(), new SmoothbrainBackpackStore(), new JewelcraftingGemBagStore() }; public static StoreHit Query(Player player, Inventory inventory, ItemData item) { int num = 0; float num2 = 1f; for (int i = 0; i < Stores.Length; i++) { if (Stores[i].TryAccept(player, inventory, item, out var weightFactor)) { num++; num2 = weightFactor; } } if (num == 0) { return StoreHit.None; } if (num > 1 || float.IsNaN(num2) || float.IsInfinity(num2) || num2 < 0f) { num2 = 1f; } return new StoreHit(wouldStore: true, num2); } internal static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } return null; } internal static bool AssemblyLoaded(string simpleName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if (string.Equals(assemblies[i].GetName().Name, simpleName, StringComparison.Ordinal)) { return true; } } return false; } internal static void LogOnce(ref bool logged, string message) { if (!logged) { logged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)message); } } } } internal static class ItemIcons { public static Sprite Load(string id) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) string text = "EvuMagnets.icons." + id + ".png"; using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text); if (stream == null) { throw new InvalidOperationException("Missing embedded icon " + text + "."); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = DecodePng(memoryStream.ToArray(), text); ((Texture)val).filterMode = (FilterMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } private static Texture2D DecodePng(byte[] png, string name) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_006e: 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) if (!TryDecodeRgba(png, out int width, out int height, out byte[] rgba)) { throw new InvalidOperationException("Could not read icon " + name + "."); } Color32[] array = (Color32[])(object)new Color32[width * height]; for (int i = 0; i < height; i++) { int num = i * width * 4; int num2 = (height - 1 - i) * width; for (int j = 0; j < width; j++) { int num3 = num + j * 4; array[num2 + j] = new Color32(rgba[num3], rgba[num3 + 1], rgba[num3 + 2], rgba[num3 + 3]); } } Texture2D val = new Texture2D(width, height, (TextureFormat)4, false); val.SetPixels32(array); val.Apply(false, true); return val; } internal static bool TryDecodeRgba(byte[] png, out int width, out int height, out byte[] rgba) { width = 0; height = 0; rgba = Array.Empty<byte>(); if (png == null || png.Length < 8 || png[0] != 137 || png[1] != 80 || png[2] != 78 || png[3] != 71) { return false; } MemoryStream memoryStream = new MemoryStream(); int num = 8; int num2 = 0; int num3 = 0; int num4; for (; num + 8 <= png.Length; num += num4 + 4) { num4 = ReadInt(png, num); num += 4; int num5 = ReadInt(png, num); num += 4; if (num4 < 0 || num + num4 + 4 > png.Length) { return false; } switch (num5) { case 1229472850: width = ReadInt(png, num); height = ReadInt(png, num + 4); num2 = png[num + 8]; num3 = png[num + 9]; if (png[num + 12] == 0) { continue; } return false; case 1229209940: memoryStream.Write(png, num, num4); continue; default: continue; case 1229278788: break; } break; } if (width <= 0 || height <= 0 || num2 != 8 || num3 != 6) { return false; } byte[] array = Inflate(memoryStream.ToArray()); int num6 = width * 4; if (array.Length < height * (num6 + 1)) { return false; } rgba = new byte[height * num6]; byte[] array2 = new byte[num6]; byte[] array3 = new byte[num6]; int num7 = 0; for (int i = 0; i < height; i++) { byte filter = array[num7++]; Buffer.BlockCopy(array, num7, array3, 0, num6); num7 += num6; Unfilter(filter, array3, array2, num6); Buffer.BlockCopy(array3, 0, rgba, i * num6, num6); byte[] array4 = array2; array2 = array3; array3 = array4; } return true; } private static void Unfilter(byte filter, byte[] current, byte[] previous, int stride) { for (int i = 0; i < stride; i++) { byte b = (byte)((i >= 4) ? current[i - 4] : 0); byte b2 = previous[i]; byte upLeft = (byte)((i >= 4) ? previous[i - 4] : 0); current[i] = filter switch { 0 => current[i], 1 => (byte)(current[i] + b), 2 => (byte)(current[i] + b2), 3 => (byte)(current[i] + (b + b2) / 2), 4 => (byte)(current[i] + Paeth(b, b2, upLeft)), _ => current[i], }; } } private static byte Paeth(byte left, byte up, byte upLeft) { int num = left + up - upLeft; int num2 = Math.Abs(num - left); int num3 = Math.Abs(num - up); int num4 = Math.Abs(num - upLeft); if (num2 <= num3 && num2 <= num4) { return left; } if (num3 > num4) { return upLeft; } return up; } private static byte[] Inflate(byte[] zlib) { if (zlib.Length < 6) { return Array.Empty<byte>(); } using MemoryStream stream = new MemoryStream(zlib, 2, zlib.Length - 6); using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress); using MemoryStream memoryStream = new MemoryStream(); deflateStream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static int ReadInt(byte[] data, int offset) { return (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]; } } internal sealed class JewelcraftingGemBagStore : IExtraStore { private const BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static bool _resolved; private static bool _logged; private static MethodInfo? _dryRun; public bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor) { weightFactor = 1f; try { if (!Ensure() || _dryRun == null) { return false; } return (bool)_dryRun.Invoke(null, new object[3] { inventory, item, true }); } catch (Exception ex) { ExtraStores.LogOnce(ref _logged, "Jewelcrafting gem bag check failed: " + ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message)); return false; } } private static bool Ensure() { if (_resolved) { return _dryRun != null; } _resolved = true; _dryRun = (ExtraStores.FindType("Jewelcrafting.MiscSetup")?.GetNestedType("AddItemToBag", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetMethod("Do", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3] { typeof(Inventory), typeof(ItemData), typeof(bool) }, null); if (_dryRun == null && ExtraStores.AssemblyLoaded("Jewelcrafting")) { ExtraStores.LogOnce(ref _logged, "Jewelcrafting is loaded, but its gem bag check was not found. A full inventory will not pull into that bag."); } return _dryRun != null; } } internal static class MagnetEquip { private static readonly List<string> EquippedNames = new List<string>(); private static int _reconciledId; private static bool _loggedNoCell; public static void ReconcileAfterLoad(Player? player) { if ((Object)(object)player == (Object)null || player.m_isLoading || !AzuMagnetSlot.Exists) { return; } int instanceID = ((Object)player).GetInstanceID(); if (_reconciledId == instanceID) { return; } _reconciledId = instanceID; Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } ItemData val = DedupeEquipped(player, inventory); if (val == null) { return; } if (!AzuMagnetSlot.TryGetSlotGrid(inventory, out var x, out var y)) { if (!_loggedNoCell) { _loggedNoCell = true; Plugin.Log.LogInfo((object)"Magnet slot has no grid cell; leaving the magnet where it is."); } } else { PlaceEquippedMagnet(inventory, val, x, y); } } public static void OnEquipped(Player player, ItemData item) { if (!((Object)(object)player == (Object)null) && item != null && !player.m_isLoading && PickupRules.IsMagnet(PrefabName(item))) { if (AzuMagnetSlot.Exists) { AzuMagnetSlot.TryMoveToSlot(player, item); } UnequipOtherMagnets(player, item); } } private static void UnequipOtherMagnets(Player player, ItemData keep) { List<ItemData> equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val = equippedItems[i]; if (val != null && val != keep && PickupRules.IsMagnet(PrefabName(val))) { ((Humanoid)player).UnequipItem(val, false); } } } private static ItemData? DedupeEquipped(Player player, Inventory inventory) { ItemData val = null; int num = 0; List<ItemData> allItems = inventory.GetAllItems(); AzuMagnetSlot.TryGetEquippedPrefab(out var prefabName); for (int i = 0; i < allItems.Count; i++) { ItemData val2 = allItems[i]; if (val2 != null && val2.m_equipped && PickupRules.IsMagnet(PrefabName(val2))) { num++; if (val == null || (prefabName != null && PrefabName(val2) == prefabName)) { val = val2; } } } if (num > 1 && val != null) { UnequipOtherMagnets(player, val); } return val; } private static void PlaceEquippedMagnet(Inventory inventory, ItemData magnet, int slotX, int slotY) { //IL_0052: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) int num = default(int); int num2 = default(int); int num3 = default(int); int num4 = default(int); if (PickupRules.TryExchangeMagnetSlot(magnet.m_equipped, magnet.m_gridPos.x, magnet.m_gridPos.y, slotX, slotY, ref num, ref num2, ref num3, ref num4)) { ItemData itemAt = inventory.GetItemAt(slotX, slotY); if (itemAt != null && itemAt != magnet) { itemAt.m_gridPos = new Vector2i(num3, num4); } magnet.m_gridPos = new Vector2i(num, num2); inventory.Changed(false, false); } } public static string? ActivePrefab(Player? player) { if ((Object)(object)player == (Object)null) { return null; } List<ItemData> equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems(); EquippedNames.Clear(); for (int i = 0; i < equippedItems.Count; i++) { string text = PrefabName(equippedItems[i]); if (text != null) { EquippedNames.Add(text); } } AzuMagnetSlot.TryGetEquippedPrefab(out var prefabName); return PickupRules.ActivePrefab(AzuMagnetSlot.Exists, prefabName, (IReadOnlyList<string>)EquippedNames); } public static float ActiveRange(Player player, PluginConfig config) { if (config == null || !config.Enabled.Value || !config.Active.Value) { return 2f; } string text = ActivePrefab(player); if (text == null || !config.TryTier(text, out TierConfig tier) || tier == null) { return 2f; } int num = 1; List<ItemData> equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { if (PrefabName(equippedItems[i]) == text) { num = equippedItems[i].m_quality; break; } } return PickupRules.RangeForQuality((IReadOnlyList<float>)tier.Ranges, num); } public static string? PrefabName(ItemData? item) { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return null; } return ((Object)item.m_dropPrefab).name; } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] internal static class EquipPatch { [HarmonyPriority(0)] private static void Postfix(Humanoid __instance, ItemData item, bool __result) { if (__result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { MagnetEquip.OnEquipped(val, item); } } } } internal static class MagnetItems { private sealed class ParsedTier { public IReadOnlyList<Ingredient> Craft { get; } public IReadOnlyList<IReadOnlyList<Ingredient>> Upgrades { get; } public ParsedTier(IReadOnlyList<Ingredient> craft, IReadOnlyList<IReadOnlyList<Ingredient>> upgrades) { Craft = craft; Upgrades = upgrades; } } private static readonly Dictionary<string, Recipe> Recipes = new Dictionary<string, Recipe>(StringComparer.Ordinal); private static readonly Dictionary<string, ParsedTier> Parsed = new Dictionary<string, ParsedTier>(StringComparer.Ordinal); private static PluginConfig _config = null; private static bool _registered; public static void Bind(PluginConfig config) { _config = config; foreach (KeyValuePair<string, TierConfig> tier in config.Tiers) { tier.Value.ListenRecipe(delegate { ApplyRecipes(); }); } config.Cast.Listen(delegate { ApplyRecipes(); }); } public static void Register() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0081: Unknown result type (might be due to invalid IL or missing references) if (!_registered) { _registered = true; AddTranslations(); ItemType itemType = (ItemType)24; if (AzuMagnetSlot.TryGetFakeItemType(out var itemType2)) { itemType = itemType2; Plugin.Log.LogInfo((object)"AzuEPI is loaded. Magnets use AzuEPI's slot item type."); } string text = FindCloneSource(); Plugin.Log.LogInfo((object)("Magnets are cloned from " + text + ".")); string[] array = new string[MagnetCatalog.All.Count]; for (int i = 0; i < MagnetCatalog.All.Count; i++) { MagnetTierInfo val = MagnetCatalog.All[i]; array[i] = val.PrefabName; RegisterTier(val, text, itemType); } AzuMagnetSlot.Register(array); RegisterCast(); RegisterConversion(); ApplyRecipes(); } } public static void ApplyRecipes() { if (_config == null) { return; } Parsed.Clear(); IReadOnlyList<Ingredient> readOnlyList = default(IReadOnlyList<Ingredient>); string text = default(string); IReadOnlyList<IReadOnlyList<Ingredient>> readOnlyList2 = default(IReadOnlyList<IReadOnlyList<Ingredient>>); foreach (MagnetTierInfo item in MagnetCatalog.All) { if (!_config.Tiers.TryGetValue(item.Id, out TierConfig value) || !item.Forged || value.Craft == null || value.Upgrades == null || value.Station == null || value.StationLevel == null) { continue; } if (!RecipeText.TryParseList(value.Craft.Value, ref readOnlyList, ref text) || !RecipeText.TryParseUpgrades(value.Upgrades.Value, ref readOnlyList2, ref text)) { Plugin.Log.LogWarning((object)(item.EnglishName + " recipe was not applied: " + text)); continue; } Parsed[item.PrefabName] = new ParsedTier(readOnlyList, readOnlyList2); if (Recipes.TryGetValue(item.PrefabName, out Recipe value2) && !((Object)(object)value2 == (Object)null)) { CraftingStation val = FindStation(value.Station.Value); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)(item.EnglishName + " station was not found: " + value.Station.Value)); } else { value2.m_craftingStation = val; } value2.m_minStationLevel = value.StationLevel.Value; if (!TryBuildRequirements(RecipeText.Requirements(readOnlyList, readOnlyList2), out Requirement[] requirements)) { value2.m_enabled = false; value2.m_resources = Array.Empty<Requirement>(); } else { value2.m_enabled = true; value2.m_resources = requirements; } } } ApplyCast(); ApplyFoundryTime(); } public static bool TryAmount(Requirement requirement, int quality, out int amount) { amount = 0; if (requirement == null) { return false; } ItemDrop resItem = requirement.m_resItem; if ((Object)(object)resItem == (Object)null || string.IsNullOrEmpty(((Object)resItem).name)) { return false; } string name = ((Object)resItem).name; foreach (KeyValuePair<string, Recipe> recipe in Recipes) { Requirement[] array = (((Object)(object)recipe.Value != (Object)null) ? recipe.Value.m_resources : null); if (array == null || !Parsed.TryGetValue(recipe.Key, out ParsedTier value)) { continue; } for (int i = 0; i < array.Length; i++) { if (array[i] == requirement) { amount = RecipeText.AmountFor(quality, name, value.Craft, value.Upgrades); return true; } } } return false; } private static void RegisterTier(MagnetTierInfo tier, string source, ItemType itemType) { //IL_009a: 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) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown GameObject val = PrefabManager.Instance.CreateClonedPrefab(tier.PrefabName, source); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)("Could not clone " + source + " for " + tier.PrefabName + ".")); return; } ItemDrop component = val.GetComponent<ItemDrop>(); SharedData shared = component.m_itemData.m_shared; shared.m_name = "$" + tier.Token; shared.m_description = "$" + tier.Token + "_desc"; shared.m_itemType = itemType; shared.m_maxStackSize = 1; shared.m_weight = 2f; shared.m_maxQuality = tier.Ranges.Length; shared.m_teleportable = true; shared.m_useDurability = false; shared.m_durabilityDrain = 0f; shared.m_equipStatusEffect = null; shared.m_setStatusEffect = null; shared.m_fullAdrenalineSE = null; shared.m_setName = ""; shared.m_setSize = 0; shared.m_skillType = (SkillType)0; shared.m_icons = (Sprite[])(object)new Sprite[1] { ItemIcons.Load(tier.Id) }; component.m_itemData.m_dropPrefab = val; Tint(val, tier.Id); if (!tier.Forged) { ItemManager.Instance.AddItem(new CustomItem(val, false)); return; } Recipe val2 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val2).name = "Recipe_" + tier.PrefabName; val2.m_item = component; val2.m_amount = 1; val2.m_enabled = true; CustomItem val3 = new CustomItem(val, false); val3.Recipe = new CustomRecipe(val2, false, false); ItemManager.Instance.AddItem(val3); Recipes[tier.PrefabName] = val3.Recipe.Recipe; } private static void AddTranslations() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text; string token; for (int i = 0; i < MagnetCatalog.All.Count; i++) { MagnetTierInfo val = MagnetCatalog.All[i]; text = "English"; token = val.Token; localization.AddTranslation(ref text, ref token, val.EnglishName); text = "English"; token = val.Token + "_desc"; localization.AddTranslation(ref text, ref token, val.EnglishDescription); } text = "English"; token = "item_evu_cast_bloodgold"; localization.AddTranslation(ref text, ref token, "Magnet Cast"); text = "English"; token = "item_evu_cast_bloodgold_desc"; localization.AddTranslation(ref text, ref token, "A black-forged mold. Set it in the frost foundry with liquid frost, and a bloodgold magnet comes out."); } private static void RegisterCast() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown GameObject val = PrefabManager.Instance.CreateClonedPrefab("evu_cast_bloodgold", "Iron"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Could not clone Iron for evu_cast_bloodgold."); return; } ItemDrop component = val.GetComponent<ItemDrop>(); SharedData shared = component.m_itemData.m_shared; shared.m_name = "$item_evu_cast_bloodgold"; shared.m_description = "$item_evu_cast_bloodgold_desc"; shared.m_itemType = (ItemType)1; shared.m_maxStackSize = 10; shared.m_weight = 2f; shared.m_maxQuality = 1; shared.m_teleportable = true; shared.m_useDurability = false; shared.m_durabilityDrain = 0f; shared.m_equipStatusEffect = null; shared.m_setStatusEffect = null; shared.m_setName = ""; shared.m_setSize = 0; shared.m_skillType = (SkillType)0; shared.m_icons = (Sprite[])(object)new Sprite[1] { ItemIcons.Load("cast") }; component.m_itemData.m_dropPrefab = val; Tint(val, "cast"); Recipe val2 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val2).name = "Recipe_evu_cast_bloodgold"; val2.m_item = component; val2.m_amount = 1; val2.m_enabled = true; CustomItem val3 = new CustomItem(val, false); val3.Recipe = new CustomRecipe(val2, false, false); ItemManager.Instance.AddItem(val3); Recipes["evu_cast_bloodgold"] = val3.Recipe.Recipe; } private static void RegisterConversion() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new CookingConversionConfig { Station = _config.Cast.Foundry.Value, FromItem = "evu_cast_bloodgold", ToItem = "evu_magnet_bloodgold", CookTime = _config.Cast.CookTime.Value })); } private static void ApplyFoundryTime() { GameObject prefab = PrefabManager.Instance.GetPrefab(_config.Cast.Foundry.Value); CookingStation val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CookingStation>() : null); if ((Object)(object)val == (Object)null || val.m_conversion == null) { return; } for (int i = 0; i < val.m_conversion.Count; i++) { ItemConversion val2 = val.m_conversion[i]; if (val2 != null && (Object)(object)val2.m_from != (Object)null && ((Object)val2.m_from).name == "evu_cast_bloodgold") { val2.m_cookTime = _config.Cast.CookTime.Value; break; } } } private static void ApplyCast() { if (!Recipes.TryGetValue("evu_cast_bloodgold", out Recipe value) || (Object)(object)value == (Object)null) { return; } IReadOnlyList<Ingredient> craft = default(IReadOnlyList<Ingredient>); string text = default(string); if (!RecipeText.TryParseList(_config.Cast.Craft.Value, ref craft, ref text)) { Plugin.Log.LogWarning((object)("Magnet cast recipe was not applied: " + text)); value.m_enabled = false; value.m_resources = Array.Empty<Requirement>(); return; } CraftingStation val = FindStation(_config.Cast.Station.Value); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("Magnet cast station was not found: " + _config.Cast.Station.Value)); } else { value.m_craftingStation = val; } value.m_minStationLevel = _config.Cast.StationLevel.Value; if (!TryBuildRequirements(craft, out Requirement[] requirements)) { value.m_enabled = false; value.m_resources = Array.Empty<Requirement>(); } else { value.m_enabled = true; value.m_resources = requirements; } } private static string FindCloneSource() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Invalid comparison between Unknown and I4 string text = null; List<GameObject> list = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.m_items : null); if (list != null) { for (int i = 0; i < list.Count; i++) { ItemDrop val = (((Object)(object)list[i] != (Object)null) ? list[i].GetComponent<ItemDrop>() : null); if (!((Object)(object)val == (Object)null) && (int)val.m_itemData.m_shared.m_itemType == 24 && (text == null || string.CompareOrdinal(((Object)list[i]).name, text) < 0)) { text = ((Object)list[i]).name; } } } return text ?? "BeltStrength"; } private static CraftingStation? FindStation(string name) { if (string.IsNullOrWhiteSpace(name)) { return null; } GameObject prefab = PrefabManager.Instance.GetPrefab(name.Trim()); if (!((Object)(object)prefab != (Object)null)) { return null; } return prefab.GetComponent<CraftingStation>(); } private static bool TryBuildRequirements(IReadOnlyList<Ingredient> craft, out Requirement[] requirements) { //IL_0016: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_003e: 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) requirements = (Requirement[])(object)new Requirement[craft.Count]; for (int i = 0; i < craft.Count; i++) { Ingredient val = craft[i]; ItemDrop val2 = FindItem(((Ingredient)(ref val)).Item); if ((Object)(object)val2 == (Object)null) { ManualLogSource log = Plugin.Log; val = craft[i]; log.LogWarning((object)("Recipe item was not found: " + ((Ingredient)(ref val)).Item)); requirements = Array.Empty<Requirement>(); return false; } Requirement[] obj = requirements; int num = i; Requirement val3 = new Requirement { m_resItem = val2 }; val = craft[i]; val3.m_amount = ((Ingredient)(ref val)).Amount; val3.m_amountPerLevel = 0; val3.m_recover = true; val3.m_upgraderResource = false; obj[num] = val3; } return true; } private static ItemDrop? FindItem(string name) { GameObject prefab = PrefabManager.Instance.GetPrefab(name); ItemDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val != (Object)null) { return val; } if ((Object)(object)ObjectDB.instance == (Object)null) { return null; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val != (Object)null) { return val; } List<GameObject> items = ObjectDB.instance.m_items; if (items == null) { return null; } for (int i = 0; i < items.Count; i++) { if (!((Object)(object)items[i] == (Object)null) && !(((Object)items[i]).name != name)) { val = items[i].GetComponent<ItemDrop>(); if ((Object)(object)val != (Object)null) { return val; } } } return null; } private static void Tint(GameObject prefab, string id) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) Color color = (Color)(id switch { "cast" => new Color(0.78f, 0.74f, 0.62f), "bloodgold" => new Color(0.95f, 0.74f, 0.22f), "flametal" => new Color(0.95f, 0.28f, 0.05f), "blackmetal" => new Color(0.12f, 0.42f, 0.18f), "silver" => new Color(0.78f, 0.82f, 0.86f), _ => new Color(0.45f, 0.42f, 0.4f), }); Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = componentsInChildren[i].sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { if (!((Object)(object)sharedMaterials[j] == (Object)null)) { Material val = new Material(sharedMaterials[j]); if (val.HasProperty("_Color")) { val.color = color; } sharedMaterials[j] = val; } } componentsInChildren[i].sharedMaterials = sharedMaterials; } } } [HarmonyPatch(typeof(Requirement), "GetAmount")] internal static class RequirementAmountPatch { private static void Postfix(Requirement __instance, int qualityLevel, ref int __result) { if (MagnetItems.TryAmount(__instance, qualityLevel, out var amount)) { __result = amount; } } } internal static class MagnetReach { private static readonly int ReachHash = StringExtensionMethods.GetStableHashCode("EvuMagnets.Reach"); private static float _published = -1f; private static ZDO? _publishedTo; public static void Publish(Player player, float range) { if ((Object)(object)player == (Object)null) { return; } ZNetView nview = ((Character)player).m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { ZDO zDO = nview.GetZDO(); if (zDO != _publishedTo || range != _published) { zDO.Set(ReachHash, range); _published = range; _publishedTo = zDO; } } } public static float Of(Player other) { ZNetView val = (((Object)(object)other != (Object)null) ? ((Character)other).m_nview : null); if ((Object)(object)val == (Object)null || !val.IsValid()) { return 2f; } return PickupRules.Reach(val.GetZDO().GetFloat(ReachHash, 0f)); } } [HarmonyPatch(typeof(Player), "AutoPickup")] internal static class PickupPatch { private struct Pass { public float OriginalRange; public bool Extend; public float Range; } private const int InitialHits = 128; private static Collider[] Hits = (Collider[])(object)new Collider[128]; private static readonly List<ClaimDistance> Claims = new List<ClaimDistance>(); private static readonly HashSet<string> Blocked = new HashSet<string>(StringComparer.Ordinal); private static bool _loggedDropFailure; private static bool _resolvedFreeCells; private static MethodInfo? _freeNormalCells; private static void Prefix(Player __instance, ref Pass __state) { __state.OriginalRange = __instance.m_autoPickupRange; __state.Extend = ShouldExtend(__instance, out __state.Range); MagnetReach.Publish(__instance, __state.Extend ? __state.Range : 0f); if (__state.Extend) { __instance.m_autoPickupRange = 0f; } } private static void Postfix(Player __instance, float dt, Pass __state) { __instance.m_autoPickupRange = __state.OriginalRange; if (__state.Extend) { PullExtraRing(__instance, dt, __state.Range); } } private static bool ShouldExtend(Player player, out float range) { range = 2f; if ((Object)(object)player == (Object)null || Plugin.Settings == null || !Player.m_enableAutoPickup) { return false; } range = MagnetEquip.ActiveRange(player, Plugin.Settings); return range > 2f; } private static void PullExtraRing(Player player, float dt, float range) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //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_006a: Unknown result type (might be due to invalid IL or missing references) if (((Character)player).IsDead() || ((Character)player).IsTeleporting()) { return; } Blocked.Clear(); Vector3 origin = ((Component)player).transform.position + Vector3.up; int num = Overlap(origin, range, player.m_autoPickupMask); Inventory inventory = ((Humanoid)player).GetInventory(); for (int i = 0; i < num; i++) { Collider val = Hits[i]; Hits[i] = null; if ((Object)(object)val == (Object)null) { continue; } try { PullOne(player, inventory, val, origin, range, dt); } catch (Exception ex) { if (!_loggedDropFailure) { _loggedDropFailure = true; Plugin.Log.LogWarning((object)("Skipped a drop the magnet could not read: " + ex.Message)); } } } } private static void PullOne(Player player, Inventory inventory, Collider collider, Vector3 origin, float range, float dt) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) Rigidbody attachedRigidbody = collider.attachedRigidbody; if ((Object)(object)attachedRigidbody == (Object)null) { return; } ItemDrop component = ((Component)attachedRigidbody).GetComponent<ItemDrop>(); FloatingTerrainDummy val = null; if ((Object)(object)component == (Object)null) { val = ((Component)attachedRigidbody).GetComponent<FloatingTerrainDummy>(); if ((Object)(object)val != (Object)null && (Object)(object)val.m_parent != (Object)null) { component = ((Component)val.m_parent).GetComponent<ItemDrop>(); } } if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null || !component.m_autoPickup || component.IsPiece() || ((Humanoid)player).HaveUniqueKey(component.m_itemData.m_shared.m_name)) { return; } ZNetView component2 = ((Component)component).GetComponent<ZNetView>(); if ((Object)(object)component2 == (Object)null || !component2.IsValid() || component.InTar()) { return; } Vector3 position = ((Component)component).transform.position; if (!PickupRules.AllowInWard(Plugin.Settings.PullThroughAllWards.Value, PrivateArea.CheckAccess(position, 0f, false, true))) { return; } Vector3 position2 = ((Component)player).transform.position; float num = HorizontalDistance(position, position2); float num2 = Vector3.Distance(position, origin); bool flag = num2 < 0.3f; bool flag2 = num2 >= 0.3f && num2 <= range; if (!flag && !flag2) { return; } ItemData itemData = component.m_itemData; string name = itemData.m_shared.m_name; if (name != null && Blocked.Contains(name)) { return; } if (component2.IsOwner()) { component.Load(); } int stack = itemData.m_stack; float totalWeight = inventory.GetTotalWeight(); float maxCarryWeight = player.GetMaxCarryWeight(); bool flag3 = FitsInventory(inventory, itemData, 1); bool flag4 = stack > 0 && FitsInventory(inventory, itemData, stack); StoreHit store = ((flag3 && flag4) ? StoreHit.None : ExtraStores.Query(player, inventory, itemData)); if (!CanMove(1, flag3, store, totalWeight, itemData.GetWeight(1), maxCarryWeight)) { if (name != null) { Blocked.Add(name); } } else { if (!CanMove(stack, flag4, store, totalWeight, itemData.GetWeight(stack), maxCarryWeight)) { return; } FillClaims(player, position); bool flag5 = PickupRules.IsBestClaim(num, player.GetPlayerID(), (IReadOnlyList<ClaimDistance>)Claims, 0.75f); if (!component2.IsOwner()) { if (flag5 && flag2) { component.RequestOwn(); } } else { if (!flag5 || !component.CanPickup(true)) { return; } if (flag) { ((Humanoid)player).Pickup(((Component)component).gameObject, true, true); return; } float num3 = default(float); float num4 = default(float); float num5 = default(float); PickupRules.PullOffset(position.x, position.y, position.z, origin.x, origin.y, origin.z, 15f, dt, ref num3, ref num4, ref num5); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(num3, num4, num5); Stop(attachedRigidbody); Stop(((Component)component).GetComponent<Rigidbody>()); Transform transform = ((Component)component).transform; transform.position += val2; if ((Object)(object)val != (Object)null) { Transform transform2 = ((Component)val).transform; transform2.position += val2; } } } } private static bool CanMove(int stack, bool gridFits, StoreHit store, float carried, float weight, float maxCarry) { bool flag = gridFits || store.WouldStore; float num = ((gridFits || !store.WouldStore) ? 1f : store.WeightFactor); return PickupRules.ShouldMove(stack, flag, carried, weight * num, maxCarry); } private static bool FitsInventory(Inventory inventory, ItemData data, int stack) { SharedData shared = data.m_shared; int num = inventory.FindFreeStackSpace(shared.m_name, (float)data.m_worldLevel); return PickupRules.GridFits(stack, num, FreeCells(inventory), shared.m_maxStackSize); } private static int FreeCells(Inventory inventory) { if (!_resolvedFreeCells) { _resolvedFreeCells = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { _freeNormalCells = assemblies[i].GetType("AzuEPI.Core.InventoryHandlers.Capacity")?.GetMethod("FreeNormalCells", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (_freeNormalCells != null) { break; } } } if (_freeNormalCells != null) { return (int)_freeNormalCells.Invoke(null, new object[1] { inventory }); } return inventory.GetEmptySlots(); } private static int Overlap(Vector3 origin, float range, int mask) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) int num = HitCap(); if (Hits.Length > num) { Hits = (Collider[])(object)new Collider[num]; } int num2; while (true) { num2 = Physics.OverlapSphereNonAlloc(origin, range, Hits, mask); if (num2 < Hits.Length || Hits.Length >= num) { return num2; } int num3 = Hits.Length * 2; if (num3 > num) { num3 = num; } if (num3 <= Hits.Length) { break; } Hits = (Collider[])(object)new Collider[num3]; } return num2; } private static int HitCap() { int num = ((Plugin.Settings != null) ? Plugin.Settings.MaxHits.Value : 2048); if (num < 128) { return 128; } if (num > 2048) { return 2048; } return num; } private static void FillClaims(Player player, Vector3 itemPosition) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) Claims.Clear(); List<Player> allPlayers = Player.GetAllPlayers(); for (int i = 0; i < allPlayers.Count; i++) { Player val = allPlayers[i]; if (!((Object)(object)val == (Object)null) && val != player && !((Character)val).IsDead() && !((Character)val).IsTeleporting()) { float num = HorizontalDistance(((Component)val).transform.position, itemPosition); if (PickupRules.CanReach(num, MagnetReach.Of(val))) { Claims.Add(new ClaimDistance(num, val.GetPlayerID())); } } } } private static float HorizontalDistance(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return Mathf.Sqrt(num * num + num2 * num2); } private static void Stop(Rigidbody body) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)body == (Object)null)) { body.linearVelocity = Vector3.zero; body.angularVelocity = Vector3.zero; } } } [BepInPlugin("evu.evumagnets", "EvuMagnets", "0.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { private ConfigFileWatcher _configWatcher; internal static PluginConfig Settings { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Settings = new PluginConfig(((BaseUnityPlugin)this).Config); _configWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); MagnetItems.Bind(Settings); ItemManager.OnVanillaItemsAvailable += MagnetItems.Register; ItemManager.OnItemsRegistered += MagnetItems.ApplyRecipes; SynchronizationManager.OnConfigurationSynchronized += delegate { MagnetItems.ApplyRecipes(); }; Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "evu.evumagnets"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"EvuMagnets loaded."); } private void Update() { //IL_001b: 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) MagnetEquip.ReconcileAfterLoad(Player.m_localPlayer); if (Settings != null) { KeyboardShortcut value = Settings.Toggle.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !Typing()) { Settings.Active.Value = !Settings.Active.Value; } } } private static bool Typing() { if ((Object)(object)Console.instance != (Object)null && Console.IsVisible()) { return true; } if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return true; } if ((Object)(object)TextInput.instance != (Object)null) { return TextInput.IsVisible(); } return false; } } internal sealed class TierConfig { public ConfigEntry<float> Range1 { get; } public ConfigEntry<float>? Range2 { get; } public ConfigEntry<float>? Range3 { get; } public ConfigEntry<float>? Range4 { get; } public ConfigEntry<string>? Craft { get; } public ConfigEntry<string>? Upgrades { get; } public ConfigEntry<string>? Station { get; } public ConfigEntry<int>? StationLevel { get; } public float[] Ranges { get { if (Range2 != null && Range3 != null && Range4 != null) { return new float[4] { Range1.Value, Range2.Value, Range3.Value, Range4.Value }; } return new float[1] { Range1.Value }; } } public TierConfig(ConfigFile config, MagnetTierInfo tier, int order) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown string englishName = tier.EnglishName; Range1 = BindRange(config, englishName, "Range1", tier.Ranges[0], "Pickup radius in meters at quality 1.", order); if (tier.Forged) { Range2 = BindRange(config, englishName, "Range2", tier.Ranges[1], "Pickup radius in meters at quality 2.", order - 1); Range3 = BindRange(config, englishName, "Range3", tier.Ranges[2], "Pickup radius in meters at quality 3.", order - 2); Range4 = BindRange(config, englishName, "Range4", tier.Ranges[3], "Pickup radius in meters at quality 4.", order - 3); ConfigEntry<string> val = config.Bind<string>(englishName, "Craft", tier.Craft, new ConfigDescription("Ingredients for a new magnet. Item prefab names and amounts, separated by commas.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(order - 4) })); ConfigEntry<string> val2 = config.Bind<string>(englishName, "Upgrades", tier.Upgrades, new ConfigDescription("Three upgrade steps, separated by semicolons. Each step is Item:Amount pairs separated by commas.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(order - 5) })); if (tier.Id == "flametal") { val.Value = MagnetCatalog.KeepEdited(val.Value, "Iron:10,Flametal:10,Thunderstone:1,Eitr:5", tier.Craft); val2.Value = MagnetCatalog.KeepEdited(val2.Value, "Flametal:10,Thunderstone:1;Flametal:20,Thunderstone:2;Flametal:40,Thunderstone:4", tier.Upgrades); } Craft = val; Upgrades = val2; Station = config.Bind<string>(englishName, "Station", tier.Station, new ConfigDescription("Crafting station prefab name.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(order - 6) })); StationLevel = config.Bind<int>(englishName, "StationLevel", tier.StationLevel, new ConfigDescription("Crafting station level required to make quality 1. Each upgrade asks for one level more.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), new object[1] { ConfigHints.Synced(order - 7) })); } } public void ListenRecipe(EventHandler handler) { if (Craft != null) { Craft.SettingChanged += handler; } if (Upgrades != null) { Upgrades.SettingChanged += handler; } if (Station != null) { Station.SettingChanged += handler; } if (StationLevel != null) { StationLevel.SettingChanged += handler; } } private static ConfigEntry<float> BindRange(ConfigFile config, string section, string key, float value, string description, int order) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown return config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 64f), new object[1] { ConfigHints.Synced(order) })); } } internal sealed class PluginConfig { public ConfigEntry<bool> Enabled { get; } public ConfigEntry<bool> PullThroughAllWards { get; } public ConfigEntry<bool> Active { get; } public ConfigEntry<KeyboardShortcut> Toggle { get; } public ConfigEntry<int> MaxHits { get; } public IReadOnlyDictionary<string, TierConfig> Tiers { get; } public CastConfig Cast { get; } public PluginConfig(ConfigFile config) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00bb: 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_00e3: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown Enabled = config.Bind<bool>("General", "Enabled", true, new ConfigDescription("When off, magnets do not extend pickup range. Crafted magnets stay in the world.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(100) })); PullThroughAllWards = config.Bind<bool>("General", "PullThroughAllWards", false, new ConfigDescription("When on, magnets also pull items that sit inside other players' wards. Players can always pull items inside their own wards.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(90) })); Active = config.Bind<bool>("Local", "Active", true, new ConfigDescription("When off, your magnet does not extend pickup. Vanilla auto-pickup stays on. This client only.", (AcceptableValueBase)null, new object[1] { ConfigHints.Local(200) })); Toggle = config.Bind<KeyboardShortcut>("Local", "Toggle", new KeyboardShortcut((KeyCode)118, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Key that turns your magnet on or off. This client only.", (AcceptableValueBase)null, new object[1] { ConfigHints.Local(190) })); MaxHits = config.Bind<int>("Local", "MaxHits", 2048, new ConfigDescription("Most nearby colliders one magnet pass will search. The search starts at 128 and grows to this cap. Lower it if a large pull hitches. This client only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(128, 2048), new object[1] { ConfigHints.Local(180) })); Dictionary<string, TierConfig> dictionary = new Dictionary<string, TierConfig>(StringComparer.Ordinal); for (int i = 0; i < MagnetCatalog.All.Count; i++) { MagnetTierInfo val = MagnetCatalog.All[i]; dictionary[val.Id] = new TierConfig(config, val, 80 - i * 10); } Tiers = dictionary; Cast = new CastConfig(config); } public bool TryTier(string? prefabName, out TierConfig? tier) { tier = null; MagnetTierInfo val = default(MagnetTierInfo); if (!MagnetCatalog.TryGet(prefabName, ref val) || val == null) { return false; } return Tiers.TryGetValue(val.Id, out tier); } } internal sealed class CastConfig { public ConfigEntry<string> Craft { get; } public ConfigEntry<string> Station { get; } public ConfigEntry<int> StationLevel { get; } public ConfigEntry<string> Foundry { get; } public ConfigEntry<float> CookTime { get; } public CastConfig(ConfigFile config) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown Craft = config.Bind<string>("Magnet Cast", "Craft", "Iron:10,Thunderstone:1,Gold:10,FrostCore:5", new ConfigDescription("Ingredients for a magnet cast. Item prefab names and amounts, separated by commas.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(20) })); Station = config.Bind<string>("Magnet Cast", "Station", "blackforge", new ConfigDescription("Crafting station prefab name.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(19) })); StationLevel = config.Bind<int>("Magnet Cast", "StationLevel", 1, new ConfigDescription("Crafting station level required.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), new object[1] { ConfigHints.Synced(18) })); Foundry = config.Bind<string>("Magnet Cast", "Foundry", "piece_FrostFoundry", new ConfigDescription("Frost foundry prefab. Place the cast in it and liquid frost in the fuel slot. Read when a world loads.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(17) })); CookTime = config.Bind<float>("Magnet Cast", "CookTime", 50f, new ConfigDescription("Seconds the frost foundry takes to turn one cast into a bloodgold magnet.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), new object[1] { ConfigHints.Synced(16) })); } public void Listen(EventHandler handler) { Craft.SettingChanged += handler; Station.SettingChanged += handler; StationLevel.SettingChanged += handler; CookTime.SettingChanged += handler; } } internal static class ConfigHints { public static ConfigurationManagerAttributes Synced(int order) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = true, Order = order }; } public static ConfigurationManagerAttributes Local(int order) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = false, Order = order }; } } internal static class PluginInfo { public const string Guid = "evu.evumagnets"; public const string Name = "EvuMagnets"; public const string Version = "0.4.0"; } internal sealed class SmoothbrainBackpackStore : IExtraStore { private const BindingFlags InstanceAny = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags StaticAny = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static bool _resolved; private static bool _logged; private static MethodInfo? _data; private static MethodInfo? _get; private static MethodInfo? _mayAutoPickup; private static MethodInfo? _canAddItem; private static MethodInfo? _weightFactor; private static MethodInfo? _canAddToInventory; private static MethodInfo? _containsName; private static FieldInfo? _inventory; private static PropertyInfo? _item; private static Type? _containerType; private static Type? _customType; private static FieldInfo? _allowedItems; public bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor) { weightFactor = 1f; try { if (!Ensure() || inventory.m_inventory == null || _data == null || _get == null) { return false; } object obj = null; long num = long.MinValue; List<ItemData> inventory2 = inventory.m_inventory; for (int i = 0; i < inventory2.Count; i++) { ItemData val = inventory2[i]; if (val == null || !TryContainer(val, out object container) || container == null || !CallBool(_mayAutoPickup, container, item) || !CallBool(_canAddItem, container, item)) { continue; } object? obj2 = _inventory?.GetValue(container); Inventory val2 = (Inventory)((obj2 is Inventory) ? obj2 : null); if (val2 != null && !(_canAddToInventory == null) && (bool)_canAddToInventory.Invoke(val2, new object[2] { item, -1 })) { long num2 = Score(container, val2, item.m_shared.m_name); if (num2 > num) { num = num2; obj = container; } } } if (obj == null || _weightFactor == null) { return false; } weightFactor = (float)_weightFactor.Invoke(obj, null); return true; } catch (Exception ex) { ExtraStores.LogOnce(ref _logged, "Backpacks store check failed: " + ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message)); return false; } } private bool TryContainer(ItemData held, out object? container) { container = null; object obj = _data.Invoke(null, new object[1] { held }); if (obj == null || _get == null || _containerType == null) { return false; } container = _get.Invoke(obj, new object[1] { string.Empty }); return container != null; } private static bool CallBool(MethodInfo? method, object instance, ItemData item) { if (method != null) { return (bool)method.Invoke(instance, new object[1] { item }); } return false; } private long Score(object container, Inventory bag, string? itemName) { //IL_0029: 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) //IL_0024: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) object? obj = _item?.GetValue(container, null); ItemData val = (ItemData)((obj is ItemData) ? obj : null); Vector2i val2 = (Vector2i)(((??)val?.m_gridPos) ?? default(Vector2i)); long num = 1 + val2.x + (long)val2.y * 100L; if (itemName != null && _containsName != null && (bool)_containsName.Invoke(bag, new object[1] { itemName })) { num += 10000; } Type type = container.GetType(); if (_customType != null && !_customType.IsInstanceOfType(container) && type != _containerType) { num *= 400000000; } else if (_customType != null && _customType.IsInstanceOfType(container) && HasAllowedList(val)) { num *= 20000; } return num; } private bool HasAllowedList(ItemData? backpack) { string text = backpack?.m_shared?.m_name; if (text == null || !(_allowedItems?.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(text)) { return false; } if (dictionary[text] is ICollection collection) { return collection.Count > 0; } return false; } private static bool Ensure() { if (_resolved) { return _data != null; } _resolved = true; _containerType = ExtraStores.FindType("Backpacks.ItemContainer"); _customType = ExtraStores.FindType("Backpacks.CustomBackpack"); Type? type = ExtraStores.FindType("ItemDataManager.ItemExtensions"); Type infoType = ExtraStores.FindType("ItemDataManager.ItemInfo"); _data = type?.GetMethod("Data", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null); _get = GenericGet(infoType); if (_get != null && _containerType != null) { _get = _get.MakeGenericMethod(_containerType); } _mayAutoPickup = _containerType?.GetMethod("MayAutoPickup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null); _canAddItem = _containerType?.GetMethod("CanAddItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null); _weightFactor = _containerType?.GetMethod("WeightFactor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); _inventory = _containerType?.GetField("Inventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _item = _containerType?.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _allowedItems = _customType?.GetField("AllowedItems", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _canAddToInventory = typeof(Inventory).GetMethod("CanAddItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(ItemData), typeof(int) }, null); _containsName = typeof(Inventory).GetMethod("ContainsItemByName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); int num; if (_data != null && _get != null && _mayAutoPickup != null && _canAddItem != null && _weightFactor != null && _inventory != null) { num = ((_canAddToInventory != null) ? 1 : 0); if (num != 0) { goto IL_0281; } } else { num = 0; } if (ExtraStores.AssemblyLoaded("Backpacks")) { ExtraStores.LogOnce(ref _logged, "Backpacks is loaded, but its auto-fill check was not found. A full inventory will not pull into those backpacks."); } goto IL_0281; IL_0281: return (byte)num != 0; } private static MethodInfo? GenericGet(Type? infoType) { if (infoType == null) { return null; } MethodInfo[] methods = infoType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "Get") && methodInfo.IsGenericMethodDefinition) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string)) { return methodInfo; } } } return null; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }