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 Valheim Blue Archive Mod v1.1.0
plugins/Valheim_Blue_Archive_Mod.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace ValheimBlueArchiveMod; [BepInPlugin("com.ayok.valheim.bluearchive", "Valheim_Blue_Archive_Mod", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class BlueArchivePlugin : BaseUnityPlugin { public class KeptItemData { public ItemData Item { get; } public bool WasEquipped { get; } public bool IsTool { get; } public KeptItemData(ItemData item, bool wasEquipped, bool isTool) { Item = item; WasEquipped = wasEquipped; IsTool = isTool; } } [HarmonyPatch(typeof(Player), "CreateTombStone")] [HarmonyAfter(new string[] { "randyknapp.mods.equipmentandquickslots" })] public static class CreateTombStone_Patch { [HarmonyPrefix] [HarmonyAfter(new string[] { "randyknapp.mods.equipmentandquickslots" })] public static bool Prefix(Player __instance, out List<KeptItemData> __state) { __state = new List<KeptItemData>(); if (!ModEnabled.Value || (Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (VanillaKeepsEntireInventory()) { return true; } Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory == null) { return true; } List<ItemData> allItems = inventory.GetAllItems(); if (allItems == null) { return true; } try { for (int num = allItems.Count - 1; num >= 0; num--) { ItemData item = allItems[num]; if (ShouldKeepItem(__instance, item)) { bool wasEquipped = IsEquipped(__instance, item); bool isTool = IsTool(item); __state.Add(new KeptItemData(item, wasEquipped, isTool)); allItems.RemoveAt(num); } } if (__state.Count > 0) { int num2 = 0; int num3 = 0; for (int i = 0; i < __state.Count; i++) { if (__state[i].WasEquipped) { num3++; } else if (__state[i].IsTool) { num2++; } } if (Log != null) { Log.LogInfo((object)("Player '" + __instance.GetPlayerName() + "' died: preserving " + num2 + " unequipped tools and " + num3 + " equipped items that vanilla would have dropped.")); } } return HasDroppableRemainder(allItems); } catch (Exception ex) { if (Log != null) { Log.LogError((object)("Error in CreateTombStone Prefix: " + ex)); } return true; } } [HarmonyPostfix] [HarmonyAfter(new string[] { "randyknapp.mods.equipmentandquickslots" })] public static void Postfix(Player __instance, List<KeptItemData> __state) { if (!ModEnabled.Value || (Object)(object)__instance == (Object)null || __state == null || __state.Count == 0 || ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { return; } Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory == null) { return; } List<ItemData> allItems = inventory.GetAllItems(); if (allItems == null) { return; } try { int num = 0; int num2 = 0; for (int i = 0; i < __state.Count; i++) { KeptItemData keptItemData = __state[i]; if (keptItemData.Item != null) { keptItemData.Item.m_equipped = keptItemData.WasEquipped; if (!allItems.Contains(keptItemData.Item)) { allItems.Add(keptItemData.Item); } if (keptItemData.WasEquipped) { num2++; } else if (keptItemData.IsTool) { num++; } } } if (inventory.m_onChanged != null) { inventory.m_onChanged(); } if (NotificationOnDeath.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && (num > 0 || num2 > 0)) { ((Character)__instance).Message((MessageType)2, "Death Protection: " + num + " tools & " + num2 + " equipped items preserved.", 0, (Sprite)null, false); } } catch (Exception ex) { if (Log != null) { Log.LogError((object)("Error in CreateTombStone Postfix: " + ex)); } } } private static bool HasDroppableRemainder(List<ItemData> inventoryList) { for (int i = 0; i < inventoryList.Count; i++) { ItemData val = inventoryList[i]; if (val != null && val.m_shared != null && !val.m_shared.m_questItem) { return true; } } return false; } } public const string ModGUID = "com.ayok.valheim.bluearchive"; public const string ModName = "Valheim_Blue_Archive_Mod"; public const string ModVersion = "1.1.0"; public const string EquipmentAndQuickSlotsGUID = "randyknapp.mods.equipmentandquickslots"; public static ConfigEntry<bool> ModEnabled; public static ConfigEntry<bool> KeepTools; public static ConfigEntry<bool> KeepEquippedItems; public static ConfigEntry<bool> NotificationOnDeath; public static ConfigEntry<bool> KeepBuildingAndFarmingTools; public static ConfigEntry<bool> KeepPickaxes; public static ConfigEntry<bool> KeepAxes; public static ConfigEntry<bool> KeepFishingRod; public static ConfigEntry<bool> KeepButcherKnife; public static ConfigEntry<string> IncludePrefabs; public static ConfigEntry<string> ExcludePrefabs; private static readonly HashSet<string> IncludeList = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> ExcludeList = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private Harmony _harmony; public static BlueArchivePlugin Instance { get; private set; } public static ManualLogSource Log { get { if (!((Object)(object)Instance != (Object)null)) { return null; } return ((BaseUnityPlugin)Instance).Logger; } } private void Awake() { //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown Instance = this; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable Valheim_Blue_Archive_Mod."); KeepTools = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepTools", true, "Keep unequipped tools in your inventory on death instead of dropping them into the gravestone."); KeepEquippedItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepEquippedItems", true, "Keep equipped items when the world would otherwise unequip and drop them. No-op if the world already keeps equipped items."); NotificationOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowDeathNotification", true, "Display a brief on-screen message upon death showing how many tools and equipped items were preserved."); KeepBuildingAndFarmingTools = ((BaseUnityPlugin)this).Config.Bind<bool>("ToolTypes", "KeepBuildingAndFarmingTools", true, "Keep construction and farming tools (Hammer, Hoe, Cultivator, and other ItemType.Tool items)."); KeepPickaxes = ((BaseUnityPlugin)this).Config.Bind<bool>("ToolTypes", "KeepPickaxes", true, "Keep mining pickaxes (Antler, Bronze, Iron, Blackmetal, and modded pickaxes)."); KeepAxes = ((BaseUnityPlugin)this).Config.Bind<bool>("ToolTypes", "KeepAxes", true, "Keep woodcutting axes (Stone, Flint, Bronze, Iron, Blackmetal, Jotun Bane, battleaxes, and modded axes)."); KeepFishingRod = ((BaseUnityPlugin)this).Config.Bind<bool>("ToolTypes", "KeepFishingRod", true, "Keep fishing rods."); KeepButcherKnife = ((BaseUnityPlugin)this).Config.Bind<bool>("ToolTypes", "KeepButcherKnife", true, "Keep butcher knives."); IncludePrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("CustomFilters", "IncludePrefabs", "", "Comma-separated list of additional prefab names or localization tokens to treat as tools and keep on death (e.g. 'MyCustomTool,SpecialAxe')."); ExcludePrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("CustomFilters", "ExcludePrefabs", "", "Comma-separated list of prefab names or localization tokens to explicitly exclude from tool protection."); IncludePrefabs.SettingChanged += delegate { RefreshCustomFilters(); }; ExcludePrefabs.SettingChanged += delegate { RefreshCustomFilters(); }; RefreshCustomFilters(); _harmony = new Harmony("com.ayok.valheim.bluearchive"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim_Blue_Archive_Mod v1.1.0 loaded."); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private static void RefreshCustomFilters() { RebuildSet(IncludeList, (IncludePrefabs != null) ? IncludePrefabs.Value : null); RebuildSet(ExcludeList, (ExcludePrefabs != null) ? ExcludePrefabs.Value : null); } private static void RebuildSet(HashSet<string> target, string raw) { target.Clear(); if (string.IsNullOrEmpty(raw)) { return; } string[] array = raw.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { target.Add(StripClone(text)); } } } public static bool ShouldKeepItem(Player player, ItemData item) { if (item == null || item.m_shared == null) { return false; } if (item.m_shared.m_questItem) { return false; } if (KeepTools.Value && IsTool(item)) { return true; } if (KeepEquippedItems.Value && IsEquipped(player, item) && VanillaWillDropEquipped()) { return true; } return false; } public static bool IsEquipped(Player player, ItemData item) { if (item.m_equipped) { return true; } if ((Object)(object)player != (Object)null) { return ((Humanoid)player).IsItemEquiped(item); } return false; } public static bool VanillaWillDropEquipped() { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return true; } if (instance.GetGlobalKey((GlobalKeys)23)) { return false; } if (instance.GetGlobalKey((GlobalKeys)19)) { return false; } return true; } public static bool VanillaKeepsEntireInventory() { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance != (Object)null) { return instance.GetGlobalKey((GlobalKeys)23); } return false; } public static bool IsTool(ItemData item) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0062: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return false; } string prefabName = PrefabName(item); string sharedName = item.m_shared.m_name ?? ""; if (IsListed(ExcludeList, prefabName, sharedName)) { return false; } if (IsListed(IncludeList, prefabName, sharedName)) { return true; } ItemType itemType = item.m_shared.m_itemType; if (IsWearableOrNonToolType(itemType)) { return false; } if ((int)itemType == 19) { if (!KeepFishingRod.Value && IsFishingRod(item, prefabName, sharedName)) { return false; } if (!KeepButcherKnife.Value && IsButcherKnife(item, prefabName, sharedName)) { return false; } if (KeepBuildingAndFarmingTools.Value) { return true; } if (KeepFishingRod.Value && IsFishingRod(item, prefabName, sharedName)) { return true; } if (KeepButcherKnife.Value && IsButcherKnife(item, prefabName, sharedName)) { return true; } return false; } if (KeepPickaxes.Value && IsPickaxe(item, prefabName, sharedName)) { return true; } if (KeepAxes.Value && IsWoodcuttingAxe(item, prefabName, sharedName)) { return true; } if (KeepFishingRod.Value && IsFishingRod(item, prefabName, sharedName)) { return true; } if (KeepButcherKnife.Value && IsButcherKnife(item, prefabName, sharedName)) { return true; } return false; } private static bool IsWearableOrNonToolType(ItemType itemType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected I4, but got Unknown switch (itemType - 1) { case 0: case 1: case 3: case 4: case 5: case 6: case 8: case 9: case 10: case 11: case 12: case 14: case 16: case 17: case 20: case 22: case 23: return true; default: return false; } } private static bool IsPickaxe(ItemData item, string prefabName, string sharedName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)item.m_shared.m_skillType == 12) { return true; } return IsPickaxeName(prefabName, sharedName); } private static bool IsWoodcuttingAxe(ItemData item, string prefabName, string sharedName) { //IL_0011: 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) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if (IsPickaxeName(prefabName, sharedName)) { return false; } SkillType skillType = item.m_shared.m_skillType; if (((int)skillType == 7 || (int)skillType == 13) && item.m_shared.m_damages.m_chop > 0f) { return true; } return IsAxeName(prefabName, sharedName); } private static bool IsAxeName(string prefabName, string sharedName) { if (IsPickaxeName(prefabName, sharedName)) { return false; } if (StartsWithIgnoreCase(prefabName, "Axe") || StartsWithIgnoreCase(prefabName, "Battleaxe")) { return true; } if (ContainsIgnoreCase(sharedName, "$item_battleaxe") || ContainsIgnoreCase(sharedName, "battleaxe")) { return true; } if (ContainsIgnoreCase(sharedName, "$item_axe")) { return true; } return false; } private static bool IsPickaxeName(string prefabName, string sharedName) { if (StartsWithIgnoreCase(prefabName, "Pickaxe") || ContainsIgnoreCase(prefabName, "Pickaxe")) { return true; } if (ContainsIgnoreCase(sharedName, "$item_pickaxe") || ContainsIgnoreCase(sharedName, "pickaxe")) { return true; } return false; } private static bool IsFishingRod(ItemData item, string prefabName, string sharedName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)item.m_shared.m_skillType == 104) { return true; } if (!ContainsIgnoreCase(prefabName, "fishingrod") && !ContainsIgnoreCase(sharedName, "fishingrod")) { return ContainsIgnoreCase(sharedName, "$item_fishingrod"); } return true; } private static bool IsButcherKnife(ItemData item, string prefabName, string sharedName) { if (!ContainsIgnoreCase(prefabName, "butcher") && !ContainsIgnoreCase(sharedName, "butcher")) { return ContainsIgnoreCase(sharedName, "$item_butcher"); } return true; } private static bool IsListed(HashSet<string> list, string prefabName, string sharedName) { if (list.Count == 0) { return false; } if (!string.IsNullOrEmpty(prefabName) && list.Contains(prefabName)) { return true; } if (!string.IsNullOrEmpty(sharedName) && list.Contains(sharedName)) { return true; } return false; } private static string PrefabName(ItemData item) { if ((Object)(object)item.m_dropPrefab == (Object)null) { return ""; } return StripClone(((Object)item.m_dropPrefab).name); } private static string StripClone(string name) { if (string.IsNullOrEmpty(name)) { return ""; } if (name.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { return name.Substring(0, name.Length - "(Clone)".Length).Trim(); } return name; } private static bool StartsWithIgnoreCase(string value, string prefix) { if (!string.IsNullOrEmpty(value)) { return value.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); } return false; } private static bool ContainsIgnoreCase(string value, string token) { if (!string.IsNullOrEmpty(value)) { return value.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } }