using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using AzuEPI; using AzuEPI.Core.Slots; using AzuExtendedPlayerInventory; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ItemManager; using JetBrains.Annotations; using LocalizationManager; using Magic_Supremacy; using Microsoft.CodeAnalysis; using PieceManager; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: AssemblyFileVersion("3.0.6")] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("Magic_Supremacy")] [assembly: AssemblyCompany("Dreanegade")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("Magic_Supremacy")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.6.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<335460cb-33f0-4d8c-9458-c7990561a517>Embedded] internal sealed class <335460cb-33f0-4d8c-9458-c7990561a517>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<335460cb-33f0-4d8c-9458-c7990561a517>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <5ea91132-7291-4072-bba1-fdb04647c6e6>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <5ea91132-7291-4072-bba1-fdb04647c6e6>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <5ea91132-7291-4072-bba1-fdb04647c6e6>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [<335460cb-33f0-4d8c-9458-c7990561a517>Embedded] internal sealed class <702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContextAttribute : Attribute { public readonly byte Flag; public <702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContextAttribute(byte P_0) { Flag = P_0; } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static class ExtraTooltip { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private static class DevLog { public const bool Enabled = false; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public enum TooltipAttackSlot { Main, Secondary } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class TooltipLinkDef { public readonly string ItemPrefabName; public readonly TooltipAttackSlot AttackSlot; public readonly List Entries; public TooltipLinkDef(string itemPrefabName, TooltipAttackSlot attackSlot, string statusEffectPrefabName) { ItemPrefabName = itemPrefabName; AttackSlot = attackSlot; Entries = new List { new TooltipSELine(statusEffectPrefabName) }; } public TooltipLinkDef(string itemPrefabName, TooltipAttackSlot attackSlot, params TooltipEntry[] entries) { ItemPrefabName = itemPrefabName; AttackSlot = attackSlot; Entries = new List(entries); } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private abstract class TooltipEntry { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public abstract string Build(string itemPrefabName, int qualityLevel, float skillLevel); } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class TooltipSELine : TooltipEntry { private readonly string StatusEffectPrefabName; public TooltipSELine(string statusEffectPrefabName) { StatusEffectPrefabName = statusEffectPrefabName; } public override string Build(string itemPrefabName, int qualityLevel, float skillLevel) { StatusEffect val = FindStatusEffect(StatusEffectPrefabName); if ((Object)(object)val == (Object)null) { DLog("StatusEffect not found: " + StatusEffectPrefabName + " for item " + itemPrefabName + "."); return ""; } string text = BuildVanillaStatusEffectTooltip(val, qualityLevel, skillLevel); if (string.IsNullOrEmpty(text)) { DLog("Tooltip skipped for " + itemPrefabName + ": empty tooltip from " + StatusEffectPrefabName + "."); return ""; } return text; } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class TooltipTextLine : TooltipEntry { private readonly string TextKeyOrText; private readonly string Color; public TooltipTextLine(string textKeyOrText, string color = null) { TextKeyOrText = textKeyOrText; Color = color; } public override string Build(string itemPrefabName, int qualityLevel, float skillLevel) { return Colorize(Localize(TextKeyOrText), Color); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class TooltipInlineLine : TooltipEntry { private readonly List Parts; public TooltipInlineLine(params TooltipInlinePart[] parts) { Parts = new List(parts); } public override string Build(string itemPrefabName, int qualityLevel, float skillLevel) { StringBuilder stringBuilder = new StringBuilder(); foreach (TooltipInlinePart part in Parts) { if (part != null) { stringBuilder.Append(part.Build()); } } return stringBuilder.ToString(); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class TooltipInlinePart { private readonly string TextKeyOrText; private readonly string Color; public TooltipInlinePart(string textKeyOrText, string color = null) { TextKeyOrText = textKeyOrText; Color = color; } public string Build() { return Colorize(Localize(TextKeyOrText), Color); } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] private static class ItemData_GetTooltip_ExtraTooltipPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) try { if (item == null || item.m_shared == null) { return; } string itemPrefabName = GetItemPrefabName(item); if (string.IsNullOrEmpty(itemPrefabName)) { return; } List defsForItem = GetDefsForItem(itemPrefabName); if (defsForItem.Count != 0) { float skillLevel = 0f; if ((Object)(object)Player.m_localPlayer != (Object)null) { skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel(item.m_shared.m_skillType); } StringBuilder stringBuilder = new StringBuilder(); AppendEntriesForSlot(stringBuilder, defsForItem, TooltipAttackSlot.Main, qualityLevel, skillLevel); AppendEntriesForSlot(stringBuilder, defsForItem, TooltipAttackSlot.Secondary, qualityLevel, skillLevel); if (stringBuilder.Length <= 0) { DLog("Tooltip skipped for " + itemPrefabName + ": no valid extra tooltip was generated."); return; } __result = __result + "\n\n" + stringBuilder.ToString().TrimEnd(Array.Empty()); DLog("Extra tooltip added for " + itemPrefabName + "."); } } catch (Exception arg) { DLog($"ERROR while adding extra tooltip: {arg}"); } } } private const string MainAttackHeaderColor = "#FFC654"; private const string SecondaryAttackHeaderColor = "#FFC654"; private const string VanillaSENameColor = "orange"; private const string HealValueColor = "#C8FF6A"; private const string MainAttackKey = "$main_attack_DO"; private const string SecondaryAttackKey = "$secondary_attack_DO"; private static readonly List Defs = new List { new TooltipLinkDef("StaffTotemcallerTotemDO", TooltipAttackSlot.Main, "SE_TotemSlow_DO"), new TooltipLinkDef("StaffTotemcallerTotemDO", TooltipAttackSlot.Secondary, "SE_TotemBuff_DO"), new TooltipLinkDef("StaffTotemcallerBoomerangDO", TooltipAttackSlot.Secondary, "SE_TotemcallerOrbit_DO"), new TooltipLinkDef("StaffMushroomcallerMushroomDO", TooltipAttackSlot.Main, new TooltipTextLine("$aoe_trap_damage_DO"), new TooltipTextLine(" "), new TooltipSELine("SE_MushroomcallerSlow_DO")), new TooltipLinkDef("StaffMushroomcallerMushroomDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_light_DO")), new TooltipLinkDef("StaffDeathcallerBlasterDO", TooltipAttackSlot.Secondary, "SE_DeathcallerDebuff_DO"), new TooltipLinkDef("BowFrostcallerIceDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_trap_damage_DO"), new TooltipTextLine("$aoe_area_debuff_DO"), new TooltipTextLine(" "), new TooltipSELine("SE_FrostcallerAura_DO")), new TooltipLinkDef("StaffFrostcallerShotgunDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_spawn_DO"), new TooltipTextLine("$aoe_area_obstacle_DO")), new TooltipLinkDef("StaffFirecallerRingDO", TooltipAttackSlot.Secondary, "SE_FirecallerOrbit_DO"), new TooltipLinkDef("StaffStonecallerBurstDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_obstacle_DO")), new TooltipLinkDef("StaffWindcallerBuffDO", TooltipAttackSlot.Main, "SE_WindcallerShield_DO"), new TooltipLinkDef("StaffWindcallerBuffDO", TooltipAttackSlot.Secondary, "SE_WindcallerPetal_DO"), new TooltipLinkDef("StaffLightcallerHealDO", TooltipAttackSlot.Main, new TooltipTextLine("$aoe_trap_heal_DO"), new TooltipInlineLine(new TooltipInlinePart("$heal_DO"), new TooltipInlinePart(": "), new TooltipInlinePart("40", "orange"))), new TooltipLinkDef("StaffLightcallerHealDO", TooltipAttackSlot.Secondary, "SE_LightcallerHeal_DO"), new TooltipLinkDef("StaffLightcallerSphereDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_light_DO"), new TooltipTextLine("$aoe_area_damage_DO")), new TooltipLinkDef("StaffStormcallerSphereDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_trap_damage_DO")), new TooltipLinkDef("StaffStormcallerShockerDO", TooltipAttackSlot.Secondary, "SE_StormcallerOrbit_DO"), new TooltipLinkDef("StaffBloodcallerHealDO", TooltipAttackSlot.Main, "SE_BloodcallerHeal_DO"), new TooltipLinkDef("StaffBloodcallerHealDO", TooltipAttackSlot.Secondary, "SE_BloodBuff_DO"), new TooltipLinkDef("StaffBloodcallerShotgunDO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_damage_DO"), new TooltipTextLine(" "), new TooltipTextLine("$aoe_area_debuff_DO"), new TooltipTextLine(" "), new TooltipSELine("SE_BloodDebuff_DO")) }; private static void AppendEntriesForSlot(StringBuilder sb, List itemDefs, TooltipAttackSlot slot, int qualityLevel, float skillLevel) { bool flag = false; foreach (TooltipLinkDef itemDef in itemDefs) { if (itemDef.AttackSlot != slot) { continue; } string value = BuildDefTooltip(itemDef, qualityLevel, skillLevel); if (string.IsNullOrEmpty(value)) { continue; } if (!flag) { if (sb.Length > 0) { sb.Append("\n\n"); } sb.Append(GetAttackHeader(slot)); sb.Append("\n"); flag = true; } else { sb.Append("\n\n"); } sb.Append(value); } } private static string BuildDefTooltip(TooltipLinkDef def, int qualityLevel, float skillLevel) { if (def == null || def.Entries == null || def.Entries.Count == 0) { return ""; } StringBuilder stringBuilder = new StringBuilder(); foreach (TooltipEntry entry in def.Entries) { if (entry == null) { continue; } string value = entry.Build(def.ItemPrefabName, qualityLevel, skillLevel); if (!string.IsNullOrEmpty(value)) { if (stringBuilder.Length > 0) { stringBuilder.Append("\n"); } stringBuilder.Append(value); } } return stringBuilder.ToString(); } private static string BuildVanillaStatusEffectTooltip(StatusEffect statusEffect, int qualityLevel, float skillLevel) { if ((Object)(object)statusEffect == (Object)null) { return ""; } statusEffect.SetLevel(qualityLevel, skillLevel); return "" + statusEffect.m_name + "\n" + statusEffect.GetTooltipString(); } private static string GetAttackHeader(TooltipAttackSlot slot) { return slot switch { TooltipAttackSlot.Main => Colorize(Localize("$main_attack_DO"), "#FFC654"), TooltipAttackSlot.Secondary => Colorize(Localize("$secondary_attack_DO"), "#FFC654"), _ => "", }; } private static string Colorize(string text, string color) { if (string.IsNullOrEmpty(text)) { return ""; } if (string.IsNullOrEmpty(color)) { return text; } return "" + text + ""; } private static string Localize(string keyOrText) { if (string.IsNullOrEmpty(keyOrText)) { return ""; } if (Localization.instance == null) { return keyOrText; } if (keyOrText.StartsWith("$")) { return Localization.instance.Localize(keyOrText); } return keyOrText; } private static List GetDefsForItem(string itemPrefabName) { List list = new List(); foreach (TooltipLinkDef def in Defs) { if (def.ItemPrefabName == itemPrefabName) { list.Add(def); } } return list; } private static StatusEffect FindStatusEffect(string statusEffectPrefabName) { if ((Object)(object)ObjectDB.instance == (Object)null) { return null; } foreach (StatusEffect statusEffect in ObjectDB.instance.m_StatusEffects) { if (!((Object)(object)statusEffect == (Object)null)) { if (((Object)statusEffect).name == statusEffectPrefabName) { return statusEffect; } if (Utils.GetPrefabName(((Object)statusEffect).name) == statusEffectPrefabName) { return statusEffect; } } } return null; } private static string GetItemPrefabName(ItemData item) { if (item == null) { return ""; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return Utils.GetPrefabName(((Object)item.m_dropPrefab).name); } if (item.m_shared != null && !string.IsNullOrEmpty(item.m_shared.m_name)) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(item.m_shared.m_name) : null); if ((Object)(object)val != (Object)null) { return Utils.GetPrefabName(((Object)val).name); } } return ""; } private static void DLog(string message) { } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public static class ItemDropExtendedStats { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private static class DevLog { public const bool Enabled = false; public const bool Skill = false; public const bool CarryWeight = false; public const bool MovementSpeed = false; public const bool Adrenaline = false; public const bool Tooltips = false; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public enum ExtendedStatType { SkillLevelBonus, CarryWeightBonus, MovementSpeedModifier, AdrenalineGainModifier } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class ExtendedStatEntry { public string PrefabName; public ExtendedStatType StatType; public SkillType SkillType; public float Value; public ExtendedStatEntry(string prefab, ExtendedStatType statType, float value) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) PrefabName = prefab; StatType = statType; SkillType = (SkillType)0; Value = value; } public ExtendedStatEntry(string prefab, ExtendedStatType statType, SkillType skillType, float value) { //IL_0015: 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) PrefabName = prefab; StatType = statType; SkillType = skillType; Value = value; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(Skills), "GetSkillLevel")] public static class Skills_GetSkillLevel_ItemDropExtendedStatsPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(Skills __instance, SkillType skillType, ref float __result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return; } Player player = __instance.m_player; if (!((Object)(object)player == (Object)null) && (int)skillType != 0) { float equippedSkillBonus = GetEquippedSkillBonus(player, skillType); if (equippedSkillBonus != 0f) { __result += equippedSkillBonus; DLogSkill($"Applied item-based skill bonus to {skillType}: +{equippedSkillBonus}, result={__result}"); } } } catch (Exception ex) { LogError("Exception in Skills_GetSkillLevel_ItemDropExtendedStatsPatch: " + ex); } } } [HarmonyPatch(typeof(Player), "GetMaxCarryWeight")] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public static class Player_GetMaxCarryWeight_ItemDropExtendedStatsPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(Player __instance, ref float __result) { try { if (!((Object)(object)__instance == (Object)null)) { float equippedBonusByType = GetEquippedBonusByType(__instance, ExtendedStatType.CarryWeightBonus); if (equippedBonusByType != 0f) { __result += equippedBonusByType; DLogCarry($"Applied item-based carry weight bonus: +{equippedBonusByType}, result={__result}"); } } } catch (Exception ex) { LogError("Exception in Player_GetMaxCarryWeight_ItemDropExtendedStatsPatch: " + ex); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")] public static class SEMan_ApplyStatusEffectSpeedMods_ItemDropExtendedStatsPatch { private static void Prefix(ref float speed, out float __state) { __state = speed; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(SEMan __instance, ref float speed, Vector3 dir, float __state) { try { Player playerFromSEMan = GetPlayerFromSEMan(__instance); if ((Object)(object)playerFromSEMan == (Object)null) { return; } float equippedBonusByType = GetEquippedBonusByType(playerFromSEMan, ExtendedStatType.MovementSpeedModifier); if (equippedBonusByType != 0f) { speed += __state * equippedBonusByType; if (speed < 0f) { speed = 0f; } DLogMovement($"Applied item-based movement speed modifier: {equippedBonusByType * 100f:+0;-0}% baseSpeed={__state}, result={speed}"); } } catch (Exception ex) { LogError("Exception in SEMan_ApplyStatusEffectSpeedMods_ItemDropExtendedStatsPatch: " + ex); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(SEMan), "ModifyAdrenaline")] public static class SEMan_ModifyAdrenaline_ItemDropExtendedStatsPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(SEMan __instance, float baseValue, ref float use) { try { Player playerFromSEMan = GetPlayerFromSEMan(__instance); if (!((Object)(object)playerFromSEMan == (Object)null)) { float equippedBonusByType = GetEquippedBonusByType(playerFromSEMan, ExtendedStatType.AdrenalineGainModifier); if (equippedBonusByType != 0f) { use += baseValue * equippedBonusByType; DLogAdrenaline($"Applied item-based adrenaline gain modifier: {equippedBonusByType * 100f:+0;-0}% baseValue={baseValue}, result={use}"); } } } catch (Exception ex) { LogError("Exception in SEMan_ModifyAdrenaline_ItemDropExtendedStatsPatch: " + ex); } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [HarmonyPatch] public static class ItemData_StaticGetTooltip_ItemDropExtendedStatsPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[5] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) }, (Type[])null); } private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) try { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return; } string name = ((Object)item.m_dropPrefab).name; DLogTooltip($"Static GetTooltip Postfix called for {name}, q={qualityLevel}, crafting={crafting}, worldLevel={worldLevel}, stackOverride={stackOverride}"); string text = BuildExtendedTooltipBlock(item); if (string.IsNullOrEmpty(text)) { return; } float num = 0f; if ((Object)(object)Player.m_localPlayer != (Object)null) { num = ((Character)Player.m_localPlayer).GetSkillLevel(item.m_shared.m_skillType); } string statusEffectTooltip = item.GetStatusEffectTooltip(qualityLevel, num); string chainTooltip = item.GetChainTooltip(qualityLevel, num); string setStatusEffectTooltip = item.GetSetStatusEffectTooltip(qualityLevel, num); int num2 = -1; if (!string.IsNullOrEmpty(statusEffectTooltip)) { int num3 = __result.IndexOf(statusEffectTooltip, StringComparison.Ordinal); if (num3 >= 0) { num2 = ((num3 - 2 >= 0 && __result.Substring(num3 - 2, 2) == "\n\n") ? (num3 - 2) : num3); } } if (num2 < 0 && !string.IsNullOrEmpty(chainTooltip)) { int num4 = __result.IndexOf(chainTooltip, StringComparison.Ordinal); if (num4 >= 0) { num2 = ((num4 - 2 >= 0 && __result.Substring(num4 - 2, 2) == "\n\n") ? (num4 - 2) : num4); } } if (num2 < 0) { int num5 = __result.IndexOf("\n$item_eitrregen_modifier:", StringComparison.Ordinal); if (num5 >= 0) { num2 = num5; } } if (num2 < 0 && !string.IsNullOrEmpty(setStatusEffectTooltip)) { int num6 = __result.IndexOf("\n\n$item_seteffect", StringComparison.Ordinal); if (num6 >= 0) { num2 = num6; } } if (num2 < 0) { int num7 = __result.IndexOf("\n$item_fulladrenaline:", StringComparison.Ordinal); if (num7 >= 0) { num2 = num7; } } if (num2 >= 0) { DLogTooltip("Inserting extended ItemDrop stats before special/effect section for " + name); __result = __result.Insert(num2, text); } else { DLogTooltip("No special/effect section found, appending extended ItemDrop stats at end for " + name); __result += text; } } catch (Exception ex) { LogError("Exception in ItemData_StaticGetTooltip_ItemDropExtendedStatsPatch: " + ex); } } } public static readonly List ExtendedStatsConfig = new List { new ExtendedStatEntry("ArmorInspirationTrinketMountainDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 2f), new ExtendedStatEntry("ArmorInspirationTrinketPlainsDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 2f), new ExtendedStatEntry("ArmorInspirationTrinketMistlandsDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 2f), new ExtendedStatEntry("ArmorInspirationTrinketAshlandsDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 2f), new ExtendedStatEntry("ArmorMushroomcallerChestDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 2f), new ExtendedStatEntry("ArmorTotemcallerChestDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 2f), new ExtendedStatEntry("ArmorDeathcallerLegsDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 4f), new ExtendedStatEntry("ArmorFrostcallerHelmetDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 6f), new ExtendedStatEntry("ArmorFirecallerChestDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 8f), new ExtendedStatEntry("ArmorStonecallerChestDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 8f), new ExtendedStatEntry("ArmorWindcallerLegsDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 10f), new ExtendedStatEntry("ArmorLightcallerLegsDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 10f), new ExtendedStatEntry("ArmorStormcallerHelmetDO", ExtendedStatType.SkillLevelBonus, (SkillType)9, 12f), new ExtendedStatEntry("ArmorBloodcallerHelmetDO", ExtendedStatType.SkillLevelBonus, (SkillType)10, 12f), new ExtendedStatEntry("ArmorTotemcallerCapeDO", ExtendedStatType.MovementSpeedModifier, 0.04f), new ExtendedStatEntry("ArmorMushroomcallerCapeDO", ExtendedStatType.CarryWeightBonus, 20f), new ExtendedStatEntry("ArmorFirecallerCapeDO", ExtendedStatType.AdrenalineGainModifier, 0.15f), new ExtendedStatEntry("ArmorStormcallerCapeDO", ExtendedStatType.MovementSpeedModifier, 0.09f), new ExtendedStatEntry("ArmorBloodcallerCapeDO", ExtendedStatType.SkillLevelBonus, (SkillType)10, 20f) }; private static FieldRef _semanCharacterRef; private static bool _semanInit; private static void DLogSkill(string msg) { } private static void DLogCarry(string msg) { } private static void DLogMovement(string msg) { } private static void DLogAdrenaline(string msg) { } private static void DLogTooltip(string msg) { } private static void LogError(string msg) { } private static void EnsureSEManInit() { if (!_semanInit) { _semanInit = true; _semanCharacterRef = AccessTools.FieldRefAccess("m_character"); } } private static Player GetPlayerFromSEMan(SEMan seman) { if (seman == null) { return null; } try { EnsureSEManInit(); Character obj = _semanCharacterRef.Invoke(seman); return (Player)(object)((obj is Player) ? obj : null); } catch (Exception ex) { LogError("Exception in GetPlayerFromSEMan: " + ex); return null; } } private static float GetEquippedSkillBonus(Player player, SkillType requestedSkill) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return 0f; } float num = 0f; try { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return 0f; } List equippedItems = inventory.GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val = equippedItems[i]; if (val == null || (Object)(object)val.m_dropPrefab == (Object)null) { continue; } string name = ((Object)val.m_dropPrefab).name; for (int j = 0; j < ExtendedStatsConfig.Count; j++) { ExtendedStatEntry extendedStatEntry = ExtendedStatsConfig[j]; if (extendedStatEntry.StatType == ExtendedStatType.SkillLevelBonus && string.Equals(name, extendedStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase) && ((int)extendedStatEntry.SkillType == 999 || extendedStatEntry.SkillType == requestedSkill)) { num += extendedStatEntry.Value; DLogSkill($"Matched {name} for {requestedSkill}: +{extendedStatEntry.Value}"); } } } } catch (Exception ex) { LogError("Exception in GetEquippedSkillBonus: " + ex); } return num; } private static float GetEquippedBonusByType(Player player, ExtendedStatType statType) { if ((Object)(object)player == (Object)null) { return 0f; } float num = 0f; try { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return 0f; } List equippedItems = inventory.GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val = equippedItems[i]; if (val == null || (Object)(object)val.m_dropPrefab == (Object)null) { continue; } string name = ((Object)val.m_dropPrefab).name; for (int j = 0; j < ExtendedStatsConfig.Count; j++) { ExtendedStatEntry extendedStatEntry = ExtendedStatsConfig[j]; if (extendedStatEntry.StatType == statType && string.Equals(name, extendedStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase)) { num += extendedStatEntry.Value; } } } } catch (Exception ex) { LogError($"Exception in GetEquippedBonusByType({statType}): " + ex); } return num; } private static string BuildExtendedTooltipBlock(ItemData item) { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return string.Empty; } string name = ((Object)item.m_dropPrefab).name; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < ExtendedStatsConfig.Count; i++) { ExtendedStatEntry extendedStatEntry = ExtendedStatsConfig[i]; if (!string.Equals(name, extendedStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase)) { continue; } switch (extendedStatEntry.StatType) { case ExtendedStatType.SkillLevelBonus: { string text = "$skill_" + ((object)(SkillType)(ref extendedStatEntry.SkillType)).ToString().ToLower(); string arg = text; if (Localization.instance != null) { arg = Localization.instance.Localize(text); } stringBuilder.AppendFormat("\n{0} {1}", arg, extendedStatEntry.Value.ToString("+0;-0")); break; } case ExtendedStatType.CarryWeightBonus: stringBuilder.AppendFormat("\n$se_max_carryweight: {0}", extendedStatEntry.Value.ToString("+0;-0")); break; case ExtendedStatType.MovementSpeedModifier: stringBuilder.AppendFormat("\n$item_movement_modifier: {0}%", (extendedStatEntry.Value * 100f).ToString("+0;-0")); break; case ExtendedStatType.AdrenalineGainModifier: stringBuilder.AppendFormat("\n$se_adrenaline: {0}%", (extendedStatEntry.Value * 100f).ToString("+0;-0")); break; } } return stringBuilder.ToString(); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static class TooltipColor { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class StatusEffectTextColorDef { public readonly string StatusEffectPrefabName; public readonly string TooltipColor; public StatusEffectTextColorDef(string statusEffectPrefabName, string tooltipColor) { StatusEffectPrefabName = statusEffectPrefabName; TooltipColor = tooltipColor; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(SE_Stats), "GetTooltipString")] private static class SE_Stats_GetTooltipString_TooltipColorPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(SE_Stats __instance, ref string __result) { try { if (!((Object)(object)__instance == (Object)null) && !string.IsNullOrEmpty(__result)) { StatusEffectTextColorDef statusEffectTextColorDef = GetStatusEffectTextColorDef(Utils.GetPrefabName(((Object)__instance).name)); if (statusEffectTextColorDef != null && !string.IsNullOrEmpty(statusEffectTextColorDef.TooltipColor)) { ApplyTooltipDescriptionColor(__instance, statusEffectTextColorDef.TooltipColor, ref __result); } } } catch (Exception ex) { Debug.LogError((object)("[TooltipColor] ERROR: " + ex)); } } } private static readonly List StatusEffectTextColorDefs = new List { new StatusEffectTextColorDef("SE_MushroomcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_TotemcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_DeathcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_FrostcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_FirecallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_StonecallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_WindcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_LightcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_StormcallerArmor_DO", "#f0bdff"), new StatusEffectTextColorDef("SE_BloodcallerArmor_DO", "#f0bdff") }; private static void ApplyTooltipDescriptionColor(SE_Stats se, string color, ref string result) { if ((Object)(object)se == (Object)null || string.IsNullOrEmpty(color)) { return; } string tooltip = ((StatusEffect)se).m_tooltip; if (!string.IsNullOrEmpty(tooltip)) { if (result.StartsWith(tooltip + "\n\n")) { result = Colorize(tooltip, color) + result.Substring(tooltip.Length); } else if (result.StartsWith(tooltip + "\n")) { result = Colorize(tooltip, color) + result.Substring(tooltip.Length); } else if (result == tooltip) { result = Colorize(tooltip, color); } } } private static StatusEffectTextColorDef GetStatusEffectTextColorDef(string sePrefabName) { if (string.IsNullOrEmpty(sePrefabName)) { return null; } foreach (StatusEffectTextColorDef statusEffectTextColorDef in StatusEffectTextColorDefs) { if (statusEffectTextColorDef != null && statusEffectTextColorDef.StatusEffectPrefabName == sePrefabName) { return statusEffectTextColorDef; } } return null; } private static string Colorize(string text, string color) { if (string.IsNullOrEmpty(text)) { return ""; } if (string.IsNullOrEmpty(color)) { return text; } return "" + text + ""; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] internal sealed class ConfigurationManagerAttributes { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func ObjToStr; public Func StrToObj; } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static class ExtraStats { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private static class DevLog { public const bool Enabled = false; public const bool AttackSpeed = false; public const bool WetImmune = false; public const bool Tooltips = false; public const bool FoodStats = false; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public enum ExtraStatType { Health, Stamina, Eitr, AttackSpeed, WetImmune } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public enum ExtraSourceType { ItemDrop, StatusEffect } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class ExtraStatEntry { public string PrefabName; public ExtraStatType StatType; public float Value; public float? DisplayValue; public ExtraSourceType SourceType; public ExtraStatEntry(string prefab, ExtraStatType stat, float value, ExtraSourceType source) { PrefabName = prefab; StatType = stat; Value = value; DisplayValue = null; SourceType = source; } public ExtraStatEntry(string prefab, ExtraStatType stat, float value, float? displayValue, ExtraSourceType source) { PrefabName = prefab; StatType = stat; Value = value; DisplayValue = displayValue; SourceType = source; } } [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public static class Player_GetTotalFoodValue_ExtraStatsPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr) { if ((Object)(object)__instance == (Object)null) { return; } float num = 0f; float num2 = 0f; float num3 = 0f; try { Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory != null) { foreach (ItemData equippedItem in inventory.GetEquippedItems()) { if (equippedItem != null && !((Object)(object)equippedItem.m_dropPrefab == (Object)null)) { string name = ((Object)equippedItem.m_dropPrefab).name; GetItemDropBonusesForPrefab(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var _); if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f) { num += extraHp; num2 += extraStamina; num3 += extraEitr; DLogFood($"ItemDrop matched for food stats: {name} → +HP {extraHp}, +Stamina {extraStamina}, +Eitr {extraEitr}"); } } } } if (((Character)__instance).m_seman != null && ((Character)__instance).m_seman.m_statusEffects != null) { foreach (StatusEffect statusEffect in ((Character)__instance).m_seman.m_statusEffects) { if (!((Object)(object)statusEffect == (Object)null)) { string name2 = ((Object)statusEffect).name; GetStatusEffectBonuses(name2, out var extraHp2, out var extraStamina2, out var extraEitr2, out var _, out var _); if (extraHp2 != 0f || extraStamina2 != 0f || extraEitr2 != 0f) { num += extraHp2; num2 += extraStamina2; num3 += extraEitr2; string prefabName = Utils.GetPrefabName(name2); DLogFood($"StatusEffect matched for food stats: {name2} (clean={prefabName}) → +HP {extraHp2}, +Stamina {extraStamina2}, +Eitr {extraEitr2}"); } } } } } catch (Exception ex) { LogError("Exception in ExtraStats Player.GetTotalFoodValue Postfix: " + ex); } if (num != 0f || num2 != 0f || num3 != 0f) { DLogFood($"Total food bonuses applied to player: +HP {num}, +Stamina {num2}, +Eitr {num3}"); hp += num; stamina += num2; eitr += num3; } } } [HarmonyPatch] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public static class ItemData_StaticGetTooltip_ExtraStatsPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[5] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) }, (Type[])null); } private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) try { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return; } string name = ((Object)item.m_dropPrefab).name; DLogTooltip($"Static GetTooltip Postfix called for {name}, q={qualityLevel}, crafting={crafting}, worldLevel={worldLevel}, stackOverride={stackOverride}"); GetItemDropBonusesForPrefab(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var displayAttackSpeedPercent, out var wetImmune); if (extraHp == 0f && extraStamina == 0f && extraEitr == 0f && displayAttackSpeedPercent == 0f && !wetImmune) { return; } string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune); if (string.IsNullOrEmpty(text)) { return; } float num = 0f; if ((Object)(object)Player.m_localPlayer != (Object)null) { num = ((Character)Player.m_localPlayer).GetSkillLevel(item.m_shared.m_skillType); } string statusEffectTooltip = item.GetStatusEffectTooltip(qualityLevel, num); string chainTooltip = item.GetChainTooltip(qualityLevel, num); string setStatusEffectTooltip = item.GetSetStatusEffectTooltip(qualityLevel, num); int num2 = -1; if (!string.IsNullOrEmpty(statusEffectTooltip)) { int num3 = __result.IndexOf(statusEffectTooltip, StringComparison.Ordinal); if (num3 >= 0) { num2 = ((num3 - 2 >= 0 && __result.Substring(num3 - 2, 2) == "\n\n") ? (num3 - 2) : num3); } } if (num2 < 0 && !string.IsNullOrEmpty(chainTooltip)) { int num4 = __result.IndexOf(chainTooltip, StringComparison.Ordinal); if (num4 >= 0) { num2 = ((num4 - 2 >= 0 && __result.Substring(num4 - 2, 2) == "\n\n") ? (num4 - 2) : num4); } } if (num2 < 0) { int num5 = __result.IndexOf("\n$item_eitrregen_modifier:", StringComparison.Ordinal); if (num5 >= 0) { num2 = num5; } } if (num2 < 0 && !string.IsNullOrEmpty(setStatusEffectTooltip)) { int num6 = __result.IndexOf("\n\n$item_seteffect", StringComparison.Ordinal); if (num6 >= 0) { num2 = num6; } } if (num2 < 0) { int num7 = __result.IndexOf("\n$item_fulladrenaline:", StringComparison.Ordinal); if (num7 >= 0) { num2 = num7; } } if (num2 >= 0) { DLogTooltip("Inserting ItemDrop extras before special/effect section for " + name); __result = __result.Insert(num2, text); } else { DLogTooltip("No special/effect section found, appending ItemDrop extras at end for " + name); __result += text; } } catch (Exception ex) { LogError("Exception in ItemData_StaticGetTooltip_ExtraStatsPatch: " + ex); } } } [HarmonyPatch(typeof(SE_Stats), "GetTooltipString")] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public static class SE_Stats_GetTooltipString_ExtraStatsPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(SE_Stats __instance, ref string __result) { try { if ((Object)(object)__instance == (Object)null) { return; } string name = ((Object)__instance).name; string prefabName = Utils.GetPrefabName(name); DLogTooltip("SE GetTooltipString for " + name + " (clean=" + prefabName + ")"); GetStatusEffectBonuses(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var displayAttackSpeedPercent, out var wetImmune); if (extraHp == 0f && extraStamina == 0f && extraEitr == 0f && displayAttackSpeedPercent == 0f && !wetImmune) { return; } string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune); if (!string.IsNullOrEmpty(text)) { if (text.StartsWith("\n")) { text = text.Substring(1); } DLogTooltip($"Appending SE extras for {name} (clean={prefabName}): HP {extraHp}, Stamina {extraStamina}, Eitr {extraEitr}, AttackSpeed(Display)% {displayAttackSpeedPercent}, WetImmune {wetImmune}"); __result += text; } } catch (Exception ex) { LogError("Exception in SE_Stats_GetTooltipString_ExtraStatsPatch: " + ex); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private sealed class HumanoidState { public float DesiredSpeed = 1f; public float LastAppliedSpeed = 1f; public bool HasDesiredSpeed; public bool WasInAttack; public int ActiveAttackDepth; public float ActiveAttackMul = 1f; } [HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[] { typeof(Character), typeof(bool) })] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public static class Humanoid_StartAttack_AttackSpeedPatch { [HarmonyPostfix] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(Humanoid __instance, Character target, bool secondaryAttack, ref bool __result) { EnsureAttackInit(); if (!__result) { return; } HumanoidState attackState = GetAttackState(__instance); float num = ComputeTotalAttackSpeedPercentForHumanoid(__instance); if (num == 0f) { attackState.DesiredSpeed = 1f; attackState.HasDesiredSpeed = false; ApplyAnimSpeed(__instance, attackState, 1f); attackState.ActiveAttackDepth = 0; attackState.ActiveAttackMul = 1f; return; } float num2 = 1f + num / 100f; if (num2 <= 0f || float.IsNaN(num2) || float.IsInfinity(num2)) { attackState.DesiredSpeed = 1f; attackState.HasDesiredSpeed = false; ApplyAnimSpeed(__instance, attackState, 1f); attackState.ActiveAttackDepth = 0; attackState.ActiveAttackMul = 1f; } else { attackState.DesiredSpeed = num2; attackState.HasDesiredSpeed = true; ApplyAnimSpeed(__instance, attackState, num2); attackState.ActiveAttackDepth++; attackState.ActiveAttackMul = num2; DLogAttackSpeed($"StartAttack: total AttackSpeed%={num} → mul={num2} (activeDepth={attackState.ActiveAttackDepth})"); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(Attack), "Stop")] public static class Attack_Stop_AttackSpeedResetPatch { [HarmonyPostfix] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(Attack __instance) { try { EnsureAttackInit(); if (__instance != null) { Humanoid character = __instance.m_character; if (!((Object)(object)character == (Object)null)) { ResetForHumanoid(character); DLogAttackSpeed("Attack.Stop: ResetForHumanoid"); } } } catch (Exception) { } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(Humanoid), "UpdateAttack")] public static class Humanoid_UpdateAttack_AttackSpeedDtPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPrefix] private static void Prefix(Humanoid __instance, ref float dt) { try { EnsureAttackInit(); if ((Object)(object)__instance == (Object)null) { return; } HumanoidState attackState = GetAttackState(__instance); if (attackState.ActiveAttackDepth > 0) { float activeAttackMul = attackState.ActiveAttackMul; if (!(activeAttackMul <= 0f) && !float.IsNaN(activeAttackMul) && !float.IsInfinity(activeAttackMul)) { dt *= activeAttackMul; } } } catch (Exception ex) { LogError("Exception in Humanoid_UpdateAttack_AttackSpeedDtPatch: " + ex); } } } [HarmonyPatch(typeof(Humanoid), "CustomFixedUpdate")] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public static class Humanoid_CustomFixedUpdate_AttackSpeedPatch { [HarmonyPostfix] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(Humanoid __instance, float fixedDeltaTime) { EnsureAttackInit(); HumanoidState attackState = GetAttackState(__instance); bool flag = ((Character)__instance).InAttack(); if (flag) { if (attackState.HasDesiredSpeed) { ApplyAnimSpeed(__instance, attackState, attackState.DesiredSpeed); } else { ApplyAnimSpeed(__instance, attackState, 1f); } } else if (attackState.WasInAttack) { ApplyAnimSpeed(__instance, attackState, 1f); attackState.HasDesiredSpeed = false; attackState.DesiredSpeed = 1f; } attackState.WasInAttack = flag; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(Character), "RPC_Stagger")] public static class Character_RPC_Stagger_AttackSpeedResetPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPostfix] private static void Postfix(Character __instance, long sender, Vector3 forceDirection) { try { EnsureAttackInit(); Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null); if (!((Object)(object)val == (Object)null)) { ResetForHumanoid(val); } } catch (Exception) { } } } [HarmonyPatch(typeof(Character), "OnDeath")] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public static class Character_OnDeath_AttackSpeedResetPatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPostfix] private static void Postfix(Character __instance) { try { EnsureAttackInit(); Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null); if (!((Object)(object)val == (Object)null)) { ResetForHumanoid(val); } } catch (Exception) { } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(Character), "FreezeFrame")] public static class Character_FreezeFrame_AttackSpeedScalePatch { [HarmonyPrefix] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Prefix(Character __instance, ref float duration) { try { EnsureAttackInit(); if ((Object)(object)__instance == (Object)null || Mathf.Abs(duration - 0.15f) > 0.01f) { return; } Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } HumanoidState attackState = GetAttackState(val); if (!attackState.HasDesiredSpeed) { return; } float desiredSpeed = attackState.DesiredSpeed; if (!(desiredSpeed <= 1.001f) && !float.IsNaN(desiredSpeed) && !float.IsInfinity(desiredSpeed)) { float num = duration / desiredSpeed; if (num < 0.03f) { num = 0.03f; } DLogAttackSpeed($"FreezeFrame scale: {duration:F3} -> {num:F3} (mul={desiredSpeed:F3})"); duration = num; } } catch (Exception ex) { LogError("Exception in Character_FreezeFrame_AttackSpeedScalePatch: " + ex); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(CharacterAnimEvent), "UpdateFreezeFrame")] public static class CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch { [HarmonyPostfix] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static void Postfix(CharacterAnimEvent __instance, float dt) { try { EnsureAttackInit(); if ((Object)(object)__instance == (Object)null) { return; } Character componentInParent = ((Component)__instance).GetComponentInParent(); Humanoid val = (Humanoid)(object)((componentInParent is Humanoid) ? componentInParent : null); if (!((Object)(object)val == (Object)null)) { HumanoidState attackState = GetAttackState(val); if (attackState.HasDesiredSpeed && (attackState.ActiveAttackDepth > 0 || ((Character)val).InAttack())) { ApplyAnimSpeed(val, attackState, attackState.DesiredSpeed); } else { ApplyAnimSpeed(val, attackState, 1f); } } } catch (Exception ex) { LogError("Exception in CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch: " + ex); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(float) })] public static class SEMan_AddStatusEffect_ByHash_WetImmunePatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPrefix] private static bool Prefix(SEMan __instance, int nameHash, bool resetTime, int itemLevel, float skillLevel) { try { EnsureWetInit(); if (nameHash != SEMan.s_statusEffectWet) { return true; } Character val = null; try { val = _semanCharacterRef.Invoke(__instance); } catch (Exception) { val = null; } if ((Object)(object)val != (Object)null && HasWetImmune(val)) { DLogWet("Blocked Wet (AddStatusEffect by hash) due to WetImmune"); return false; } } catch (Exception ex2) { LogError("Exception in SEMan_AddStatusEffect_ByHash_WetImmunePatch: " + ex2); } return true; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(StatusEffect), typeof(bool), typeof(int), typeof(float) })] public static class SEMan_AddStatusEffect_BySE_WetImmunePatch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPrefix] private static bool Prefix(SEMan __instance, StatusEffect statusEffect, bool resetTime, int itemLevel, float skillLevel, ref StatusEffect __result) { try { if ((Object)(object)statusEffect == (Object)null) { return true; } if (statusEffect.NameHash() != SEMan.s_statusEffectWet) { return true; } Character character = statusEffect.m_character; if ((Object)(object)character != (Object)null && HasWetImmune(character)) { DLogWet("Blocked Wet (AddStatusEffect by SE) due to WetImmune"); __result = null; return false; } } catch (Exception ex) { LogError("Exception in SEMan_AddStatusEffect_BySE_WetImmunePatch: " + ex); } return true; } } public static bool DEBUG = false; public static readonly List ExtraStatsConfig = new List { new ExtraStatEntry("ArmorInspirationTrinketPlainsDO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorInspirationTrinketMistlandsDO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorInspirationTrinketAshlandsDO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorMushroomcallerLegsDO", ExtraStatType.Eitr, 5f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorTotemcallerLegsDO", ExtraStatType.Health, 5f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorDeathcallerHelmetDO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorFrostcallerChestDO", ExtraStatType.Eitr, 15f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorFirecallerLegsDO", ExtraStatType.Eitr, 20f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorStonecallerLegsDO", ExtraStatType.Eitr, 20f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorWindcallerHelmetDO", ExtraStatType.Eitr, 25f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorLightcallerHelmetDO", ExtraStatType.Eitr, 25f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorStormcallerChestDO", ExtraStatType.Eitr, 30f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorBloodcallerChestDO", ExtraStatType.Health, 20f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorFrostcallerCapeDO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorWindcallerCapeDO", ExtraStatType.Stamina, 20f, ExtraSourceType.ItemDrop), new ExtraStatEntry("ArmorBloodcallerCapeDO", ExtraStatType.Health, 50f, ExtraSourceType.ItemDrop), new ExtraStatEntry("SE_MushroomcallerBelt_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_DeathcallerBelt_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_FrostcallerBelt_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_FirecallerBelt_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_StonecallerBelt_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_LightcallerBelt_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_StormcallerBelt_DO", ExtraStatType.Eitr, 25f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_TotemcallerBelt_DO", ExtraStatType.Health, 10f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_WindcallerBelt_DO", ExtraStatType.Stamina, 15f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_BloodBuff_DO", ExtraStatType.Health, 50f, ExtraSourceType.StatusEffect) }; private static readonly ConditionalWeakTable _attackState = new ConditionalWeakTable(); private static FieldRef _zanimRef; private static bool _attackInit; private const float HitFreeze_Default = 0.15f; private const float HitFreeze_Epsilon = 0.01f; private const float HitFreeze_Min = 0.03f; private static FieldRef _semanCharacterRef; private static bool _wetInit; private static void LogInfo(string msg) { } private static void LogError(string msg) { } private static void DLogAttackSpeed(string msg) { } private static void DLogWet(string msg) { } private static void DLogTooltip(string msg) { } private static void DLogFood(string msg) { } private static void GetItemDropBonusesForPrefab(string prefabName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out float displayAttackSpeedPercent, out bool wetImmune) { extraHp = 0f; extraStamina = 0f; extraEitr = 0f; extraAttackSpeedPercent = 0f; displayAttackSpeedPercent = 0f; wetImmune = false; if (string.IsNullOrEmpty(prefabName)) { return; } for (int i = 0; i < ExtraStatsConfig.Count; i++) { ExtraStatEntry extraStatEntry = ExtraStatsConfig[i]; if (extraStatEntry.SourceType == ExtraSourceType.ItemDrop && string.Equals(prefabName, extraStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase)) { switch (extraStatEntry.StatType) { case ExtraStatType.Health: extraHp += extraStatEntry.Value; break; case ExtraStatType.Stamina: extraStamina += extraStatEntry.Value; break; case ExtraStatType.Eitr: extraEitr += extraStatEntry.Value; break; case ExtraStatType.AttackSpeed: extraAttackSpeedPercent += extraStatEntry.Value; displayAttackSpeedPercent += (extraStatEntry.DisplayValue.HasValue ? extraStatEntry.DisplayValue.Value : extraStatEntry.Value); break; case ExtraStatType.WetImmune: wetImmune = true; break; } } } } private static void GetItemDropBonusesForPrefab(string prefabName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out bool wetImmune) { GetItemDropBonusesForPrefab(prefabName, out extraHp, out extraStamina, out extraEitr, out extraAttackSpeedPercent, out var _, out wetImmune); } private static void GetStatusEffectBonuses(string seRawName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out float displayAttackSpeedPercent, out bool wetImmune) { extraHp = 0f; extraStamina = 0f; extraEitr = 0f; extraAttackSpeedPercent = 0f; displayAttackSpeedPercent = 0f; wetImmune = false; if (string.IsNullOrEmpty(seRawName)) { return; } string prefabName = Utils.GetPrefabName(seRawName); for (int i = 0; i < ExtraStatsConfig.Count; i++) { ExtraStatEntry extraStatEntry = ExtraStatsConfig[i]; if (extraStatEntry.SourceType == ExtraSourceType.StatusEffect && string.Equals(prefabName, extraStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase)) { switch (extraStatEntry.StatType) { case ExtraStatType.Health: extraHp += extraStatEntry.Value; break; case ExtraStatType.Stamina: extraStamina += extraStatEntry.Value; break; case ExtraStatType.Eitr: extraEitr += extraStatEntry.Value; break; case ExtraStatType.AttackSpeed: extraAttackSpeedPercent += extraStatEntry.Value; displayAttackSpeedPercent += (extraStatEntry.DisplayValue.HasValue ? extraStatEntry.DisplayValue.Value : extraStatEntry.Value); break; case ExtraStatType.WetImmune: wetImmune = true; break; } } } } private static void GetStatusEffectBonuses(string seRawName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out bool wetImmune) { GetStatusEffectBonuses(seRawName, out extraHp, out extraStamina, out extraEitr, out extraAttackSpeedPercent, out var _, out wetImmune); } private static string BuildExtraStatsTooltipBlock(float extraHp, float extraStamina, float extraEitr, float displayAttackSpeedPercent, bool wetImmune) { if (extraHp == 0f && extraStamina == 0f && extraEitr == 0f && displayAttackSpeedPercent == 0f && !wetImmune) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); string text = "$extrastats_health_DO"; string text2 = "$extrastats_stamina_DO"; string text3 = "$extrastats_eitr_DO"; string text4 = "$extrastats_attackspeed_DO"; string text5 = "$extrastats_immune_DO"; string text6 = "$extrastats_wet_DO"; if (Localization.instance != null) { text = Localization.instance.Localize(text); text2 = Localization.instance.Localize(text2); text3 = Localization.instance.Localize(text3); text4 = Localization.instance.Localize(text4); text5 = Localization.instance.Localize(text5); text6 = Localization.instance.Localize(text6); } if (extraHp != 0f) { string arg = ((extraHp >= 0f) ? "+" : ""); stringBuilder.Append($"\n{text}: {arg}{extraHp:F0}"); } if (extraStamina != 0f) { string arg2 = ((extraStamina >= 0f) ? "+" : ""); stringBuilder.Append($"\n{text2}: {arg2}{extraStamina:F0}"); } if (extraEitr != 0f) { string arg3 = ((extraEitr >= 0f) ? "+" : ""); stringBuilder.Append($"\n{text3}: {arg3}{extraEitr:F0}"); } if (displayAttackSpeedPercent != 0f) { int num = Mathf.RoundToInt(displayAttackSpeedPercent); string arg4 = ((num >= 0) ? "+" : ""); stringBuilder.Append($"\n{text4}: {arg4}{num}%"); } if (wetImmune) { stringBuilder.Append("\n" + text5 + ": " + text6 + ""); } return stringBuilder.ToString(); } private static bool HasWetImmune(Character c) { if ((Object)(object)c == (Object)null) { return false; } try { Player val = (Player)(object)((c is Player) ? c : null); if ((Object)(object)val != (Object)null) { Inventory inventory = ((Humanoid)val).GetInventory(); if (inventory != null) { List equippedItems = inventory.GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val2 = equippedItems[i]; if (val2 != null && !((Object)(object)val2.m_dropPrefab == (Object)null)) { string name = ((Object)val2.m_dropPrefab).name; GetItemDropBonusesForPrefab(name, out var _, out var _, out var _, out var _, out var _, out var wetImmune); if (wetImmune) { DLogWet("WetImmune from ItemDrop: " + name); return true; } } } } } if (c.m_seman != null && c.m_seman.m_statusEffects != null) { List statusEffects = c.m_seman.m_statusEffects; for (int j = 0; j < statusEffects.Count; j++) { StatusEffect val3 = statusEffects[j]; if (!((Object)(object)val3 == (Object)null)) { string name2 = ((Object)val3).name; GetStatusEffectBonuses(name2, out var _, out var _, out var _, out var _, out var _, out var wetImmune2); if (wetImmune2) { string prefabName = Utils.GetPrefabName(name2); DLogWet("WetImmune from StatusEffect: " + name2 + " (clean=" + prefabName + ")"); return true; } } } } } catch (Exception ex) { LogError("Exception in HasWetImmune: " + ex); } return false; } private static void EnsureAttackInit() { if (!_attackInit) { _attackInit = true; _zanimRef = AccessTools.FieldRefAccess("m_zanim"); } } private static HumanoidState GetAttackState(Humanoid h) { return _attackState.GetValue(h, (Humanoid _) => new HumanoidState()); } private static void ApplyAnimSpeed(Humanoid h, HumanoidState state, float speed) { ZSyncAnimation val = null; try { val = _zanimRef.Invoke((Character)(object)h); } catch (Exception) { return; } if (!((Object)(object)val == (Object)null) && !Mathf.Approximately(state.LastAppliedSpeed, speed)) { val.SetSpeed(speed); state.LastAppliedSpeed = speed; } } private static void ResetForHumanoid(Humanoid h) { if (!((Object)(object)h == (Object)null)) { EnsureAttackInit(); HumanoidState attackState = GetAttackState(h); ApplyAnimSpeed(h, attackState, 1f); attackState.HasDesiredSpeed = false; attackState.DesiredSpeed = 1f; attackState.WasInAttack = false; attackState.ActiveAttackDepth = 0; attackState.ActiveAttackMul = 1f; } } private static float ComputeTotalAttackSpeedPercentForHumanoid(Humanoid h) { float num = 0f; if ((Object)(object)h == (Object)null) { return 0f; } try { Player val = (Player)(object)((h is Player) ? h : null); if ((Object)(object)val != (Object)null) { Inventory inventory = ((Humanoid)val).GetInventory(); if (inventory != null) { List equippedItems = inventory.GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val2 = equippedItems[i]; if (val2 != null && !((Object)(object)val2.m_dropPrefab == (Object)null)) { string name = ((Object)val2.m_dropPrefab).name; GetItemDropBonusesForPrefab(name, out var _, out var _, out var _, out var extraAttackSpeedPercent, out var _, out var _); if (extraAttackSpeedPercent != 0f) { num += extraAttackSpeedPercent; DLogAttackSpeed($"AttackSpeed from ItemDrop: {name} → {extraAttackSpeedPercent}%"); } } } } } if (((Character)h).m_seman != null && ((Character)h).m_seman.m_statusEffects != null) { List statusEffects = ((Character)h).m_seman.m_statusEffects; for (int j = 0; j < statusEffects.Count; j++) { StatusEffect val3 = statusEffects[j]; if (!((Object)(object)val3 == (Object)null)) { string name2 = ((Object)val3).name; GetStatusEffectBonuses(name2, out var _, out var _, out var _, out var extraAttackSpeedPercent2, out var _, out var _); if (extraAttackSpeedPercent2 != 0f) { num += extraAttackSpeedPercent2; string prefabName = Utils.GetPrefabName(name2); DLogAttackSpeed($"AttackSpeed from StatusEffect: {name2} (clean={prefabName}) → {extraAttackSpeedPercent2}%"); } } } } } catch (Exception ex) { LogError("Exception in ComputeTotalAttackSpeedPercentForHumanoid: " + ex); } return num; } private static void EnsureWetInit() { if (!_wetInit) { _wetInit = true; _semanCharacterRef = AccessTools.FieldRefAccess("m_character"); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPatch] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public static class LivingContainerSpawner { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private static class DevLog { public const bool Enabled = false; public const bool SpawnTimers = true; public const bool SpawnAttempts = true; public const bool Dedicated = true; public const bool Lifecycle = true; public const bool Perf = true; public const bool Watcher = true; public const bool WatcherVerbose = false; public const bool StateReset = true; } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class LivingContainerDef { public string Prefab; public Biome Biomes; public float CheckInterval; public float SpawnChance; public int MaxInWorld; public float MinDistance; public float MaxDistance; public float MinAltitude; public float MaxAltitude; public bool AllowInWater; public int MaxSpawnAttempts; public float DestroyDelay; public string VfxPrefab; public string PinSprite; public string PinText; public bool PinAnimate; public bool PinDoubleSize; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private struct ItemsCacheEntry { public int ItemsLen; public int QuickHash; public bool IsEmpty; public int DecodedCount; public float LastTouchTime; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private struct PrefabContainerTuning { public int Width; public int Height; public int LootMin; public int LootMax; public bool Equals(PrefabContainerTuning other) { if (Width == other.Width && Height == other.Height && LootMin == other.LootMin) { return LootMax == other.LootMax; } return false; } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class LivingContainerRegistryComponent : MonoBehaviour { private ZNetView _nview; private ZDOID _uid; private string _prefab; private void Awake() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) try { _nview = ((Component)this).GetComponent(); if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } _prefab = Utils.GetPrefabName(((Object)((Component)this).gameObject).name); BuildDefCache(); if (DefByPrefab.ContainsKey(_prefab)) { ZDO val = null; try { val = _nview.GetZDO(); } catch { } if (val != null) { _uid = val.m_uid; RegisterLoadedRiko(_uid, _nview, _prefab); } } } catch { } } private void OnDestroy() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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) try { if (_uid != default(ZDOID)) { UnregisterLoadedRiko(_uid); } } catch { } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private enum GroundFail { None, WorldGenNoHeight, RaycastNoHit, WrongBiome, InWater, WaterTooDeep, OceanDepth, Lava, Altitude, Overlap, MistlandsBlocked } [HarmonyPatch(typeof(InventoryGui), "Hide")] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private static class InventoryGui_Hide_Patch { private static void Prefix(InventoryGui __instance, out Container __state) { __state = (((Object)(object)__instance != (Object)null) ? __instance.m_currentContainer : null); } private static void Postfix(Container __state) { if ((Object)(object)__state != (Object)null) { HandleContainerClosed(__state); } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class LivingContainerPinComponent : MonoBehaviour { public string PinSprite; public string PinText; public bool PinAnimate; public bool PinDoubleSize; private PinData _pin; private const float PinUpdateInterval_Seconds = 5f; private float _nextPinUpdateTime; private void Update() { //IL_006b: 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) if (!LivingContainerConfig.IsRikoEnabled()) { if (_pin != null && (Object)(object)Minimap.instance != (Object)null) { Minimap.instance.RemovePin(_pin); _pin = null; } Object.Destroy((Object)(object)this); return; } float time = Time.time; if (_pin != null) { if (!(time < _nextPinUpdateTime)) { _nextPinUpdateTime = time + 5f; _pin.m_pos = ((Component)this).transform.position; } } else { TryCreatePin(); } } private void TryCreatePin() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(PinSprite) && !((Object)(object)Minimap.instance == (Object)null) && Magic_SupremacyPlugin.PinSprites != null && Magic_SupremacyPlugin.PinSprites.TryGetValue(PinSprite, out var value) && !((Object)(object)value == (Object)null)) { PinData val = Minimap.instance.AddPin(((Component)this).transform.position, (PinType)8, PinText ?? "", false, false, 0L, default(PlatformUserID)); val.m_icon = value; val.m_animate = PinAnimate; val.m_doubleSize = PinDoubleSize; val.m_save = false; _pin = val; _nextPinUpdateTime = Time.time + 5f; } } private void OnDestroy() { if (_pin != null && (Object)(object)Minimap.instance != (Object)null) { Minimap.instance.RemovePin(_pin); } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private class RikoSpawnStabilizer : MonoBehaviour { private bool _started; public void Init() { if (!_started) { _started = true; ((MonoBehaviour)this).StartCoroutine(StabilizeRoutine()); } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private IEnumerator StabilizeRoutine() { StabilizeOnce(((Component)this).gameObject); yield return null; StabilizeOnce(((Component)this).gameObject); yield return (object)new WaitForSeconds(0.35f); StabilizeOnce(((Component)this).gameObject); } } private static readonly LivingContainerDef[] Defs = new LivingContainerDef[6] { new LivingContainerDef { Prefab = "EncounterCreatureRikoBlackforestDO", Biomes = (Biome)8, CheckInterval = 360f, SpawnChance = 0.3f, MaxInWorld = 3, MinDistance = 18f, MaxDistance = 36f, MinAltitude = 0f, MaxAltitude = 2000f, AllowInWater = false, MaxSpawnAttempts = 15, DestroyDelay = 1f, VfxPrefab = "fx_riko_disappear_DO", PinSprite = "PinRikoDO", PinText = "", PinAnimate = false, PinDoubleSize = true }, new LivingContainerDef { Prefab = "EncounterCreatureRikoSwampDO", Biomes = (Biome)2, CheckInterval = 360f, SpawnChance = 0.3f, MaxInWorld = 3, MinDistance = 18f, MaxDistance = 36f, MinAltitude = -1f, MaxAltitude = 2000f, AllowInWater = false, MaxSpawnAttempts = 18, DestroyDelay = 1f, VfxPrefab = "fx_riko_disappear_DO", PinSprite = "PinRikoDO", PinText = "", PinAnimate = false, PinDoubleSize = true }, new LivingContainerDef { Prefab = "EncounterCreatureRikoMountainDO", Biomes = (Biome)4, CheckInterval = 360f, SpawnChance = 0.3f, MaxInWorld = 3, MinDistance = 18f, MaxDistance = 36f, MinAltitude = 10f, MaxAltitude = 2000f, AllowInWater = false, MaxSpawnAttempts = 15, DestroyDelay = 1f, VfxPrefab = "fx_riko_disappear_DO", PinSprite = "PinRikoDO", PinText = "", PinAnimate = false, PinDoubleSize = true }, new LivingContainerDef { Prefab = "EncounterCreatureRikoPlainsDO", Biomes = (Biome)16, CheckInterval = 360f, SpawnChance = 0.3f, MaxInWorld = 3, MinDistance = 18f, MaxDistance = 36f, MinAltitude = 0f, MaxAltitude = 2000f, AllowInWater = false, MaxSpawnAttempts = 15, DestroyDelay = 1f, VfxPrefab = "fx_riko_disappear_DO", PinSprite = "PinRikoDO", PinText = "", PinAnimate = false, PinDoubleSize = true }, new LivingContainerDef { Prefab = "EncounterCreatureRikoMistlandsDO", Biomes = (Biome)512, CheckInterval = 360f, SpawnChance = 0.3f, MaxInWorld = 3, MinDistance = 15f, MaxDistance = 40f, MinAltitude = 12f, MaxAltitude = 2000f, AllowInWater = false, MaxSpawnAttempts = 18, DestroyDelay = 1f, VfxPrefab = "fx_riko_disappear_DO", PinSprite = "PinRikoDO", PinText = "", PinAnimate = false, PinDoubleSize = true }, new LivingContainerDef { Prefab = "EncounterCreatureRikoAshlandsDO", Biomes = (Biome)32, CheckInterval = 360f, SpawnChance = 0.3f, MaxInWorld = 3, MinDistance = 18f, MaxDistance = 36f, MinAltitude = 0f, MaxAltitude = 2000f, AllowInWater = false, MaxSpawnAttempts = 15, DestroyDelay = 1f, VfxPrefab = "fx_riko_disappear_DO", PinSprite = "PinRikoDO", PinText = "", PinAnimate = false, PinDoubleSize = true } }; private const float Riko_SeenRadius_Meters = 120f; private const float Riko_SeenUpdateInterval_Seconds = 12f; private const float Riko_TTL_Minutes = 20f; private const float Riko_Grace_Minutes = 2f; private const float Riko_TtlScanInterval_Seconds = 45f; private const float Riko_DestroyScanInterval_Seconds = 20f; private const float Riko_LoadedDestroyCheckInterval_Seconds = 0.2f; private const float Riko_EmptyWatcherInterval_Seconds = 30f; private const float ConfigRefreshInterval_Seconds = 5f; private const int OriginMaxAttempts = 3; private const int OriginPickGuard = 16; private const int MaxCatchupChecksPerTick_PerDef = 2; private const float WorldCountRescanInterval_Seconds = 90f; private const float ServerStartupGrace_Seconds = 10f; private const float MaxAllowedWaterDepth_Center = 0.08f; private const float MaxAllowedWaterDepth_Side = 0.12f; private const float DryAreaProbeRadius = 0.9f; private const int DryAreaAllowedWetSideSamples = 1; private const float MistlandsHeadroomHeight = 2.2f; private const float MistlandsHeadroomRadius = 0.45f; private const float MistlandsCeilingCheckStart = 0.15f; private const float DedNoGroundLogInterval_Seconds = 15f; private const string ZdoKey_Killed = "MS_Riko_Killed"; private const string ZdoKey_SpawnTime = "MS_Riko_SpawnTime"; private const string ZdoKey_LastSeenTime = "MS_Riko_LastSeenTime"; private const string ZdoKey_DestroyAt = "MS_Riko_DestroyAt"; private const string ZdoKey_VfxPlayed = "MS_Riko_VfxPlayed"; private const string ZdoKey_FinalDestroyCounted = "MS_Riko_FinalDestroyCounted"; private static readonly Dictionary DefByPrefab = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary WorldCounts = new Dictionary(StringComparer.OrdinalIgnoreCase); private static float[] WorldChecks; private static float LastWorldUpdate; private static float NextSeenUpdateTime; private static float NextDestroyScanTime; private static float NextLoadedDestroyCheckTime; private static float NextTtlScanTime; private static float NextConfigRefreshTime; private static float NextWorldCountRescanTime; private static readonly Dictionary NextAuthoritativeCountCheckTime = new Dictionary(StringComparer.OrdinalIgnoreCase); private const float AuthoritativeCountRefreshInterval_Seconds = 20f; private static bool WorldCountCacheInitialized; private static readonly List OriginPositions = new List(32); private static readonly FieldInfo ZNetPeer_m_refPos_Field = AccessTools.Field(typeof(ZNetPeer), "m_refPos"); private static readonly Dictionary LoadedRikos = new Dictionary(256); private static int LoadedRegistryInvalidSweeps; private static List _registrySweepKeys; private static bool PurgeInProgress; private static int PurgePrefabIndex; private static int PurgeSectorIndex; private static readonly List PurgeZdos = new List(256); private static float ServerWorldEnterTime = -1f; private static bool ServerGraceLogged; private static float _dedNextNoGroundLogTime; private static int _dedLastPlayers = -999; private static int _dedLastPeers = -999; private static int _dedLastOriginPos = -999; private static float _dedNextHeartbeatTime; private static bool _emptyWatcherInProgress; private static int _emptyWatcherPrefabIndex; private static int _emptyWatcherSectorIndex; private static readonly List _emptyWatcherZdos = new List(256); private static float _emptyWatcherNextRunTime; private static int _hashInUse; private static int _hashItems; private static readonly Dictionary _itemsCache = new Dictionary(512); private static float _itemsCacheNextCleanupTime; private const float ItemsCacheCleanupInterval_Seconds = 60f; private const float ItemsCacheKeepSeconds = 600f; private const int ItemsCacheMaxSize = 4096; private static List _itemsCacheKeysTmp; private static readonly Dictionary AppliedPrefabTuning = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly int SolidMask = LayerMask.GetMask(new string[5] { "terrain", "static_solid", "Default", "piece", "vehicle" }); private static readonly Vector2[] DryAreaProbeOffsets = (Vector2[])(object)new Vector2[5] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(-1f, 0f), new Vector2(0f, 1f), new Vector2(0f, -1f) }; private static void Log(string msg) { } private static void LogTimers(string msg) { } private static void LogSpawn(string msg) { } private static void LogDed(string msg) { } private static void LogLife(string msg) { } private static void LogPerf(string msg) { } private static void LogWatcher(string msg) { } private static void LogWatcherVerbose(string msg) { } private static void LogReset(string msg) { } private static void RegisterLoadedRiko(ZDOID uid, ZNetView nv, string prefab) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)nv == (Object)null)) { LoadedRikos[uid] = nv; LogPerf($"registry ADD prefab={prefab} uid={uid} loaded={LoadedRikos.Count}"); } } private static void UnregisterLoadedRiko(ZDOID uid) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (LoadedRikos.Remove(uid)) { LogPerf($"registry REMOVE uid={uid} loaded={LoadedRikos.Count}"); } } private static void EnsureRegistryComponent(GameObject go) { if (!((Object)(object)go == (Object)null) && !((Object)(object)go.GetComponent() != (Object)null)) { go.AddComponent(); } } [HarmonyPostfix] [HarmonyPatch(typeof(ZNet), "Awake")] private static void ZNet_Awake_Postfix() { try { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { ResetRuntimeState_Server("ZNet.Awake"); } } catch { } } private static void ResetRuntimeState_Server(string reason) { WorldChecks = null; LastWorldUpdate = 0f; WorldCounts.Clear(); WorldCountCacheInitialized = false; NextWorldCountRescanTime = 0f; NextAuthoritativeCountCheckTime.Clear(); LoadedRikos.Clear(); LoadedRegistryInvalidSweeps = 0; NextSeenUpdateTime = 0f; NextDestroyScanTime = 0f; NextLoadedDestroyCheckTime = 0f; NextTtlScanTime = 0f; NextConfigRefreshTime = 0f; PurgeInProgress = false; PurgePrefabIndex = 0; PurgeSectorIndex = 0; PurgeZdos.Clear(); _emptyWatcherInProgress = false; _emptyWatcherPrefabIndex = 0; _emptyWatcherSectorIndex = 0; _emptyWatcherZdos.Clear(); _emptyWatcherNextRunTime = 0f; _itemsCache.Clear(); _itemsCacheNextCleanupTime = 0f; ServerWorldEnterTime = Time.time; ServerGraceLogged = false; OriginPositions.Clear(); _dedNextNoGroundLogTime = 0f; _dedLastPlayers = -999; _dedLastPeers = -999; _dedLastOriginPos = -999; _dedNextHeartbeatTime = 0f; LogReset($"server RuntimeState RESET reason={reason} time={ServerWorldEnterTime:0.00} session={ZDOMan.GetSessionID()}"); } [HarmonyPostfix] [HarmonyPatch(typeof(ZoneSystem), "Update")] private static void ZoneSystem_Update_Postfix() { if (!LivingContainerConfig.IsRikoEnabled() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ObjectDB.instance == (Object)null) { return; } if (ServerWorldEnterTime < 0f) { ServerWorldEnterTime = Time.time; } float num = Time.time - ServerWorldEnterTime; bool flag = num < 10f; if (flag && !ServerGraceLogged) { ServerGraceLogged = true; LogTimers($"server StartupGrace ACTIVE seconds={10f:0.0} sinceEnter={num:0.00}"); } BuildDefCache(); if (Time.time >= NextConfigRefreshTime) { RefreshDefsFromConfig(); NextConfigRefreshTime = Time.time + 5f; } List allPlayers = Player.GetAllPlayers(); BuildOriginPositions(allPlayers); LogDedicatedStateIfNeeded(allPlayers); UpdateLastSeenForLoadedRikos(); ProcessLoadedDestroyDueFast(); ProcessScheduledDestroyForLoadedRikos(); TryRunEmptyWatcher_Server(); TryPurgeExpiredOrKilledRikoZDOs(); if (OriginPositions.Count == 0) { return; } float time = Time.time; if (LastWorldUpdate <= 0f) { LastWorldUpdate = time; EnsureWorldChecksInitialized(); EnsureWorldCounts_Cached(initial: true); LogTimers($"server WorldTimers INIT sinceEnter={num:0.00} note=FirstWorldTick"); return; } float num2 = time - LastWorldUpdate; if (num2 < 5f) { return; } LastWorldUpdate = time; EnsureWorldChecksInitialized(); EnsureWorldCounts_Cached(initial: false); LogTimers($"server WorldTick sinceEnter={num:0.00} delta={num2:0.00} origins={OriginPositions.Count}"); for (int i = 0; i < Defs.Length; i++) { LivingContainerDef livingContainerDef = Defs[i]; if (livingContainerDef == null) { continue; } float num3 = WorldChecks[i]; WorldChecks[i] -= num2; float num4 = WorldChecks[i]; if (num3 > 0f && (num3 < 5f || num4 <= 0f)) { LogTimers($"server WorldTimer prefab={livingContainerDef.Prefab} before={num3:0.00} after={num4:0.00} delta={num2:0.00} interval={livingContainerDef.CheckInterval:0.0} grace={flag}"); } if (WorldChecks[i] > 0f) { continue; } if (flag) { WorldChecks[i] = Mathf.Max(1f, livingContainerDef.CheckInterval); LogTimers($"server WorldTimer BLOCKED_BY_GRACE prefab={livingContainerDef.Prefab} setNext={WorldChecks[i]:0.00}"); continue; } int num5 = 0; float num6 = Mathf.Max(1f, livingContainerDef.CheckInterval); while (WorldChecks[i] <= 0f && num5 < 2) { TrySpawnWithFallbackOrigins(OriginPositions, livingContainerDef, num, num5); WorldChecks[i] += num6; num5++; } if (WorldChecks[i] <= 0f) { WorldChecks[i] = Mathf.Min(1f, num6); LogTimers($"server WorldTimer STILL_OVERDUE prefab={livingContainerDef.Prefab} cappedNext={WorldChecks[i]:0.00}"); } else { LogTimers($"server WorldTimer ADVANCED prefab={livingContainerDef.Prefab} nextIn={WorldChecks[i]:0.00} catchupUsed={num5}"); } } } private static void EnsureWorldChecksInitialized() { if (WorldChecks == null || WorldChecks.Length != Defs.Length) { WorldChecks = new float[Defs.Length]; for (int i = 0; i < WorldChecks.Length; i++) { LivingContainerDef livingContainerDef = Defs[i]; float num = ((livingContainerDef != null) ? Mathf.Max(1f, livingContainerDef.CheckInterval) : 60f); float num2 = Mathf.Min(30f, num * 0.1f); WorldChecks[i] = num + Random.Range(0f, num2); } LogTimers($"server WorldChecks CREATED count={WorldChecks.Length}"); } } private static void BuildOriginPositions(List players) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00f7: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00c2: Unknown result type (might be due to invalid IL or missing references) OriginPositions.Clear(); if (players != null && players.Count > 0) { for (int i = 0; i < players.Count; i++) { Player val = players[i]; if (!((Object)(object)val == (Object)null)) { AddOriginPosition(((Component)val).transform.position); } } } else { if ((Object)(object)ZNet.instance == (Object)null) { return; } List list = null; try { list = ZNet.instance.GetPeers(); } catch { } if (list == null || list.Count == 0) { return; } for (int j = 0; j < list.Count; j++) { ZNetPeer val2 = list[j]; if (val2 == null) { continue; } Vector3 val3 = Vector3.zero; try { if (ZNetPeer_m_refPos_Field != null) { object value = ZNetPeer_m_refPos_Field.GetValue(val2); if (value is Vector3) { Vector3 val4 = (Vector3)value; val3 = val4; } } } catch { } if (!(val3 == Vector3.zero)) { AddOriginPosition(val3); AddOriginPosition(val3 + new Vector3(24f, 0f, 0f)); AddOriginPosition(val3 + new Vector3(-24f, 0f, 0f)); AddOriginPosition(val3 + new Vector3(0f, 0f, 24f)); AddOriginPosition(val3 + new Vector3(0f, 0f, -24f)); } } } } private static void AddOriginPosition(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (pos == Vector3.zero) { return; } for (int i = 0; i < OriginPositions.Count; i++) { Vector3 val = OriginPositions[i] - pos; if (((Vector3)(ref val)).sqrMagnitude < 1f) { return; } } OriginPositions.Add(pos); } private static void LogDedicatedStateIfNeeded(List players) { } private static bool SafeIsDedicated() { try { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated(); } catch { return false; } } private static bool TrySpawnWithFallbackOrigins(List origins, LivingContainerDef def, float sinceEnter, int catchup) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (origins == null || origins.Count == 0 || def == null) { return false; } int num = 0; int num2 = -1; int num3 = -1; int num4 = -1; for (int i = 0; i < 3; i++) { int num5 = -1; Vector3 val = Vector3.zero; int num6 = 0; while (num5 < 0 && num6 < 16) { num6++; int num7 = Random.Range(0, origins.Count); if (num7 != num2 && num7 != num3 && num7 != num4) { Vector3 val2 = origins[num7]; if (!(val2 == Vector3.zero)) { num5 = num7; val = val2; } } } if (num5 < 0) { for (int j = 0; j < origins.Count; j++) { if (j != num2 && j != num3 && j != num4) { Vector3 val3 = origins[j]; if (!(val3 == Vector3.zero)) { num5 = j; val = val3; break; } } } } if (num5 < 0) { return false; } switch (num) { case 0: num2 = num5; break; case 1: num3 = num5; break; case 2: num4 = num5; break; } num++; Biome biomeSafe = GetBiomeSafe(val); if ((int)biomeSafe != 0 && (biomeSafe & def.Biomes) == 0) { LogSpawn("server TrySpawn SKIP originBiomeMismatch " + $"originPos=({val.x:0.0},{val.y:0.0},{val.z:0.0}) " + $"originBiome={biomeSafe} needed={def.Biomes} prefab={def.Prefab} " + $"originAttempt={i + 1}/{3}"); continue; } LogSpawn($"server TrySpawn CALL originPos=({val.x:0.0},{val.y:0.0},{val.z:0.0}) prefab={def.Prefab} sinceEnter={sinceEnter:0.00} catchup={catchup} originAttempt={i + 1}/{3}"); if (TrySpawnAtPosition(val, def)) { return true; } } return false; } private static bool TrySpawnAtPosition(Vector3 origin, LivingContainerDef def) { //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) if (def == null) { return false; } float value = Random.value; if (value > def.SpawnChance) { LogSpawn($"server TrySpawn FAIL chance prefab={def.Prefab} rnd={value:0.000} chance={def.SpawnChance:0.000}"); return false; } int authoritativeAliveCountForPrefab = GetAuthoritativeAliveCountForPrefab(def.Prefab); if (authoritativeAliveCountForPrefab >= def.MaxInWorld) { LogSpawn($"server TrySpawn FAIL maxInWorld prefab={def.Prefab} count={authoritativeAliveCountForPrefab} max={def.MaxInWorld}"); return false; } GameObject prefab = ZNetScene.instance.GetPrefab(def.Prefab); if ((Object)(object)prefab == (Object)null) { LogSpawn("server TrySpawn FAIL missingPrefab prefab=" + def.Prefab); return false; } ApplyContainerConfigToPrefab(def, prefab); int num = Mathf.Max(1, def.MaxSpawnAttempts); int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; int num8 = 0; int num9 = 0; int num10 = 0; int num11 = 0; for (int i = 0; i < num; i++) { Vector3 val = PickPoint(origin, def.MinDistance, def.MaxDistance); if (!TryGetRikoSpawnPoint(val, def, out var spawnPos, out var fail)) { switch (fail) { case GroundFail.WorldGenNoHeight: case GroundFail.RaycastNoHit: num2++; break; case GroundFail.WrongBiome: num3++; break; case GroundFail.InWater: num4++; break; case GroundFail.WaterTooDeep: num5++; break; case GroundFail.OceanDepth: num6++; break; case GroundFail.Lava: num7++; break; case GroundFail.Altitude: num8++; break; case GroundFail.Overlap: num9++; break; case GroundFail.MistlandsBlocked: num10++; break; } LogSpawn($"server TrySpawn attempt={i + 1} FAIL prefab={def.Prefab} fail={fail} candidate=({val.x:0.0},{val.y:0.0},{val.z:0.0})"); continue; } Quaternion val2 = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f); GameObject val3 = Object.Instantiate(prefab, spawnPos, val2); if ((Object)(object)val3 == (Object)null) { num11++; LogSpawn($"server TrySpawn attempt={i + 1} FAIL instantiateNull prefab={def.Prefab}"); continue; } EnsureRegistryComponent(val3); AttachPinComponent(val3, def); Container component = val3.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_autoDestroyEmpty = false; } FixSpawnInsideGeometry(val3); ZNetView val4 = null; ZDO val5 = null; try { val4 = val3.GetComponent(); if ((Object)(object)val4 != (Object)null && val4.IsValid()) { val5 = val4.GetZDO(); } } catch { } if (val5 != null) { try { EnsureServerOwnership(val4, val5, "SpawnInitZdo"); long nowSeconds = GetNowSeconds(); val5.Set("MS_Riko_SpawnTime", nowSeconds); val5.Set("MS_Riko_LastSeenTime", nowSeconds); val5.Set("MS_Riko_Killed", 0); val5.Set("MS_Riko_DestroyAt", 0L); val5.Set("MS_Riko_VfxPlayed", 0); val5.Set("MS_Riko_FinalDestroyCounted", 0); } catch { } } WorldCounts[def.Prefab] = ((!WorldCounts.TryGetValue(def.Prefab, out var value2)) ? 1 : (value2 + 1)); string text = ((val5 != null) ? ((object)(ZDOID)(ref val5.m_uid)).ToString() : "null"); LogSpawn($"server TrySpawn SUCCESS prefab={def.Prefab} uid={text} pos=({spawnPos.x:0.0},{spawnPos.y:0.0},{spawnPos.z:0.0}) attempt={i + 1} worldCount={WorldCounts[def.Prefab]}"); LogSpawn($"server TrySpawn SUMMARY prefab={def.Prefab} attempts={num} " + $"groundFail={num2} biomeFail={num3} waterFail={num4} deepWaterFail={num5} oceanFail={num6} lavaFail={num7} altitudeFail={num8} overlapFail={num9} mistBlockedFail={num10} instFail={num11}"); return true; } LogSpawn($"server TrySpawn SUMMARY prefab={def.Prefab} attempts={num} " + $"groundFail={num2} biomeFail={num3} waterFail={num4} deepWaterFail={num5} oceanFail={num6} lavaFail={num7} altitudeFail={num8} overlapFail={num9} mistBlockedFail={num10} instFail={num11}"); return false; } private static bool TryGetRikoSpawnPoint(Vector3 candidate, LivingContainerDef def, out Vector3 spawnPos, out GroundFail fail) { //IL_0001: 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_000a: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0038: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) spawnPos = candidate; fail = GroundFail.None; if (!TryGetGroundPoint(candidate, out var groundPoint, out var fail2)) { fail = fail2; return false; } Biome biomeSafe = GetBiomeSafe(groundPoint); if ((biomeSafe & def.Biomes) == 0) { fail = GroundFail.WrongBiome; return false; } bool flag = (biomeSafe & 2) > 0; Heightmap val = Heightmap.FindHeightmap(groundPoint); if ((Object)(object)val != (Object)null && val.GetOceanDepth(groundPoint) > 0.5f) { fail = GroundFail.OceanDepth; return false; } if ((def.Biomes & 0x20) != 0) { bool flag2 = IsAshlandsLavaByWorldGen(groundPoint); if (!flag2 && (Object)(object)val != (Object)null) { flag2 = val.IsLava(groundPoint, 0.4f); } if (flag2) { fail = GroundFail.Lava; return false; } } if (!def.AllowInWater && !flag && IsAreaTooWetForRiko(groundPoint, out var _, out var _)) { fail = GroundFail.WaterTooDeep; return false; } if (groundPoint.y < def.MinAltitude || groundPoint.y > def.MaxAltitude) { fail = GroundFail.Altitude; return false; } Vector3 ground = groundPoint; if (SafeIsDedicated()) { TryFindSolidBelow(groundPoint + Vector3.up * 1f, 8f, out ground); } if ((def.Biomes & 0x200) != 0 && (SafeIsDedicated() ? IsMistlandsSpawnSpaceBlocked(ground) : IsMistlandsSpawnSpaceBlocked_Local(ground))) { fail = GroundFail.MistlandsBlocked; return false; } if (IsBodyOverlapping(ground)) { fail = GroundFail.Overlap; return false; } spawnPos = ground + Vector3.up * 0.03f; return true; } private static bool TryGetGroundPoint(Vector3 candidate, out Vector3 groundPoint, out GroundFail fail) { //IL_0001: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) groundPoint = candidate; fail = GroundFail.None; if (SafeIsDedicated()) { if (TryGetWorldGeneratorHeight(candidate.x, candidate.z, out var y)) { groundPoint = new Vector3(candidate.x, y, candidate.z); RaycastHit val = default(RaycastHit); if (Physics.Raycast(candidate + Vector3.up * 200f, Vector3.down, ref val, 500f, SolidMask, (QueryTriggerInteraction)1)) { groundPoint = ((RaycastHit)(ref val)).point; } return true; } RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(candidate + Vector3.up * 200f, Vector3.down, ref val2, 500f, SolidMask, (QueryTriggerInteraction)1)) { groundPoint = ((RaycastHit)(ref val2)).point; return true; } fail = GroundFail.WorldGenNoHeight; ThrottledNoGroundLog(candidate, fail); return false; } RaycastHit val3 = default(RaycastHit); if (!Physics.Raycast(candidate + Vector3.up * 200f, Vector3.down, ref val3, 500f, SolidMask, (QueryTriggerInteraction)1)) { fail = GroundFail.RaycastNoHit; return false; } groundPoint = ((RaycastHit)(ref val3)).point; return true; } private static bool TryGetWorldGeneratorHeight(float x, float z, out float y) { y = 0f; try { if (WorldGenerator.instance == null) { return false; } Color val = default(Color); float height = WorldGenerator.instance.GetHeight(x, z, ref val); if (float.IsNaN(height) || float.IsInfinity(height)) { return false; } y = height; return true; } catch { return false; } } private static Biome GetBiomeSafe(Vector3 pos) { //IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) try { if (WorldGenerator.instance != null) { return WorldGenerator.instance.GetBiome(pos); } } catch { } try { return Heightmap.FindBiome(pos); } catch { } return (Biome)0; } private static bool IsAshlandsLavaByWorldGen(Vector3 point, float lavaValue = 0.4f) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_0025: 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_003a: Unknown result type (might be due to invalid IL or missing references) try { if (WorldGenerator.instance == null) { return false; } if ((int)WorldGenerator.instance.GetBiome(point) != 32) { return false; } Color val = default(Color); WorldGenerator.instance.GetBiomeHeight((Biome)32, point.x, point.z, ref val, false); return val.a > lavaValue; } catch { return false; } } private static void ThrottledNoGroundLog(Vector3 candidate, GroundFail fail) { } private static bool IsAreaTooWetForRiko(Vector3 centerGround, out float centerDepth, out int wetSideSamples) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) centerDepth = 0f; wetSideSamples = 0; for (int i = 0; i < DryAreaProbeOffsets.Length; i++) { Vector2 val = DryAreaProbeOffsets[i] * 0.9f; float num = centerGround.x + val.x; float num2 = centerGround.z + val.y; if (!TryGetWorldGeneratorHeight(num, num2, out var y)) { if (i == 0) { centerDepth = 999f; } return true; } if (!TryGetWaterSurfaceY(new Vector3(num, y, num2), out var waterY)) { continue; } float num3 = waterY - y; if (i == 0) { centerDepth = num3; if (num3 > 0.08f) { return true; } } else if (num3 > 0.12f) { wetSideSamples++; } } return wetSideSamples > 1; } private static bool TryGetWaterSurfaceY(Vector3 point, out float waterY) { //IL_0056: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) waterY = 0f; List instances = WaterVolume.Instances; if (instances == null || instances.Count == 0) { return false; } WaterVolume val = null; float num = float.MaxValue; for (int i = 0; i < instances.Count; i++) { WaterVolume val2 = instances[i]; if ((Object)(object)val2 == (Object)null) { continue; } Collider val3 = null; try { val3 = ((Component)val2).GetComponent(); } catch { } if ((Object)(object)val3 == (Object)null) { continue; } Vector3 val4 = val3.ClosestPoint(point) - point; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; val = val2; if (num <= 1E-06f) { break; } } } if ((Object)(object)val == (Object)null) { return false; } try { waterY = val.GetWaterSurface(point, 1f); return true; } catch { return false; } } private static bool IsMistlandsSpawnSpaceBlocked(Vector3 groundPoint) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = groundPoint + Vector3.up * 0.15f; Vector3 val2 = val + Vector3.up * 2.2f; if (!Physics.CheckCapsule(val, val2, 0.45f, SolidMask, (QueryTriggerInteraction)1)) { return false; } Vector3[] array = (Vector3[])(object)new Vector3[5] { Vector3.zero, new Vector3(0.45f, 0f, 0f), new Vector3(-0.45f, 0f, 0f), new Vector3(0f, 0f, 0.45f), new Vector3(0f, 0f, -0.45f) }; int num = 0; for (int i = 0; i < array.Length; i++) { Vector3 val3 = val + array[i]; Vector3 val4 = val2 + array[i]; if (Physics.CheckCapsule(val3, val4, 0.45f, SolidMask, (QueryTriggerInteraction)1)) { num++; } } return num >= 3; } private static bool IsMistlandsSpawnSpaceBlocked_Local(Vector3 groundPoint) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = groundPoint + Vector3.up * 0.2f; Vector3 val2 = val + Vector3.up * 1.85f; if (!Physics.CheckCapsule(val, val2, 0.3f, SolidMask, (QueryTriggerInteraction)1)) { return false; } Vector3[] array = (Vector3[])(object)new Vector3[5] { Vector3.zero, new Vector3(0.3f, 0f, 0f), new Vector3(-0.3f, 0f, 0f), new Vector3(0f, 0f, 0.3f), new Vector3(0f, 0f, -0.3f) }; int num = 0; for (int i = 0; i < array.Length; i++) { Vector3 val3 = val + array[i]; Vector3 val4 = val2 + array[i]; if (Physics.CheckCapsule(val3, val4, 0.3f, SolidMask, (QueryTriggerInteraction)1)) { num++; } } return num >= 5; } private static bool HasAnyKnownRikoInWorld() { if (LoadedRikos.Count > 0) { return true; } foreach (KeyValuePair worldCount in WorldCounts) { if (worldCount.Value > 0) { return true; } } return false; } private static void EnsureWorldCounts_Cached(bool initial) { float time = Time.time; if (!WorldCountCacheInitialized) { RescanWorldCounts_GlobalZdo("init"); WorldCountCacheInitialized = true; NextWorldCountRescanTime = time + 90f; } else if (!initial && !(time < NextWorldCountRescanTime)) { RescanWorldCounts_GlobalZdo("timer"); NextWorldCountRescanTime = time + 90f; } } private static void RescanWorldCounts_GlobalZdo(string reason) { WorldCounts.Clear(); if (ZDOMan.instance == null) { return; } int num = 0; int num2 = 0; for (int i = 0; i < Defs.Length; i++) { LivingContainerDef livingContainerDef = Defs[i]; if (livingContainerDef == null || string.IsNullOrEmpty(livingContainerDef.Prefab)) { continue; } int num3 = 0; PurgeZdos.Clear(); bool flag = false; int num4 = 0; try { while (!flag && num4 < 10000) { flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative(livingContainerDef.Prefab, PurgeZdos, ref num3); num4++; } } catch { EnsureWorldCounts_LoadedFallback(); PurgeZdos.Clear(); LogPerf("WorldCounts RESCAN_FALLBACK reason=" + reason + " note=iterativeFailed"); return; } int num5 = 0; for (int j = 0; j < PurgeZdos.Count; j++) { ZDO val = PurgeZdos[j]; if (val != null) { int num6 = 0; try { num6 = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num6 != 1) { num5++; } } } WorldCounts[livingContainerDef.Prefab] = num5; num++; num2 += PurgeZdos.Count; } PurgeZdos.Clear(); LogPerf($"WorldCounts RESCAN_OK reason={reason} prefabs={num} scannedZdos={num2}"); } private static void EnsureWorldCounts_LoadedFallback() { WorldCounts.Clear(); foreach (KeyValuePair loadedRiko in LoadedRikos) { ZNetView value = loadedRiko.Value; if ((Object)(object)value == (Object)null || !value.IsValid()) { continue; } string prefabName = Utils.GetPrefabName(((Object)((Component)value).gameObject).name); if (!DefByPrefab.ContainsKey(prefabName)) { continue; } ZDO val = null; try { val = value.GetZDO(); } catch { } if (val != null) { int num = 0; try { num = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num == 1) { continue; } } WorldCounts[prefabName] = ((!WorldCounts.TryGetValue(prefabName, out var value2)) ? 1 : (value2 + 1)); } } private static int GetAuthoritativeAliveCountForPrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return 0; } int value; int num = (WorldCounts.TryGetValue(prefabName, out value) ? value : 0); if (ZDOMan.instance == null) { return num; } float time = Time.time; if (NextAuthoritativeCountCheckTime.TryGetValue(prefabName, out var value2) && time < value2) { return num; } int num2 = 0; PurgeZdos.Clear(); bool flag = false; int num3 = 0; try { while (!flag && num3 < 10000) { flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefabName, PurgeZdos, ref num2); num3++; } } catch { NextAuthoritativeCountCheckTime[prefabName] = time + 20f; int num4 = num; LogPerf($"WorldCounts AUTHORITATIVE_FALLBACK prefab={prefabName} cached={num4} note=iterativeFailed"); PurgeZdos.Clear(); return num4; } int num5 = 0; for (int i = 0; i < PurgeZdos.Count; i++) { ZDO val = PurgeZdos[i]; if (val != null) { int num6 = 0; try { num6 = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num6 != 1) { num5++; } } } PurgeZdos.Clear(); WorldCounts[prefabName] = num5; NextAuthoritativeCountCheckTime[prefabName] = time + 20f; LogPerf($"WorldCounts AUTHORITATIVE prefab={prefabName} count={num5}"); return num5; } private static void SweepRegistryInvalidEntriesIfNeeded() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) LoadedRegistryInvalidSweeps++; if (LoadedRegistryInvalidSweeps < 10) { return; } LoadedRegistryInvalidSweeps = 0; if (LoadedRikos.Count == 0) { return; } if (_registrySweepKeys == null) { _registrySweepKeys = new List(128); } _registrySweepKeys.Clear(); foreach (KeyValuePair loadedRiko in LoadedRikos) { ZNetView value = loadedRiko.Value; if ((Object)(object)value == (Object)null || !value.IsValid()) { _registrySweepKeys.Add(loadedRiko.Key); } } for (int i = 0; i < _registrySweepKeys.Count; i++) { LoadedRikos.Remove(_registrySweepKeys[i]); } if (_registrySweepKeys.Count > 0) { LogPerf($"registry SWEEP removed={_registrySweepKeys.Count} remaining={LoadedRikos.Count}"); } } private static void UpdateLastSeenForLoadedRikos() { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (time < NextSeenUpdateTime) { return; } NextSeenUpdateTime = time + 12f; if (LoadedRikos.Count == 0 || OriginPositions.Count == 0) { return; } float num = 14400f; long nowSeconds = GetNowSeconds(); SweepRegistryInvalidEntriesIfNeeded(); foreach (KeyValuePair loadedRiko in LoadedRikos) { ZNetView value = loadedRiko.Value; if ((Object)(object)value == (Object)null || !value.IsValid()) { continue; } string prefabName = Utils.GetPrefabName(((Object)((Component)value).gameObject).name); if (!DefByPrefab.ContainsKey(prefabName)) { continue; } ZDO val = null; try { val = value.GetZDO(); } catch { } if (val != null) { int num2 = 0; try { num2 = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num2 == 1) { continue; } } Vector3 position = ((Component)value).transform.position; bool flag = false; for (int i = 0; i < OriginPositions.Count; i++) { Vector3 val2 = OriginPositions[i] - position; if (((Vector3)(ref val2)).sqrMagnitude <= num) { flag = true; break; } } if (!flag) { continue; } try { if (val != null) { val.Set("MS_Riko_LastSeenTime", nowSeconds); } } catch { } } LogPerf($"SeenUpdate tick interval={12f:0.0} loaded={LoadedRikos.Count} origins={OriginPositions.Count}"); } private static void TryDestroyKilledRikoFromZdo(ZDO zdo, string prefabName, long nowS, string reason) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || string.IsNullOrEmpty(prefabName)) { return; } long num = 0L; try { num = zdo.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num <= 0) { num = nowS; } if (nowS < num) { return; } GameObject val = null; try { if ((Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.FindInstance(zdo.m_uid); } } catch { val = null; } if ((Object)(object)val != (Object)null) { ZNetView val2 = null; try { val2 = val.GetComponent(); } catch { } if ((Object)(object)val2 != (Object)null && val2.IsValid()) { DestroyKilledLoadedRiko(val2, prefabName, reason, playFx: false); return; } } ForceDestroyZDO_AndEnqueue(zdo, prefabName, reason + " notLoaded"); } private static void ProcessLoadedDestroyDueFast() { float time = Time.time; if (time < NextLoadedDestroyCheckTime) { return; } NextLoadedDestroyCheckTime = time + 0.2f; if (LoadedRikos.Count == 0) { return; } long nowSeconds = GetNowSeconds(); SweepRegistryInvalidEntriesIfNeeded(); foreach (KeyValuePair loadedRiko in LoadedRikos) { ZNetView value = loadedRiko.Value; if ((Object)(object)value == (Object)null || !value.IsValid()) { continue; } ZDO val = null; try { val = value.GetZDO(); } catch { } if (val == null) { continue; } int num = 0; long num2 = 0L; try { num = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num != 1) { continue; } try { num2 = val.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num2 <= 0) { num2 = nowSeconds; } if (nowSeconds >= num2) { string prefabName = Utils.GetPrefabName(((Object)((Component)value).gameObject).name); if (DefByPrefab.ContainsKey(prefabName)) { DestroyKilledLoadedRiko(value, prefabName, "LoadedFastDue", playFx: false); } } } } private static void ProcessScheduledDestroyForLoadedRikos() { float time = Time.time; if (time < NextDestroyScanTime) { return; } NextDestroyScanTime = time + 20f; if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || LoadedRikos.Count == 0) { return; } long nowSeconds = GetNowSeconds(); int num = 0; int num2 = 0; int num3 = 0; for (int i = 0; i < Defs.Length; i++) { LivingContainerDef livingContainerDef = Defs[i]; if (livingContainerDef == null || string.IsNullOrEmpty(livingContainerDef.Prefab)) { continue; } int num4 = 0; PurgeZdos.Clear(); bool flag = false; int num5 = 0; try { while (!flag && num5 < 10000) { flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative(livingContainerDef.Prefab, PurgeZdos, ref num4); num5++; } } catch { PurgeZdos.Clear(); continue; } num++; num2 += PurgeZdos.Count; for (int j = 0; j < PurgeZdos.Count; j++) { ZDO val = PurgeZdos[j]; if (val == null) { continue; } int num6 = 0; try { num6 = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num6 == 1) { long num7 = 0L; try { num7 = val.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num7 <= 0) { num7 = nowSeconds; } if (nowSeconds >= num7) { num3++; TryDestroyKilledRikoFromZdo(val, livingContainerDef.Prefab, nowSeconds, "ScheduledDestroy due"); } } } PurgeZdos.Clear(); } LogPerf($"DestroyScan tick interval={20f:0.0} " + $"prefabs={num} scannedZdos={num2} dueKilled={num3}"); } private static void TryRunEmptyWatcher_Server() { //IL_0213: Unknown result type (might be due to invalid IL or missing references) if (!LivingContainerConfig.IsRikoEnabled() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (!_emptyWatcherInProgress && !HasAnyKnownRikoInWorld())) { return; } float time = Time.time; if (!_emptyWatcherInProgress && time < _emptyWatcherNextRunTime) { return; } CleanupItemsCacheIfNeeded(); EnsureZdoVarHashes(); BuildDefCache(); if (!_emptyWatcherInProgress) { _emptyWatcherInProgress = true; _emptyWatcherPrefabIndex = 0; _emptyWatcherSectorIndex = 0; _emptyWatcherZdos.Clear(); _emptyWatcherNextRunTime = time + 30f; } string text = null; while (_emptyWatcherPrefabIndex < Defs.Length) { LivingContainerDef livingContainerDef = Defs[_emptyWatcherPrefabIndex]; if (livingContainerDef != null && !string.IsNullOrEmpty(livingContainerDef.Prefab)) { text = livingContainerDef.Prefab; break; } _emptyWatcherPrefabIndex++; } if (text == null) { _emptyWatcherInProgress = false; return; } bool allZDOsWithPrefabIterative; try { allZDOsWithPrefabIterative = ZDOMan.instance.GetAllZDOsWithPrefabIterative(text, _emptyWatcherZdos, ref _emptyWatcherSectorIndex); } catch { _emptyWatcherInProgress = false; _emptyWatcherZdos.Clear(); return; } if (!allZDOsWithPrefabIterative) { return; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; long nowSeconds = GetNowSeconds(); LivingContainerDef value; bool flag = DefByPrefab.TryGetValue(text, out value); for (int i = 0; i < _emptyWatcherZdos.Count; i++) { ZDO val = _emptyWatcherZdos[i]; if (val == null) { continue; } num++; int num8 = 0; long num9 = 0L; try { num8 = val.GetInt("MS_Riko_Killed", 0); } catch { } try { num9 = val.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num8 == 1) { num2++; continue; } if (num9 > 0) { num2++; continue; } int num10 = 0; try { if (_hashInUse != 0) { num10 = val.GetInt(_hashInUse, 0); } } catch { num10 = 0; } if (num10 != 0) { num3++; continue; } if (!ZdoInventoryIsEmptyDecoded_Cached(text, val, out var _, out var _, out var _)) { num4++; continue; } GameObject val2 = null; try { val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(val.m_uid) : null); } catch { } if ((Object)(object)val2 != (Object)null) { long num11 = 0L; if (flag && value != null && value.DestroyDelay > 0f) { num11 = Mathf.CeilToInt(value.DestroyDelay); } long destroyAtS = nowSeconds + num11; bool num12 = TryMarkKilledIfNeeded(val, text, destroyAtS, "EmptyWatcher"); if (num12) { num5++; } if (!num12) { continue; } ZNetView val3 = null; try { val3 = val2.GetComponent(); } catch { } if ((Object)(object)val3 != (Object)null && val3.IsValid()) { TriggerLoadedRikoVanishWithFx(val3, text, "EmptyWatcher loaded"); num6++; if (num11 <= 0) { DestroyKilledLoadedRiko(val3, text, "EmptyWatcher loaded delay=0", playFx: false); } } } else { ForceDestroyZDO_AndEnqueue(val, text, "EmptyWatcher notLoaded immediate"); num7++; } } LogWatcher($"server EmptyWatcher SUMMARY prefab={text} scanned={num} skippedKilled={num2} skippedInUse={num3} skippedNotEmpty={num4} " + $"markedKilled={num5} immediateLoaded={num6} immediateZdo={num7} cacheSize={_itemsCache.Count}"); _emptyWatcherPrefabIndex++; _emptyWatcherSectorIndex = 0; _emptyWatcherZdos.Clear(); if (_emptyWatcherPrefabIndex >= Defs.Length) { _emptyWatcherInProgress = false; } } private static void EnsureZdoVarHashes() { if (_hashInUse != 0 && _hashItems != 0) { return; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(ZDOVars), "s_inUse"); if (fieldInfo != null) { object value = fieldInfo.GetValue(null); if (value is int) { int num = (int)value; if (num != 0) { _hashInUse = num; } } } } catch { } try { FieldInfo fieldInfo2 = AccessTools.Field(typeof(ZDOVars), "s_items"); if (fieldInfo2 != null) { object value2 = fieldInfo2.GetValue(null); if (value2 is int) { int num2 = (int)value2; if (num2 != 0) { _hashItems = num2; } } } } catch { } if (_hashInUse == 0) { try { _hashInUse = StringExtensionMethods.GetStableHashCode("InUse"); } catch { } } if (_hashItems == 0) { try { _hashItems = StringExtensionMethods.GetStableHashCode("items"); } catch { } } } private static int ComputeQuickHash(string s) { if (string.IsNullOrEmpty(s)) { return 0; } int num = 17; int length = s.Length; num = num * 31 + length; int num2 = Mathf.Min(16, length); for (int i = 0; i < num2; i++) { num = num * 31 + s[i]; } int num3 = Mathf.Min(16, length - num2); for (int j = 0; j < num3; j++) { num = num * 31 + s[length - 1 - j]; } return num; } private static bool ZdoInventoryIsEmptyDecoded_Cached(string rootPrefabName, ZDO zdo, out int decodedCount, out int itemsLen, out string itemsPreview) { //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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) //IL_01ea: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) decodedCount = -1; itemsLen = -1; itemsPreview = ""; if (zdo == null) { return false; } EnsureZdoVarHashes(); string text = ""; byte[] array = null; try { if (_hashItems != 0) { text = zdo.GetString(_hashItems, ""); } } catch { text = ""; } if (text == null) { text = ""; } itemsLen = text.Length; if (string.IsNullOrEmpty(text)) { decodedCount = 0; _itemsCache[zdo.m_uid] = new ItemsCacheEntry { ItemsLen = 0, QuickHash = 0, IsEmpty = true, DecodedCount = 0, LastTouchTime = Time.time }; return true; } int num = ComputeQuickHash(text); if (_itemsCache.TryGetValue(zdo.m_uid, out var value) && value.ItemsLen == itemsLen && value.QuickHash == num) { value.LastTouchTime = Time.time; _itemsCache[zdo.m_uid] = value; decodedCount = value.DecodedCount; return value.IsEmpty; } if (itemsLen <= 0) { try { if (_hashItems != 0) { array = zdo.GetByteArray(_hashItems, (byte[])null); } } catch { array = null; } if (array == null || array.Length == 0) { decodedCount = 0; _itemsCache[zdo.m_uid] = new ItemsCacheEntry { ItemsLen = 0, QuickHash = 0, IsEmpty = true, DecodedCount = 0, LastTouchTime = Time.time }; return true; } } try { int num2 = 4; int num3 = 1; if (LivingContainerConfig.RikoConfigs.TryGetValue(GetRikoId(rootPrefabName), out var value2)) { try { num2 = Mathf.Max(1, value2.ContainerWidth.Value); } catch { } try { num3 = Mathf.Max(1, value2.ContainerHeight.Value); } catch { } } Inventory val = new Inventory("MS_Riko_tmp", (Sprite)null, num2, num3); ZPackage val2 = ((!string.IsNullOrEmpty(text)) ? new ZPackage(text) : new ZPackage(array)); val.Load(val2); int num4 = 0; try { num4 = val.NrOfItems(); } catch { num4 = 0; } decodedCount = num4; bool flag = num4 == 0; _itemsCache[zdo.m_uid] = new ItemsCacheEntry { ItemsLen = itemsLen, QuickHash = num, IsEmpty = flag, DecodedCount = num4, LastTouchTime = Time.time }; return flag; } catch { decodedCount = -2; _itemsCache[zdo.m_uid] = new ItemsCacheEntry { ItemsLen = itemsLen, QuickHash = num, IsEmpty = false, DecodedCount = -2, LastTouchTime = Time.time }; return false; } } private static void CleanupItemsCacheIfNeeded() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (time < _itemsCacheNextCleanupTime) { return; } _itemsCacheNextCleanupTime = time + 60f; if (_itemsCache.Count == 0) { return; } float num = ((_itemsCache.Count > 4096) ? 210f : 600f); if (_itemsCacheKeysTmp == null) { _itemsCacheKeysTmp = new List(256); } _itemsCacheKeysTmp.Clear(); foreach (KeyValuePair item in _itemsCache) { if (time - item.Value.LastTouchTime > num) { _itemsCacheKeysTmp.Add(item.Key); } } for (int i = 0; i < _itemsCacheKeysTmp.Count; i++) { _itemsCache.Remove(_itemsCacheKeysTmp[i]); } if (_itemsCache.Count <= 4096) { return; } _itemsCacheKeysTmp.Clear(); int num2 = Mathf.Min(_itemsCache.Count - 4096, 512); foreach (KeyValuePair item2 in _itemsCache) { _itemsCacheKeysTmp.Add(item2.Key); if (_itemsCacheKeysTmp.Count >= num2) { break; } } for (int j = 0; j < _itemsCacheKeysTmp.Count; j++) { _itemsCache.Remove(_itemsCacheKeysTmp[j]); } } private static bool EnsureServerOwnership(ZNetView nv, ZDO zdo, string reason) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return false; } bool flag = false; try { if ((Object)(object)nv != (Object)null && nv.IsValid()) { if (nv.IsOwner()) { return true; } try { nv.ClaimOwnership(); } catch { } if (nv.IsOwner()) { flag = true; } } } catch { } try { if (!flag && zdo != null) { if (!zdo.IsOwner()) { zdo.SetOwner(ZDOMan.GetSessionID()); } if (zdo.IsOwner()) { flag = true; } } } catch { } if (!flag) { bool flag2 = false; bool flag3 = false; try { flag2 = (Object)(object)nv != (Object)null && nv.IsValid() && nv.IsOwner(); } catch { } try { flag3 = zdo != null && zdo.IsOwner(); } catch { } LogLife(string.Format("server Ownership FAIL reason={0} uid={1} nvOwner={2} zdoOwner={3}", reason, (zdo != null) ? ((object)(ZDOID)(ref zdo.m_uid)).ToString() : "null", flag2, flag3)); } return flag; } private static bool TryMarkKilledIfNeeded(ZDO zdo, string prefab, long destroyAtS, string reason, ZNetView nvMaybe = null) { //IL_00a0: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || string.IsNullOrEmpty(prefab)) { return false; } int num = 0; long num2 = 0L; try { num = zdo.GetInt("MS_Riko_Killed", 0); } catch { } try { num2 = zdo.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num == 1) { return false; } if (num2 > 0) { return false; } if (!EnsureServerOwnership(nvMaybe, zdo, "MarkKilled(" + reason + ")")) { LogLife($"server MarkKilled SKIP_NOT_OWNER prefab={prefab} uid={zdo.m_uid} reason={reason}"); return false; } try { zdo.Set("MS_Riko_Killed", 1); zdo.Set("MS_Riko_DestroyAt", destroyAtS); } catch { LogLife($"server MarkKilled SET_FAIL prefab={prefab} uid={zdo.m_uid} reason={reason}"); return false; } _itemsCache.Remove(zdo.m_uid); LogLife($"server MarkKilled OK prefab={prefab} uid={zdo.m_uid} destroyAt={destroyAtS} reason={reason}"); return true; } private static bool TryPlayVfxOnce(ZDO zdo, LivingContainerDef def, GameObject go, string prefabName, string reason) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || def == null || (Object)(object)go == (Object)null) { return false; } try { if (zdo.GetInt("MS_Riko_VfxPlayed", 0) == 1) { return false; } zdo.Set("MS_Riko_VfxPlayed", 1); } catch { } bool flag = SpawnVfx(def, go); LogLife($"server VFX PLAY prefab={prefabName} uid={zdo.m_uid} spawned={flag} reason={reason}"); return flag; } private static bool TryDecrementWorldCountOnFinalDestroy(ZDO zdo, string prefab, string reason) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || string.IsNullOrEmpty(prefab)) { return false; } try { if (zdo.GetInt("MS_Riko_FinalDestroyCounted", 0) == 1) { return false; } zdo.Set("MS_Riko_FinalDestroyCounted", 1); } catch { } if (!WorldCounts.TryGetValue(prefab, out var value)) { return false; } int num = Mathf.Max(0, value - 1); WorldCounts[prefab] = num; LogPerf($"WorldCounts FINAL_DEC prefab={prefab} {value}->{num} reason={reason} uid={zdo.m_uid}"); return true; } private static void TriggerLoadedRikoVanishWithFx(ZNetView nv, string prefabName, string reason) { if (!((Object)(object)nv == (Object)null) && nv.IsValid()) { ZDO val = null; try { val = nv.GetZDO(); } catch { } if (EnsureServerOwnership(nv, val, "TriggerLoadedVanish(" + reason + ")") && DefByPrefab.TryGetValue(prefabName, out var value) && value != null) { bool flag = TryPlayVfxOnce(val, value, ((Component)nv).gameObject, prefabName, reason); LogLife(string.Format("server TriggerLoadedVanish prefab={0} uid={1} ok={2} reason={3}", prefabName, (val != null) ? ((object)(ZDOID)(ref val.m_uid)).ToString() : "null", flag, reason)); } } } private static void DestroyKilledLoadedRiko(ZNetView nv, string prefabName, string reason, bool playFx) { if ((Object)(object)nv == (Object)null || !nv.IsValid()) { return; } ZDO val = null; try { val = nv.GetZDO(); } catch { } if (!EnsureServerOwnership(nv, val, "DestroyLoaded(" + reason + ")")) { return; } LivingContainerDef value = null; DefByPrefab.TryGetValue(prefabName, out value); if (playFx && value != null) { TryPlayVfxOnce(val, value, ((Component)nv).gameObject, prefabName, reason); } try { TryDecrementWorldCountOnFinalDestroy(val, prefabName, "LoadedDestroy(" + reason + ")"); nv.Destroy(); LogLife(string.Format("server LoadedDestroy OK prefab={0} uid={1} playFx={2} reason={3}", prefabName, (val != null) ? ((object)(ZDOID)(ref val.m_uid)).ToString() : "null", playFx, reason)); } catch { try { if (val != null) { ForceDestroyZDO_AndEnqueue(val, prefabName, "LoadedDestroyFallback(" + reason + ")"); } } catch { } } } private static void ForceDestroyZDO_AndEnqueue(ZDO zdo, string prefabName, string reason) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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) if (zdo == null || ZDOMan.instance == null) { return; } try { if (!zdo.IsOwner()) { zdo.SetOwner(ZDOMan.GetSessionID()); } } catch { } try { if (zdo.IsOwner()) { TryDecrementWorldCountOnFinalDestroy(zdo, prefabName, "DestroyZDO(" + reason + ")"); ZDOMan.instance.DestroyZDO(zdo); LogLife($"server Enqueued DestroyZDO reason={reason} uid={zdo.m_uid}"); } else { LogLife($"server DestroyZDO NOT_OWNER reason={reason} uid={zdo.m_uid}"); } } catch { } _itemsCache.Remove(zdo.m_uid); } private static void TryPurgeExpiredOrKilledRikoZDOs() { //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (!PurgeInProgress && !HasAnyKnownRikoInWorld())) { return; } float time = Time.time; if (!PurgeInProgress) { if (time < NextTtlScanTime) { return; } NextTtlScanTime = time + 45f; PurgeInProgress = true; PurgePrefabIndex = 0; PurgeSectorIndex = 0; PurgeZdos.Clear(); } string text = null; while (PurgePrefabIndex < Defs.Length) { LivingContainerDef livingContainerDef = Defs[PurgePrefabIndex]; if (livingContainerDef != null && !string.IsNullOrEmpty(livingContainerDef.Prefab)) { text = livingContainerDef.Prefab; break; } PurgePrefabIndex++; } if (text == null) { PurgeInProgress = false; return; } bool allZDOsWithPrefabIterative; try { allZDOsWithPrefabIterative = ZDOMan.instance.GetAllZDOsWithPrefabIterative(text, PurgeZdos, ref PurgeSectorIndex); } catch { PurgeInProgress = false; return; } if (!allZDOsWithPrefabIterative) { return; } long nowSeconds = GetNowSeconds(); long num = 1200L; long num2 = 120L; for (int i = 0; i < PurgeZdos.Count; i++) { ZDO val = PurgeZdos[i]; if (val == null) { continue; } int num3 = 0; long num4 = 0L; try { num3 = val.GetInt("MS_Riko_Killed", 0); } catch { } if (num3 == 1) { try { num4 = val.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num4 > 0 && nowSeconds < num4) { continue; } try { if ((Object)(object)ZNetScene.instance.FindInstance(val.m_uid) != (Object)null) { continue; } } catch { } ForceDestroyZDO_AndEnqueue(val, text, "TTL killed=1 due"); continue; } long num5 = 0L; long num6 = 0L; try { num5 = val.GetLong("MS_Riko_SpawnTime", 0L); num6 = val.GetLong("MS_Riko_LastSeenTime", 0L); } catch { continue; } if (num5 <= 0) { try { val.Set("MS_Riko_SpawnTime", nowSeconds); } catch { } try { val.Set("MS_Riko_LastSeenTime", nowSeconds); } catch { } continue; } if (num6 <= 0) { try { val.Set("MS_Riko_LastSeenTime", nowSeconds); } catch { } continue; } long num7 = nowSeconds - num5; long num8 = nowSeconds - num6; if (num7 < num || num8 < num2) { continue; } try { if ((Object)(object)ZNetScene.instance.FindInstance(val.m_uid) != (Object)null) { continue; } } catch { } TryMarkKilledIfNeeded(val, text, nowSeconds, "TTL expired"); ForceDestroyZDO_AndEnqueue(val, text, "TTL expired"); } PurgePrefabIndex++; PurgeSectorIndex = 0; PurgeZdos.Clear(); if (PurgePrefabIndex >= Defs.Length) { PurgeInProgress = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(ZNetView), "Awake")] private static void ZNetView_Awake_Postfix(ZNetView __instance) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if (!LivingContainerConfig.IsRikoEnabled() || (Object)(object)__instance == (Object)null) { return; } GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } BuildDefCache(); string prefabName = Utils.GetPrefabName(((Object)gameObject).name); if (!DefByPrefab.TryGetValue(prefabName, out var value)) { return; } AttachPinComponent(gameObject, value); EnsureRegistryComponent(gameObject); ZDO val = null; try { val = __instance.GetZDO(); } catch { } if (val == null) { return; } int num = 0; long num2 = 0L; try { num = val.GetInt("MS_Riko_Killed", 0); } catch { } try { num2 = val.GetLong("MS_Riko_DestroyAt", 0L); } catch { } if (num == 1 && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { long nowSeconds = GetNowSeconds(); if (num2 <= 0 || nowSeconds >= num2) { DestroyKilledLoadedRiko(__instance, prefabName, "ZNetView.Awake killed due", playFx: true); return; } LogLife($"server KilledObject KEEP_UNTIL prefab={prefabName} uid={val.m_uid} now={nowSeconds} destroyAt={num2}"); } try { long nowSeconds2 = GetNowSeconds(); if (val.GetLong("MS_Riko_SpawnTime", 0L) <= 0) { val.Set("MS_Riko_SpawnTime", nowSeconds2); } if (val.GetInt("MS_Riko_VfxPlayed", -1) < 0) { val.Set("MS_Riko_VfxPlayed", 0); } if (val.GetInt("MS_Riko_FinalDestroyCounted", -1) < 0) { val.Set("MS_Riko_FinalDestroyCounted", 0); } } catch { } } private static void HandleContainerClosed(Container container) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } BuildDefCache(); GameObject gameObject = ((Component)container).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } string prefabName = Utils.GetPrefabName(((Object)gameObject).name); if (!DefByPrefab.TryGetValue(prefabName, out var value)) { return; } ZNetView component = gameObject.GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } Inventory inventory = container.GetInventory(); if (inventory == null || inventory.NrOfItems() != 0) { return; } ZDO val = null; try { val = component.GetZDO(); } catch { } if (val == null) { return; } long nowSeconds = GetNowSeconds(); long num = ((value.DestroyDelay > 0f) ? Mathf.CeilToInt(value.DestroyDelay) : 0); long num2 = nowSeconds + num; bool flag = TryMarkKilledIfNeeded(val, prefabName, num2, "ContainerEmpty", component); LogLife($"server ContainerEmpty MARK_KILLED prefab={prefabName} uid={val.m_uid} delay={value.DestroyDelay:0.00} destroyAt={num2} now={nowSeconds} changed={flag}"); if (flag) { TriggerLoadedRikoVanishWithFx(component, prefabName, "ContainerEmpty"); if (num <= 0) { DestroyKilledLoadedRiko(component, prefabName, "ContainerEmpty delay=0", playFx: false); } } } private static void ApplyContainerConfigToPrefab(LivingContainerDef def, GameObject prefab) { if (def == null || (Object)(object)prefab == (Object)null || !LivingContainerConfig.RikoConfigs.TryGetValue(GetRikoId(def), out var value)) { return; } Container component = prefab.GetComponent(); if ((Object)(object)component == (Object)null) { return; } PrefabContainerTuning prefabContainerTuning = default(PrefabContainerTuning); prefabContainerTuning.Width = Mathf.Max(1, value.ContainerWidth.Value); prefabContainerTuning.Height = Mathf.Max(1, value.ContainerHeight.Value); prefabContainerTuning.LootMin = Mathf.Max(0, value.ContainerLootMin.Value); prefabContainerTuning.LootMax = Mathf.Max(0, value.ContainerLootMax.Value); PrefabContainerTuning prefabContainerTuning2 = prefabContainerTuning; if (prefabContainerTuning2.LootMax < prefabContainerTuning2.LootMin) { prefabContainerTuning2.LootMax = prefabContainerTuning2.LootMin; } if (!AppliedPrefabTuning.TryGetValue(def.Prefab, out var value2) || !value2.Equals(prefabContainerTuning2)) { component.m_width = prefabContainerTuning2.Width; component.m_height = prefabContainerTuning2.Height; if (component.m_defaultItems != null) { component.m_defaultItems.m_dropMin = prefabContainerTuning2.LootMin; component.m_defaultItems.m_dropMax = prefabContainerTuning2.LootMax; } component.m_autoDestroyEmpty = false; AppliedPrefabTuning[def.Prefab] = prefabContainerTuning2; } } [HarmonyPrefix] [HarmonyPatch(typeof(Container), "AddDefaultItems")] private static void Container_AddDefaultItems_Prefix(Container __instance) { //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } ZNetView component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return; } string prefabName = Utils.GetPrefabName(((Object)((Component)component).gameObject).name); BuildDefCache(); if (!DefByPrefab.ContainsKey(prefabName) || !LivingContainerConfig.RikoConfigs.TryGetValue(GetRikoId(prefabName), out var value)) { return; } DropTable defaultItems = __instance.m_defaultItems; if (defaultItems == null) { return; } string text = value.LootTable?.Value ?? string.Empty; if (string.IsNullOrWhiteSpace(text)) { return; } string[] array = text.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); if (defaultItems.m_drops == null) { defaultItems.m_drops = new List(); } defaultItems.m_drops.Clear(); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text2 = array2[i].Trim(); if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#") || text2.StartsWith("//")) { continue; } string[] array3 = text2.Split(new char[1] { ',' }); if (array3.Length < 4) { continue; } string text3 = array3[0].Trim(); if (int.TryParse(array3[1].Trim(), out var result) && int.TryParse(array3[2].Trim(), out var result2) && float.TryParse(array3[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text3); if (!((Object)(object)itemPrefab == (Object)null)) { DropData val = default(DropData); val.m_item = itemPrefab; val.m_stackMin = Mathf.Max(1, result); val.m_stackMax = Mathf.Max(result, result2); val.m_weight = Mathf.Max(0f, result3); val.m_dontScale = false; DropData item = val; defaultItems.m_drops.Add(item); } } } } private static void AttachPinComponent(GameObject go, LivingContainerDef def) { if (!((Object)(object)go == (Object)null) && def != null && !string.IsNullOrEmpty(def.PinSprite)) { LivingContainerPinComponent livingContainerPinComponent = go.GetComponent(); if ((Object)(object)livingContainerPinComponent == (Object)null) { livingContainerPinComponent = go.AddComponent(); } livingContainerPinComponent.PinSprite = def.PinSprite; livingContainerPinComponent.PinText = def.PinText ?? ""; livingContainerPinComponent.PinAnimate = def.PinAnimate; livingContainerPinComponent.PinDoubleSize = def.PinDoubleSize; } } private static bool SpawnVfx(LivingContainerDef def, GameObject go) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (def == null || string.IsNullOrEmpty(def.VfxPrefab)) { return false; } if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)go == (Object)null) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(def.VfxPrefab); if ((Object)(object)prefab == (Object)null) { LogLife("server VFX MISSING prefab=" + def.VfxPrefab); return false; } try { if ((Object)(object)prefab.GetComponent() != (Object)null) { bool flag = (Object)(object)Object.Instantiate(prefab, go.transform.position, go.transform.rotation) != (Object)null; LogLife($"server VFX NET_SPAWN prefab={def.VfxPrefab} ok={flag}"); return flag; } Object.Instantiate(prefab, go.transform.position, go.transform.rotation); LogLife("server VFX LOCAL_SPAWN prefab=" + def.VfxPrefab + " ok=true"); return true; } catch (Exception ex) { LogLife("server VFX SPAWN_FAIL prefab=" + def.VfxPrefab + " error=" + ex.GetType().Name); return false; } } private static void FixSpawnInsideGeometry(GameObject go) { if (!((Object)(object)go == (Object)null)) { RikoSpawnStabilizer rikoSpawnStabilizer = go.GetComponent(); if ((Object)(object)rikoSpawnStabilizer == (Object)null) { rikoSpawnStabilizer = go.AddComponent(); } rikoSpawnStabilizer.Init(); } } private static void StabilizeOnce(GameObject go) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_0069: 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) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null)) { Vector3 position = go.transform.position; go.transform.position = position + Vector3.up * 0.35f; if (TryFindSolidBelow(go.transform.position + Vector3.up * 0.25f, 8f, out var ground)) { go.transform.position = ground + Vector3.up * 0.03f; } else { go.transform.position = position + Vector3.up * 0.1f; } if (IsBodyOverlapping(go.transform.position)) { Transform transform = go.transform; transform.position += Vector3.up * 0.6f; } } } private static bool TryFindSolidBelow(Vector3 origin, float maxDist, out Vector3 ground) { //IL_0001: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) ground = origin; RaycastHit[] array = Physics.RaycastAll(origin, Vector3.down, maxDist, SolidMask, (QueryTriggerInteraction)1); if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((RaycastHit)(ref val)).collider.isTrigger) { ground = ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * 0.02f; return true; } } return false; } private static bool IsBodyOverlapping(Vector3 basePos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Vector3 val = basePos + Vector3.up * 0.25f; Vector3 val2 = basePos + Vector3.up * 1.05f; float num = 0.2f; return Physics.CheckCapsule(val, val2, num, SolidMask, (QueryTriggerInteraction)1); } private static Vector3 PickPoint(Vector3 o, float min, float max) { //IL_0008: 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_0010: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(min, max); Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * num; return new Vector3(o.x + val.x, o.y + 2f, o.z + val.y); } private static void BuildDefCache() { if (DefByPrefab.Count <= 0) { LivingContainerDef[] defs = Defs; foreach (LivingContainerDef livingContainerDef in defs) { ApplyConfig(livingContainerDef); DefByPrefab[livingContainerDef.Prefab] = livingContainerDef; } } } private static void RefreshDefsFromConfig() { for (int i = 0; i < Defs.Length; i++) { ApplyConfig(Defs[i]); } } private static void ApplyConfig(LivingContainerDef def) { if (def != null && LivingContainerConfig.RikoConfigs.TryGetValue(GetRikoId(def), out var value)) { def.CheckInterval = Mathf.Max(1f, value.CheckInterval.Value); def.SpawnChance = Mathf.Clamp01(value.SpawnChance.Value); def.MaxInWorld = Mathf.Max(0, value.MaxInWorld.Value); def.MinDistance = Mathf.Max(0f, value.MinDistance.Value); def.MaxDistance = Mathf.Max(def.MinDistance, value.MaxDistance.Value); def.MinAltitude = value.MinAltitude.Value; def.MaxAltitude = Mathf.Max(def.MinAltitude, value.MaxAltitude.Value); } } private static string GetRikoId(LivingContainerDef def) { if (def == null) { return string.Empty; } return GetRikoId(def.Prefab); } private static string GetRikoId(string prefabName) { string text = prefabName ?? string.Empty; if (!text.StartsWith("EncounterCreatureRiko", StringComparison.Ordinal) || !text.EndsWith("DO", StringComparison.Ordinal)) { return text; } return text.Substring("EncounterCreatureRiko".Length, text.Length - "EncounterCreatureRiko".Length - "DO".Length); } private static long GetNowSeconds() { try { if ((Object)(object)ZNet.instance != (Object)null) { long num = ZNet.instance.GetTime().Ticks / 10000000; if (num > 0) { return num; } } } catch { } return DateTime.UtcNow.Ticks / 10000000; } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [HarmonyPatch(typeof(RandomSpeak), "Speak")] public static class RandomSpeakUpgrade { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private struct WeightedText { public string text; public float weight; public WeightedText(string text, float weight) { this.text = text; this.weight = weight; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private class RikoPrefabConfig { public bool useGreeting; public bool useGeneral; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(1)] public WeightedText[] localTexts; } private const string ZdoGreetingKey = "riko_greeted"; private const string ZdoCycleKey = "riko_cycle"; private const string ZdoCycleIndexKey = "riko_cycle_index"; private static readonly WeightedText[] GeneralTexts = new WeightedText[12] { new WeightedText("$encounter_riko_general_text_1_DO", 0.05f), new WeightedText("$encounter_riko_general_text_2_DO", 0.05f), new WeightedText("$encounter_riko_general_text_3_DO", 0.05f), new WeightedText("$encounter_riko_general_text_4_DO", 0.05f), new WeightedText("$encounter_riko_general_text_5_DO", 0.05f), new WeightedText("$encounter_riko_general_text_6_DO", 0.05f), new WeightedText("$encounter_riko_general_text_7_DO", 0.05f), new WeightedText("$encounter_riko_general_text_8_DO", 0.05f), new WeightedText("$encounter_riko_general_text_9_DO", 0.05f), new WeightedText("$encounter_riko_general_text_10_DO", 0.05f), new WeightedText("$encounter_riko_general_text_11_DO", 0.05f), new WeightedText("$encounter_riko_general_text_12_DO", 0.05f) }; private static readonly WeightedText[] BlackforestLocalTexts = new WeightedText[5] { new WeightedText("$encounter_riko_blackforest_text_1_DO", 1f), new WeightedText("$encounter_riko_blackforest_text_2_DO", 0.8f), new WeightedText("$encounter_riko_blackforest_text_3_DO", 0.8f), new WeightedText("$encounter_riko_blackforest_text_4_DO", 0.8f), new WeightedText("$encounter_riko_blackforest_text_5_DO", 0.8f) }; private static readonly WeightedText[] SwampLocalTexts = new WeightedText[5] { new WeightedText("$encounter_riko_swamp_text_1_DO", 1f), new WeightedText("$encounter_riko_swamp_text_2_DO", 0.8f), new WeightedText("$encounter_riko_swamp_text_3_DO", 0.8f), new WeightedText("$encounter_riko_swamp_text_4_DO", 0.8f), new WeightedText("$encounter_riko_swamp_text_5_DO", 0.8f) }; private static readonly WeightedText[] MountainLocalTexts = new WeightedText[5] { new WeightedText("$encounter_riko_mountain_text_1_DO", 1f), new WeightedText("$encounter_riko_mountain_text_2_DO", 0.8f), new WeightedText("$encounter_riko_mountain_text_3_DO", 0.8f), new WeightedText("$encounter_riko_mountain_text_4_DO", 0.8f), new WeightedText("$encounter_riko_mountain_text_5_DO", 0.8f) }; private static readonly WeightedText[] PlainsLocalTexts = new WeightedText[5] { new WeightedText("$encounter_riko_plains_text_1_DO", 1f), new WeightedText("$encounter_riko_plains_text_2_DO", 0.8f), new WeightedText("$encounter_riko_plains_text_3_DO", 0.8f), new WeightedText("$encounter_riko_plains_text_4_DO", 0.8f), new WeightedText("$encounter_riko_plains_text_5_DO", 0.8f) }; private static readonly WeightedText[] MistlandsLocalTexts = new WeightedText[5] { new WeightedText("$encounter_riko_mistlands_text_1_DO", 1f), new WeightedText("$encounter_riko_mistlands_text_2_DO", 0.8f), new WeightedText("$encounter_riko_mistlands_text_3_DO", 0.8f), new WeightedText("$encounter_riko_mistlands_text_4_DO", 0.8f), new WeightedText("$encounter_riko_mistlands_text_5_DO", 0.8f) }; private static readonly WeightedText[] AshlandsLocalTexts = new WeightedText[5] { new WeightedText("$encounter_riko_ashlands_text_1_DO", 1f), new WeightedText("$encounter_riko_ashlands_text_2_DO", 0.8f), new WeightedText("$encounter_riko_ashlands_text_3_DO", 0.8f), new WeightedText("$encounter_riko_ashlands_text_4_DO", 0.8f), new WeightedText("$encounter_riko_ashlands_text_5_DO", 0.8f) }; private static readonly Dictionary PrefabConfigs = new Dictionary { { "EncounterCreatureRikoBlackforestDO", new RikoPrefabConfig { useGreeting = true, useGeneral = true, localTexts = BlackforestLocalTexts } }, { "EncounterCreatureRikoSwampDO", new RikoPrefabConfig { useGreeting = true, useGeneral = true, localTexts = SwampLocalTexts } }, { "EncounterCreatureRikoMountainDO", new RikoPrefabConfig { useGreeting = true, useGeneral = true, localTexts = MountainLocalTexts } }, { "EncounterCreatureRikoPlainsDO", new RikoPrefabConfig { useGreeting = true, useGeneral = true, localTexts = PlainsLocalTexts } }, { "EncounterCreatureRikoMistlandsDO", new RikoPrefabConfig { useGreeting = true, useGeneral = true, localTexts = MistlandsLocalTexts } }, { "EncounterCreatureRikoAshlandsDO", new RikoPrefabConfig { useGreeting = true, useGeneral = true, localTexts = AshlandsLocalTexts } } }; private static bool Prefix(RandomSpeak __instance) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (!((MonoBehaviour)__instance).IsInvoking()) { ((MonoBehaviour)__instance).InvokeRepeating("Speak", Random.Range(0f, __instance.m_interval), __instance.m_interval); } string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); if (!PrefabConfigs.TryGetValue(prefabName, out var value)) { return true; } if (Random.value > __instance.m_chance) { return false; } if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } if (Vector3.Distance(((Component)__instance).transform.position, ((Component)Player.m_localPlayer).transform.position) > __instance.m_triggerDistance) { return false; } if (__instance.m_onlyOnItemStand && !Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponentInParent())) { return false; } float dayFraction = EnvMan.instance.GetDayFraction(); if (!IsTimeAllowed(__instance, dayFraction)) { return false; } ZNetView component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return false; } ZDO zDO = component.GetZDO(); string text; if (value.useGreeting && !zDO.GetBool("riko_greeted", false)) { zDO.Set("riko_greeted", true); text = value.localTexts[0].text; } else { text = GetNextFromCycle(zDO, value); if (string.IsNullOrEmpty(text)) { return false; } } __instance.m_speakEffects.Create(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1); Chat.instance.SetNpcText(((Component)__instance).gameObject, __instance.m_offset, __instance.m_cullDistance, __instance.m_ttl, __instance.m_topic, text, __instance.m_useLargeDialog); return false; } private static string GetNextFromCycle(ZDO zdo, RikoPrefabConfig config) { string text = zdo.GetString("riko_cycle", ""); int num = zdo.GetInt("riko_cycle_index", 0); if (string.IsNullOrEmpty(text)) { text = BuildNewCycle(config); num = 0; } string[] array = text.Split(new char[1] { ',' }); if (num >= array.Length) { text = BuildNewCycle(config); num = 0; array = text.Split(new char[1] { ',' }); } int index = int.Parse(array[num]); zdo.Set("riko_cycle_index", num + 1); zdo.Set("riko_cycle", text); return ResolveTextByIndex(index, config); } private static string BuildNewCycle(RikoPrefabConfig config) { List list = new List(); List list2 = new List(); for (int i = 1; i < config.localTexts.Length; i++) { list.Add(i); list2.Add(config.localTexts[i].weight); } if (config.useGeneral) { for (int j = 0; j < GeneralTexts.Length; j++) { list.Add(100 + j); list2.Add(GeneralTexts[j].weight); } } List list3 = new List(); while (list.Count > 0) { float num = 0f; foreach (float item in list2) { num += item; } float num2 = Random.Range(0f, num); float num3 = 0f; for (int k = 0; k < list.Count; k++) { num3 += list2[k]; if (num2 <= num3) { list3.Add(list[k]); list.RemoveAt(k); list2.RemoveAt(k); break; } } } StringBuilder stringBuilder = new StringBuilder(); for (int l = 0; l < list3.Count; l++) { if (l > 0) { stringBuilder.Append(","); } stringBuilder.Append(list3[l]); } return stringBuilder.ToString(); } private static string ResolveTextByIndex(int index, RikoPrefabConfig config) { if (index >= 100) { return GeneralTexts[index - 100].text; } return config.localTexts[index].text; } private static bool IsTimeAllowed(RandomSpeak rs, float dayFraction) { if (!rs.m_invertTod) { if (!(dayFraction < rs.m_minTOD)) { return !(dayFraction > rs.m_maxTOD); } return false; } if (!(dayFraction > rs.m_minTOD)) { return !(dayFraction < rs.m_maxTOD); } return false; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] internal static class SSU_Log { private static readonly ManualLogSource _log = Logger.CreateLogSource("SlingshotSecondaryUnlock"); public static void Info(string s) { _log.LogInfo((object)s); } public static void Err(string s) { _log.LogError((object)s); } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] internal static class SSU_Whitelist { private static readonly string[] _names; internal static readonly HashSet Names; internal static readonly HashSet NameHashes; static SSU_Whitelist() { _names = new string[1] { "BowFrostcallerIceDO" }; Names = new HashSet(StringComparer.Ordinal); NameHashes = new HashSet(); string[] names = _names; foreach (string text in names) { Names.Add(text); NameHashes.Add(StringExtensionMethods.GetStableHashCode(text)); } } public static bool Match(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } if (Names.Contains(prefabName)) { return true; } return NameHashes.Contains(StringExtensionMethods.GetStableHashCode(prefabName)); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] internal static class SSU_State { private static readonly Dictionary _secondaryDrawActive = new Dictionary(); private static int Key(Player p) { if (!Object.op_Implicit((Object)(object)p)) { return 0; } return ((Object)p).GetInstanceID(); } public static bool IsSecondaryDrawActive(Player p) { int key = Key(p); bool value; return _secondaryDrawActive.TryGetValue(key, out value) && value; } public static void SetSecondaryDrawActive(Player p, bool active) { int key = Key(p); if (active) { _secondaryDrawActive[key] = true; } else { _secondaryDrawActive.Remove(key); } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] internal static class SSU_Util { private static readonly BindingFlags InstAll = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly MethodInfo MI_UpdateWeaponLoading = typeof(Player).GetMethod("UpdateWeaponLoading", InstAll, null, new Type[2] { typeof(ItemData), typeof(float) }, null); private static readonly MethodInfo MI_UpdateAttackBowDraw = typeof(Player).GetMethod("UpdateAttackBowDraw", InstAll, null, new Type[2] { typeof(ItemData), typeof(float) }, null); private static readonly MethodInfo MI_InPlaceMode = typeof(Player).GetMethod("InPlaceMode", InstAll, null, Type.EmptyTypes, null); public static string GetPrefabName(ItemData item) { if (item == null) { return null; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } try { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance != (Object)null) { foreach (GameObject item2 in instance.m_items) { if (Object.op_Implicit((Object)(object)item2) && item2.GetComponent()?.m_itemData?.m_shared == item.m_shared) { return ((Object)item2).name; } } } } catch { } return null; } private static FieldInfo FindField(Type t, string name) { while (t != null) { FieldInfo field = t.GetField(name, InstAll); if (field != null) { return field; } t = t.BaseType; } return null; } public static T GetField<[<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] T>(object obj, string name) { if (obj == null) { return default(T); } FieldInfo fieldInfo = FindField(obj.GetType(), name); if (fieldInfo == null) { return default(T); } object value = fieldInfo.GetValue(obj); if (value is T) { return (T)value; } try { return (T)Convert.ChangeType(value, typeof(T)); } catch { return default(T); } } public static void SetField(object obj, string name, object value) { if (obj != null) { FieldInfo fieldInfo = FindField(obj.GetType(), name); if (!(fieldInfo == null)) { fieldInfo.SetValue(obj, value); } } } private static bool CallBoolNoArgs(object obj, MethodInfo mi) { if (obj == null || mi == null) { return false; } try { object obj2 = mi.Invoke(obj, Array.Empty()); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } public static bool InPlaceMode(Player p) { return CallBoolNoArgs(p, MI_InPlaceMode); } public static void CallUpdateWeaponLoading(Player p, ItemData weapon, float dt) { if ((Object)(object)p == (Object)null || MI_UpdateWeaponLoading == null) { return; } try { MI_UpdateWeaponLoading.Invoke(p, new object[2] { weapon, dt }); } catch { } } public static void CallUpdateAttackBowDraw(Player p, ItemData weapon, float dt) { if ((Object)(object)p == (Object)null || MI_UpdateAttackBowDraw == null) { return; } try { MI_UpdateAttackBowDraw.Invoke(p, new object[2] { weapon, dt }); } catch { } } public static void HandleLoopingAbort(Player p) { object field = GetField(p, "m_currentAttack"); if (field == null || !GetField(field, "m_loopingAttack")) { return; } bool field2 = GetField(p, "m_currentAttackIsSecondary"); bool field3 = GetField(p, "m_attackHold"); bool field4 = GetField(p, "m_secondaryAttackHold"); if (field2 ? field4 : field3) { return; } MethodInfo method = field.GetType().GetMethod("Abort", InstAll, null, Type.EmptyTypes, null); if (method == null) { return; } try { method.Invoke(field, Array.Empty()); } catch { } } public static void HandleSlingshotAttackInput(Player p, float dt) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if ((Object)(object)p == (Object)null) { return; } ItemData currentWeapon = ((Humanoid)p).GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.m_shared == null || (int)currentWeapon.m_shared.m_itemType != 4 || !currentWeapon.m_shared.m_attack.m_bowDraw || !SSU_Whitelist.Match(GetPrefabName(currentWeapon)) || InPlaceMode(p)) { return; } CallUpdateWeaponLoading(p, currentWeapon, dt); bool field = GetField(p, "m_secondaryAttackHold"); bool field2 = GetField(p, "m_attackHold"); bool flag = currentWeapon.m_shared.m_secondaryAttack != null; bool flag2; if (SSU_State.IsSecondaryDrawActive(p)) { flag2 = true; } else { flag2 = flag && field && !field2; if (flag2) { SSU_State.SetSecondaryDrawActive(p, active: true); } } if (flag2) { SharedData shared = currentWeapon.m_shared; Attack attack = shared.m_attack; Attack secondaryAttack = shared.m_secondaryAttack; if (secondaryAttack == null) { CallUpdateAttackBowDraw(p, currentWeapon, dt); } else { bool field3 = GetField(p, "m_attackHold"); try { shared.m_attack = secondaryAttack; SetField(p, "m_attackHold", field); CallUpdateAttackBowDraw(p, currentWeapon, dt); } finally { shared.m_attack = attack; SetField(p, "m_attackHold", field3); } float field4 = GetField(p, "m_attackDrawTime"); if (!field && field4 <= 0f) { SSU_State.SetSecondaryDrawActive(p, active: false); } } } else { CallUpdateAttackBowDraw(p, currentWeapon, dt); } HandleLoopingAbort(p); } } [HarmonyPatch(typeof(Player), "PlayerAttackInput")] internal static class SSU_PlayerAttackInput_Patch { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] private static bool Prefix(Player __instance, float dt) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 try { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.m_shared == null) { return true; } if ((int)currentWeapon.m_shared.m_itemType != 4) { return true; } if (!SSU_Whitelist.Match(SSU_Util.GetPrefabName(currentWeapon))) { return true; } SSU_Util.HandleSlingshotAttackInput(__instance, dt); return false; } catch (Exception ex) { SSU_Log.Err("SlingshotSecondaryUnlock.PlayerAttackInput error: " + ex.GetType().Name + ": " + ex.Message); return true; } } } namespace SharedTools { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static class ZDOCleanup { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ZDOCleanupPatch { private static void Postfix(ZNetScene __instance) { ((MonoBehaviour)__instance).StartCoroutine(DelayedCleanup()); } private static IEnumerator DelayedCleanup() { yield return (object)new WaitForSeconds(1f); RunCleanup(); } } private static readonly string[] _oldProjectilePrefabs = new string[3] { "projectile_stormcaller_staff_sphere_DO", "projectile_frostcaller_staff_shard_DO", "projectile_lightcaller_staff_sphere_DO" }; public static void RunCleanup() { if ((Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null) { return; } int num = 0; int num2 = 0; foreach (ZDO item in ZDOMan.instance.m_objectsByID.Values.ToList()) { GameObject prefab = ZNetScene.instance.GetPrefab(item.m_prefab); if ((Object)(object)prefab == (Object)null) { ZDOMan.instance.DestroyZDO(item); num2++; } else if (_oldProjectilePrefabs.Contains(((Object)prefab).name)) { ZDOMan.instance.DestroyZDO(item); num++; } } if (num > 0 || num2 > 0) { ZLog.Log((object)$"ZDOCleanup: Cleaned {num} old projectiles and {num2} orphan ZDO(s)."); } else { ZLog.Log((object)"ZDOCleanup: No old or orphan ZDOs found."); } } } } namespace PieceManager { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [PublicAPI] public static class MaterialReplacer { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] public enum ShaderType { PieceShader, VegetationShader, RockShader, RugShader, GrassShader, CustomCreature, UseUnityShader } private static readonly Dictionary ObjectToSwap; private static readonly Dictionary OriginalMaterials; private static readonly Dictionary ObjectsForShaderReplace; private static readonly HashSet CachedShaders; private static bool hasRun; static MaterialReplacer() { //IL_0033: 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_006c: Expected O, but got Unknown CachedShaders = new HashSet(); hasRun = false; OriginalMaterials = new Dictionary(); ObjectToSwap = new Dictionary(); ObjectsForShaderReplace = new Dictionary(); new Harmony("org.bepinex.helpers.PieceManager").Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZoneSystem), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MaterialReplacer), "ReplaceAllMaterialsWithOriginal", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static void RegisterGameObjectForShaderSwap(GameObject go, ShaderType type) { if (!ObjectsForShaderReplace.ContainsKey(go)) { ObjectsForShaderReplace.Add(go, type); } } public static void RegisterGameObjectForMatSwap(GameObject go, bool isJotunnMock = false) { if (!ObjectToSwap.ContainsKey(go)) { ObjectToSwap.Add(go, isJotunnMock); } } private static void GetAllMaterials() { Material[] array = Resources.FindObjectsOfTypeAll(); foreach (Material val in array) { OriginalMaterials[((Object)val).name] = val; } } [HarmonyPriority(700)] private static void ReplaceAllMaterialsWithOriginal() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType == 4 || hasRun) { return; } if (OriginalMaterials.Count == 0) { GetAllMaterials(); } foreach (KeyValuePair item in ObjectToSwap) { GameObject key = item.Key; bool value = item.Value; ProcessGameObjectMaterials(key, value); } AssetBundle[] array = Resources.FindObjectsOfTypeAll(); foreach (AssetBundle val in array) { IEnumerable enumerable3; try { IEnumerable enumerable2; if (!val.isStreamedSceneAssetBundle || !Object.op_Implicit((Object)(object)val)) { IEnumerable enumerable = val.LoadAllAssets(); enumerable2 = enumerable; } else { enumerable2 = from shader in ((IEnumerable)val.GetAllAssetNames()).Select((Func)val.LoadAsset) where (Object)(object)shader != (Object)null select shader; } enumerable3 = enumerable2; } catch (Exception) { continue; } if (enumerable3 == null) { continue; } foreach (Shader item2 in enumerable3) { CachedShaders.Add(item2); } } foreach (KeyValuePair item3 in ObjectsForShaderReplace) { GameObject key2 = item3.Key; ShaderType value2 = item3.Value; ProcessGameObjectShaders(key2, value2); } hasRun = true; } private static void ProcessGameObjectMaterials(GameObject go, bool isJotunnMock) { Renderer[] componentsInChildren = go.GetComponentsInChildren(true); foreach (Renderer obj in componentsInChildren) { Material[] sharedMaterials = obj.sharedMaterials.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Material material) => ReplaceMaterial(material, isJotunnMock)).ToArray(); obj.sharedMaterials = sharedMaterials; } } private static Material ReplaceMaterial(Material originalMaterial, bool isJotunnMock) { string text = (isJotunnMock ? "JVLmock_" : "_REPLACE_"); if (!((Object)originalMaterial).name.StartsWith(text, StringComparison.Ordinal)) { return originalMaterial; } string text2 = ((Object)originalMaterial).name.Replace(" (Instance)", "").Replace(text, ""); if (OriginalMaterials.TryGetValue(text2, out var value)) { return value; } Debug.LogWarning((object)("No suitable material found to replace: " + text2)); return originalMaterial; } private static void ProcessGameObjectShaders(GameObject go, ShaderType shaderType) { Renderer[] componentsInChildren = go.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = componentsInChildren[i].sharedMaterials; foreach (Material val in sharedMaterials) { if ((Object)(object)val != (Object)null) { val.shader = GetShaderForType(val.shader, shaderType, ((Object)val.shader).name); } } } } private static Shader GetShaderForType(Shader orig, ShaderType shaderType, string originalShaderName) { return (Shader)(shaderType switch { ShaderType.PieceShader => FindShaderWithName(orig, "Custom/Piece"), ShaderType.VegetationShader => FindShaderWithName(orig, "Custom/Vegetation"), ShaderType.RockShader => FindShaderWithName(orig, "Custom/StaticRock"), ShaderType.RugShader => FindShaderWithName(orig, "Custom/Rug"), ShaderType.GrassShader => FindShaderWithName(orig, "Custom/Grass"), ShaderType.CustomCreature => FindShaderWithName(orig, "Custom/Creature"), ShaderType.UseUnityShader => FindShaderWithName(orig, ((Object)(object)FindShaderWithName(orig, originalShaderName) != (Object)null) ? originalShaderName : "ToonDeferredShading2017"), _ => FindShaderWithName(orig, "Standard"), }); } public static Shader FindShaderWithName(Shader origShader, string name) { foreach (Shader cachedShader in CachedShaders) { if (((Object)cachedShader).name == name) { return cachedShader; } } return origShader; } } [PublicAPI] public enum CraftingTable { None, [InternalName("piece_workbench")] Workbench, [InternalName("piece_cauldron")] Cauldron, [InternalName("forge")] Forge, [InternalName("piece_artisanstation")] ArtisanTable, [InternalName("piece_stonecutter")] StoneCutter, [InternalName("piece_magetable")] MageTable, [InternalName("blackforge")] BlackForge, [InternalName("piece_preptable")] FoodPreparationTable, [InternalName("piece_MeadCauldron")] MeadKetill, Custom } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [PublicAPI] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public class ExtensionList { public readonly List ExtensionStations = new List(); public void Set(CraftingTable table, int maxStationDistance = 5) { ExtensionStations.Add(new ExtensionConfig { Table = table, maxStationDistance = maxStationDistance }); } public void Set(string customTable, int maxStationDistance = 5) { ExtensionStations.Add(new ExtensionConfig { Table = CraftingTable.Custom, custom = customTable, maxStationDistance = maxStationDistance }); } } public struct ExtensionConfig { public CraftingTable Table; public float maxStationDistance; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public string custom; } [PublicAPI] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public class CraftingStationList { public readonly List Stations = new List(); public void Set(CraftingTable table) { Stations.Add(new CraftingStationConfig { Table = table }); } public void Set(string customTable) { Stations.Add(new CraftingStationConfig { Table = CraftingTable.Custom, custom = customTable }); } } public struct CraftingStationConfig { public CraftingTable Table; public int level; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public string custom; } [PublicAPI] public enum BuildPieceCategory { Misc = 0, Crafting = 1, BuildingWorkbench = 2, BuildingStonecutter = 3, Furniture = 4, All = 100, Custom = 99 } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class RequiredResourcesList { public readonly List Requirements = new List(); public void Add(string item, int amount, bool recover) { Requirements.Add(new Requirement { itemName = item, amount = amount, recover = recover }); } } public struct Requirement { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(1)] public string itemName; public int amount; public bool recover; } public struct SpecialProperties { [Description("Admins should be the only ones that can build this piece.")] public bool AdminOnly; [Description("Turns off generating a config for this build piece.")] public bool NoConfig; } [PublicAPI] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public class BuildingPieceCategory { public BuildPieceCategory Category; public string custom = ""; public void Set(BuildPieceCategory category) { Category = category; } public void Set(string customCategory) { Category = BuildPieceCategory.Custom; custom = customCategory; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class PieceTool { public readonly HashSet Tools = new HashSet(); public void Add(string tool) { Tools.Add(tool); } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [PublicAPI] public class BuildPiece { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] internal class PieceConfig { public ConfigEntry craft; public ConfigEntry category; public ConfigEntry customCategory; public ConfigEntry tools; public ConfigEntry extensionTable; public ConfigEntry customExtentionTable; public ConfigEntry maxStationDistance; public ConfigEntry table; public ConfigEntry customTable; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] [UsedImplicitly] public string Category; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 2, 1 })] [UsedImplicitly] public Action CustomDrawer; } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class SerializedRequirements { public readonly List Reqs; public SerializedRequirements(List reqs) { Reqs = reqs; } public SerializedRequirements(string reqs) { Reqs = reqs.Split(new char[1] { ',' }).Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (string r) => { string[] array = r.Split(new char[1] { ':' }); Requirement result = default(Requirement); result.itemName = array[0]; result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2); bool result3 = default(bool); result.recover = array.Length <= 2 || !bool.TryParse(array[2], out result3) || result3; return result; }).ToList(); } public override string ToString() { return string.Join(",", Reqs.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement r) => $"{r.itemName}:{r.amount}:{r.recover}")); } [return: <5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public static ItemDrop fetchByName(ObjectDB objectDB, string name) { GameObject itemPrefab = objectDB.GetItemPrefab(name); ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent() : null); if ((Object)(object)obj == (Object)null) { Debug.LogWarning((object)(((!string.IsNullOrWhiteSpace(((Object)plugin).name)) ? ("[" + ((Object)plugin).name + "]") : "") + " The required item '" + name + "' does not exist.")); } return obj; } public static Requirement[] toPieceReqs(SerializedRequirements craft) { return craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func)([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement r) => r.itemName), (Func)([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement r) => { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ItemDrop val = ResItem(r); return (val != null) ? new Requirement { m_amount = r.amount, m_resItem = val, m_recover = r.recover } : ((Requirement)null); })).Values.Where([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement v) => v != null).ToArray(); [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] static ItemDrop ResItem(Requirement r) { return fetchByName(ObjectDB.instance, r.itemName); } } } internal static readonly List registeredPieces = new List(); private static readonly Dictionary pieceMap = new Dictionary(); internal static Dictionary pieceConfigs = new Dictionary(); internal List Conversions = new List(); internal List conversions = new List(); [Description("Disables generation of the configs for your pieces. This is global, this turns it off for all pieces in your mod.")] public static bool ConfigurationEnabled = true; public readonly GameObject Prefab; [Description("Specifies the resources needed to craft the piece.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the building piece should need.")] public readonly RequiredResourcesList RequiredItems = new RequiredResourcesList(); [Description("Sets the category for the building piece.")] public readonly BuildingPieceCategory Category = new BuildingPieceCategory(); [Description("Specifies the tool needed to build your piece.\nUse .Add to add a tool.")] public readonly PieceTool Tool = new PieceTool(); [Description("Specifies the crafting station needed to build your piece.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.")] public CraftingStationList Crafting = new CraftingStationList(); [Description("Makes this piece a station extension")] public ExtensionList Extension = new ExtensionList(); [Description("Change the extended/special properties of your build piece.")] public SpecialProperties SpecialProperties; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] [Description("Specifies a config entry which toggles whether a recipe is active.")] public ConfigEntryBase RecipeIsActive; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private LocalizeKey _name; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private LocalizeKey _description; internal string[] activeTools; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static object configManager; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static Localization _english; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] internal static BaseUnityPlugin _plugin = null; private static bool hasConfigSync = true; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static object _configSync; public LocalizeKey Name { get { LocalizeKey name = _name; if (name != null) { return name; } Piece component = Prefab.GetComponent(); if (component.m_name.StartsWith("$")) { _name = new LocalizeKey(component.m_name); } else { string text = "$piece_" + ((Object)Prefab).name.Replace(" ", "_"); _name = new LocalizeKey(text).English(component.m_name); component.m_name = text; } return _name; } } public LocalizeKey Description { get { LocalizeKey description = _description; if (description != null) { return description; } Piece component = Prefab.GetComponent(); if (component.m_description.StartsWith("$")) { _description = new LocalizeKey(component.m_description); } else { string text = "$piece_" + ((Object)Prefab).name.Replace(" ", "_") + "_description"; _description = new LocalizeKey(text).English(component.m_description); component.m_description = text; } return _description; } } private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English")); internal static BaseUnityPlugin plugin { get { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown if (_plugin != null) { return _plugin; } IEnumerable source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); return _plugin; } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static object configSync { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] get { if (_configSync != null || !hasConfigSync) { return _configSync; } Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync"); if ((object)type != null) { _configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " PieceManager"); type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString()); type.GetProperty("IsLocked").SetValue(_configSync, true); } else { hasConfigSync = false; } return _configSync; } } public BuildPiece(string assetBundleFileName, string prefabName, string folderName = "assets") : this(PiecePrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName) { } public BuildPiece(AssetBundle bundle, string prefabName) { Prefab = PiecePrefabManager.RegisterPrefab(bundle, prefabName); registeredPieces.Add(this); } internal static void Patch_FejdStartup(FejdStartup __instance) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Expected O, but got Unknown //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Expected O, but got Unknown //IL_0849: Unknown result type (might be due to invalid IL or missing references) //IL_0853: Expected O, but got Unknown //IL_05f6: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Expected O, but got Unknown //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_06a1: Expected O, but got Unknown //IL_08b9: Unknown result type (might be due to invalid IL or missing references) //IL_08c3: Expected O, but got Unknown //IL_0ac1: Unknown result type (might be due to invalid IL or missing references) //IL_0acb: Expected O, but got Unknown //IL_0b5a: Unknown result type (might be due to invalid IL or missing references) //IL_0b64: Expected O, but got Unknown Type configManagerType = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager"); configManager = ((configManagerType == null) ? null : Chainloader.ManagerObject.GetComponent(configManagerType)); foreach (BuildPiece registeredPiece in registeredPieces) { registeredPiece.activeTools = registeredPiece.Tool.Tools.DefaultIfEmpty("Hammer").ToArray(); if (registeredPiece.Category.Category != BuildPieceCategory.Custom) { registeredPiece.Prefab.GetComponent().m_category = (PieceCategory)registeredPiece.Category.Category; } else { registeredPiece.Prefab.GetComponent().m_category = PiecePrefabManager.GetCategory(registeredPiece.Category.custom); } } if (!ConfigurationEnabled) { return; } bool saveOnConfigSet = plugin.Config.SaveOnConfigSet; plugin.Config.SaveOnConfigSet = false; foreach (BuildPiece registeredPiece2 in registeredPieces) { BuildPiece piece = registeredPiece2; if (piece.SpecialProperties.NoConfig) { continue; } PieceConfig pieceConfig2 = (pieceConfigs[piece] = new PieceConfig()); PieceConfig cfg = pieceConfig2; Piece piecePrefab2 = piece.Prefab.GetComponent(); string pieceName = piecePrefab2.m_name; string englishName = new Regex("[=\\n\\t\\\\\"\\'\\[\\]]*").Replace(english.Localize(pieceName), "").Trim(); string localizedName = Localization.instance.Localize(pieceName).Trim(); int order = 0; cfg.category = config(englishName, "Build Table Category", piece.Category.Category, new ConfigDescription("Build Category where " + localizedName + " is available.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Category = localizedName } })); ConfigurationManagerAttributes customTableAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), Browsable = (cfg.category.Value == BuildPieceCategory.Custom), Category = localizedName }; cfg.customCategory = config(englishName, "Custom Build Category", piece.Category.custom, new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); cfg.category.SettingChanged += BuildTableConfigChanged; cfg.customCategory.SettingChanged += BuildTableConfigChanged; if (cfg.category.Value == BuildPieceCategory.Custom) { piecePrefab2.m_category = PiecePrefabManager.GetCategory(cfg.customCategory.Value); } else { piecePrefab2.m_category = (PieceCategory)cfg.category.Value; } cfg.tools = config(englishName, "Tools", string.Join(", ", piece.activeTools), new ConfigDescription("Comma separated list of tools where " + localizedName + " is available.", (AcceptableValueBase)null, new object[1] { customTableAttributes })); piece.activeTools = (from s in cfg.tools.Value.Split(new char[1] { ',' }) select s.Trim()).ToArray(); cfg.tools.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { Inventory[] source = (from c in Player.s_players.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Player p) => ((Humanoid)p).GetInventory()).Concat(from c in Object.FindObjectsOfType() select c.GetInventory()) where c != null select c).ToArray(); Dictionary> dictionary = (from kv in (from i in (from p in ObjectDB.instance.m_items select p.GetComponent() into c where Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((Component)c).GetComponent()) select c).Concat(ItemDrop.s_instances) select new KeyValuePair(Utils.GetPrefabName(((Component)i).gameObject), i.m_itemData)).Concat(from i in source.SelectMany([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Inventory i) => i.GetAllItems()) select new KeyValuePair(((Object)i.m_dropPrefab).name, i)) where Object.op_Implicit((Object)(object)kv.Value.m_shared.m_buildPieces) group kv by kv.Key).ToDictionary([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (IGrouping> g) => g.Key, [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (IGrouping> g) => g.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (KeyValuePair kv) => kv.Value.m_shared.m_buildPieces).Distinct().ToList()); string[] array5 = piece.activeTools; foreach (string key in array5) { if (dictionary.TryGetValue(key, out var value2)) { foreach (PieceTable item3 in value2) { item3.m_pieces.Remove(piece.Prefab); } } } piece.activeTools = (from s in cfg.tools.Value.Split(new char[1] { ',' }) select s.Trim()).ToArray(); if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { array5 = piece.activeTools; foreach (string key2 in array5) { if (dictionary.TryGetValue(key2, out var value3)) { foreach (PieceTable item4 in value3) { if (!item4.m_pieces.Contains(piece.Prefab)) { item4.m_pieces.Add(piece.Prefab); } } } } if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_buildPieces)) { PiecePrefabManager.CategoryRefreshNeeded = true; ((Humanoid)Player.m_localPlayer).SetPlaceMode(Player.m_localPlayer.m_buildPieces); } } }; StationExtension pieceExtensionComp; List hideWhenNoneAttributes2; if (piece.Extension.ExtensionStations.Count > 0) { pieceExtensionComp = piece.Prefab.GetOrAddComponent(); PieceConfig pieceConfig3 = cfg; string group = englishName; CraftingTable table = piece.Extension.ExtensionStations.First().Table; string text = "Crafting station that " + localizedName + " extends."; object[] array = new object[1]; ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes(); int num = order - 1; order = num; configurationManagerAttributes.Order = num; array[0] = configurationManagerAttributes; pieceConfig3.extensionTable = config(group, "Extends Station", table, new ConfigDescription(text, (AcceptableValueBase)null, array)); cfg.customExtentionTable = config(englishName, "Custom Extend Station", piece.Extension.ExtensionStations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); PieceConfig pieceConfig4 = cfg; string group2 = englishName; float maxStationDistance = piece.Extension.ExtensionStations.First().maxStationDistance; string text2 = "Distance from the station that " + localizedName + " can be placed."; object[] array2 = new object[1]; ConfigurationManagerAttributes configurationManagerAttributes2 = new ConfigurationManagerAttributes(); num = order - 1; order = num; configurationManagerAttributes2.Order = num; array2[0] = configurationManagerAttributes2; pieceConfig4.maxStationDistance = config(group2, "Max Station Distance", maxStationDistance, new ConfigDescription(text2, (AcceptableValueBase)null, array2)); hideWhenNoneAttributes2 = new List(); cfg.extensionTable.SettingChanged += ExtensionTableConfigChanged; cfg.customExtentionTable.SettingChanged += ExtensionTableConfigChanged; cfg.maxStationDistance.SettingChanged += ExtensionTableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes3 = new ConfigurationManagerAttributes(); num = order - 1; order = num; configurationManagerAttributes3.Order = num; configurationManagerAttributes3.Browsable = cfg.extensionTable.Value != CraftingTable.None; ConfigurationManagerAttributes item = configurationManagerAttributes3; hideWhenNoneAttributes2.Add(item); } List hideWhenNoneAttributes; if (piece.Crafting.Stations.Count > 0) { hideWhenNoneAttributes = new List(); PieceConfig pieceConfig5 = cfg; string group3 = englishName; CraftingTable table2 = piece.Crafting.Stations.First().Table; string text3 = "Crafting station where " + localizedName + " is available."; object[] array3 = new object[1]; ConfigurationManagerAttributes configurationManagerAttributes4 = new ConfigurationManagerAttributes(); int num = order - 1; order = num; configurationManagerAttributes4.Order = num; array3[0] = configurationManagerAttributes4; pieceConfig5.table = config(group3, "Crafting Station", table2, new ConfigDescription(text3, (AcceptableValueBase)null, array3)); cfg.customTable = config(englishName, "Custom Crafting Station", piece.Crafting.Stations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); cfg.table.SettingChanged += TableConfigChanged; cfg.customTable.SettingChanged += TableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes5 = new ConfigurationManagerAttributes(); num = order - 1; order = num; configurationManagerAttributes5.Order = num; configurationManagerAttributes5.Browsable = cfg.table.Value != CraftingTable.None; ConfigurationManagerAttributes item2 = configurationManagerAttributes5; hideWhenNoneAttributes.Add(item2); } cfg.craft = itemConfig("Crafting Costs", new SerializedRequirements(piece.RequiredItems.Requirements).ToString(), "Item costs to craft " + localizedName); cfg.craft.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && (Object)(object)ObjectDB.instance.GetItemPrefab("YmirRemains") != (Object)null) { Requirement[] resources = SerializedRequirements.toPieceReqs(new SerializedRequirements(cfg.craft.Value)); piecePrefab2.m_resources = resources; Piece[] array4 = Object.FindObjectsOfType(); foreach (Piece val in array4) { if (val.m_name == pieceName) { val.m_resources = resources; } } } }; for (int j = 0; j < piece.Conversions.Count; j++) { string text4 = ((piece.Conversions.Count > 1) ? $"{j + 1}. " : ""); Conversion conversion = piece.Conversions[j]; conversion.config = new Conversion.ConversionConfig(); int index = j; conversion.config.input = config(englishName, text4 + "Conversion Input Item", conversion.Input, new ConfigDescription("Conversion input item within " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName } })); conversion.config.input.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { if (index < piece.conversions.Count) { ObjectDB instance2 = ObjectDB.instance; if (instance2 != null) { ItemDrop from = SerializedRequirements.fetchByName(instance2, conversion.config.input.Value); piece.conversions[index].m_from = from; } } }; conversion.config.output = config(englishName, text4 + "Conversion Output Item", conversion.Output, new ConfigDescription("Conversion output item within " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName } })); conversion.config.output.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { if (index < piece.conversions.Count) { ObjectDB instance = ObjectDB.instance; if (instance != null) { ItemDrop to = SerializedRequirements.fetchByName(instance, conversion.config.output.Value); piece.conversions[index].m_to = to; } } }; } void BuildTableConfigChanged(object o, EventArgs e) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (registeredPieces.Count > 0) { if (cfg.category.Value == BuildPieceCategory.Custom) { piecePrefab2.m_category = PiecePrefabManager.GetCategory(cfg.customCategory.Value); } else { piecePrefab2.m_category = (PieceCategory)cfg.category.Value; } if (Object.op_Implicit((Object)(object)Hud.instance)) { PiecePrefabManager.CategoryRefreshNeeded = true; PiecePrefabManager.CreateCategoryTabs(); } } customTableAttributes.Browsable = cfg.category.Value == BuildPieceCategory.Custom; ReloadConfigDisplay(); } void ExtensionTableConfigChanged(object o, EventArgs e) { if (piece.RequiredItems.Requirements.Count > 0) { if (cfg.extensionTable.Value == CraftingTable.Custom) { StationExtension obj2 = pieceExtensionComp; GameObject prefab2 = ZNetScene.instance.GetPrefab(cfg.customExtentionTable.Value); obj2.m_craftingStation = ((prefab2 != null) ? prefab2.GetComponent() : null); } else { pieceExtensionComp.m_craftingStation = ZNetScene.instance.GetPrefab(((InternalName)typeof(CraftingTable).GetMember(cfg.extensionTable.Value.ToString())[0].GetCustomAttributes(typeof(InternalName)).First()).internalName).GetComponent(); } pieceExtensionComp.m_maxStationDistance = cfg.maxStationDistance.Value; } customTableAttributes.Browsable = cfg.extensionTable.Value == CraftingTable.Custom; foreach (ConfigurationManagerAttributes item5 in hideWhenNoneAttributes2) { item5.Browsable = cfg.extensionTable.Value != CraftingTable.None; } ReloadConfigDisplay(); plugin.Config.Save(); } void TableConfigChanged(object o, EventArgs e) { if (piece.RequiredItems.Requirements.Count > 0) { switch (cfg.table.Value) { case CraftingTable.None: piecePrefab2.m_craftingStation = null; break; case CraftingTable.Custom: { Piece obj = piecePrefab2; GameObject prefab = ZNetScene.instance.GetPrefab(cfg.customTable.Value); obj.m_craftingStation = ((prefab != null) ? prefab.GetComponent() : null); break; } default: piecePrefab2.m_craftingStation = ZNetScene.instance.GetPrefab(((InternalName)typeof(CraftingTable).GetMember(cfg.table.Value.ToString())[0].GetCustomAttributes(typeof(InternalName)).First()).internalName).GetComponent(); break; } } customTableAttributes.Browsable = cfg.table.Value == CraftingTable.Custom; foreach (ConfigurationManagerAttributes item6 in hideWhenNoneAttributes) { item6.Browsable = cfg.table.Value != CraftingTable.None; } ReloadConfigDisplay(); plugin.Config.Save(); } ConfigEntry itemConfig(string name, string value, string desc) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes6 = new ConfigurationManagerAttributes { CustomDrawer = DrawConfigTable, Order = (order -= 1), Category = localizedName }; return config(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes6 })); } } foreach (BuildPiece registeredPiece3 in registeredPieces) { ConfigEntryBase enabledCfg = registeredPiece3.RecipeIsActive; Piece piecePrefab; if (enabledCfg != null) { piecePrefab = registeredPiece3.Prefab.GetComponent(); ConfigChanged(null, null); ((object)enabledCfg).GetType().GetEvent("SettingChanged").AddEventHandler(enabledCfg, new EventHandler(ConfigChanged)); } registeredPiece3.InitializeNewRegisteredPiece(registeredPiece3); [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] void ConfigChanged(object o, EventArgs e) { piecePrefab.m_enabled = (int)enabledCfg.BoxedValue != 0; } } if (saveOnConfigSet) { plugin.Config.SaveOnConfigSet = true; plugin.Config.Save(); } void ReloadConfigDisplay() { object obj3 = configManagerType?.GetProperty("DisplayingWindow").GetValue(configManager); if (obj3 is bool && (bool)obj3) { configManagerType.GetMethod("BuildSettingList").Invoke(configManager, Array.Empty()); } } } private void InitializeNewRegisteredPiece(BuildPiece piece) { ConfigEntryBase recipeIsActive = piece.RecipeIsActive; PieceConfig cfg; Piece piecePrefab; string pieceName; if (recipeIsActive != null) { pieceConfigs.TryGetValue(piece, out cfg); piecePrefab = piece.Prefab.GetComponent(); pieceName = piecePrefab.m_name; ((object)recipeIsActive).GetType().GetEvent("SettingChanged").AddEventHandler(recipeIsActive, new EventHandler(ConfigChanged)); } void ConfigChanged(object o, EventArgs e) { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && (Object)(object)ObjectDB.instance.GetItemPrefab("YmirRemains") != (Object)null && cfg != null) { Requirement[] resources = SerializedRequirements.toPieceReqs(new SerializedRequirements(cfg.craft.Value)); piecePrefab.m_resources = resources; Piece[] array = Object.FindObjectsOfType(); foreach (Piece val in array) { if (val.m_name == pieceName) { val.m_resources = resources; } } } } } [HarmonyPriority(700)] internal static void Patch_ObjectDBInit(ObjectDB __instance) { //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Expected O, but got Unknown if ((Object)(object)__instance.GetItemPrefab("YmirRemains") == (Object)null) { return; } foreach (BuildPiece registeredPiece in registeredPieces) { pieceConfigs.TryGetValue(registeredPiece, out var value); registeredPiece.Prefab.GetComponent().m_resources = SerializedRequirements.toPieceReqs((value == null) ? new SerializedRequirements(registeredPiece.RequiredItems.Requirements) : new SerializedRequirements(value.craft.Value)); foreach (ExtensionConfig extensionStation in registeredPiece.Extension.ExtensionStations) { switch ((value == null || registeredPiece.Extension.ExtensionStations.Count > 0) ? extensionStation.Table : value.extensionTable.Value) { case CraftingTable.None: registeredPiece.Prefab.GetComponent().m_craftingStation = null; break; case CraftingTable.Custom: { GameObject prefab = ZNetScene.instance.GetPrefab((value == null || registeredPiece.Extension.ExtensionStations.Count > 0) ? extensionStation.custom : value.customExtentionTable.Value); if (prefab != null) { registeredPiece.Prefab.GetComponent().m_craftingStation = prefab.GetComponent(); } else { Debug.LogWarning((object)("Custom crafting station '" + ((value == null || registeredPiece.Extension.ExtensionStations.Count > 0) ? extensionStation.custom : value.customExtentionTable.Value) + "' does not exist")); } break; } default: if (value != null && value.table.Value == CraftingTable.None) { registeredPiece.Prefab.GetComponent().m_craftingStation = null; } else { registeredPiece.Prefab.GetComponent().m_craftingStation = ZNetScene.instance.GetPrefab(((InternalName)typeof(CraftingTable).GetMember(((value == null || registeredPiece.Extension.ExtensionStations.Count > 0) ? extensionStation.Table : value.extensionTable.Value).ToString())[0].GetCustomAttributes(typeof(InternalName)).First()).internalName).GetComponent(); } break; } } foreach (CraftingStationConfig station in registeredPiece.Crafting.Stations) { switch ((value == null || registeredPiece.Crafting.Stations.Count > 0) ? station.Table : value.table.Value) { case CraftingTable.None: registeredPiece.Prefab.GetComponent().m_craftingStation = null; break; case CraftingTable.Custom: { GameObject prefab2 = ZNetScene.instance.GetPrefab((value == null || registeredPiece.Crafting.Stations.Count > 0) ? station.custom : value.customTable.Value); if (prefab2 != null) { registeredPiece.Prefab.GetComponent().m_craftingStation = prefab2.GetComponent(); } else { Debug.LogWarning((object)("Custom crafting station '" + ((value == null || registeredPiece.Crafting.Stations.Count > 0) ? station.custom : value.customTable.Value) + "' does not exist")); } break; } default: if (value != null && value.table.Value == CraftingTable.None) { registeredPiece.Prefab.GetComponent().m_craftingStation = null; } else { registeredPiece.Prefab.GetComponent().m_craftingStation = ZNetScene.instance.GetPrefab(((InternalName)typeof(CraftingTable).GetMember(((value == null || registeredPiece.Crafting.Stations.Count > 0) ? station.Table : value.table.Value).ToString())[0].GetCustomAttributes(typeof(InternalName)).First()).internalName).GetComponent(); } break; } } registeredPiece.conversions = new List(); for (int i = 0; i < registeredPiece.Conversions.Count; i++) { Conversion conversion = registeredPiece.Conversions[i]; registeredPiece.conversions.Add(new ItemConversion { m_from = SerializedRequirements.fetchByName(ObjectDB.instance, conversion.config?.input.Value ?? conversion.Input), m_to = SerializedRequirements.fetchByName(ObjectDB.instance, conversion.config?.output.Value ?? conversion.Output) }); if (registeredPiece.conversions[i].m_from != null && registeredPiece.conversions[i].m_to != null) { registeredPiece.Prefab.GetComponent().m_conversion.Add(registeredPiece.conversions[i]); } } } } public void Snapshot(float lightIntensity = 1.3f, Quaternion? cameraRotation = null) { SnapshotPiece(Prefab, lightIntensity, cameraRotation); } internal void SnapshotPiece(GameObject prefab, float lightIntensity = 1.3f, Quaternion? cameraRotation = null) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01de: 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_0207: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Expected O, but got Unknown //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)prefab == (Object)null) && (prefab.GetComponentsInChildren().Any() || prefab.GetComponentsInChildren().Any())) { Camera component = new GameObject("CameraIcon", new Type[1] { typeof(Camera) }).GetComponent(); component.backgroundColor = Color.clear; component.clearFlags = (CameraClearFlags)2; ((Component)component).transform.position = new Vector3(10000f, 10000f, 10000f); ((Component)component).transform.rotation = (Quaternion)(((??)cameraRotation) ?? Quaternion.Euler(0f, 180f, 0f)); component.fieldOfView = 0.5f; component.farClipPlane = 100000f; component.cullingMask = 8; Light component2 = new GameObject("LightIcon", new Type[1] { typeof(Light) }).GetComponent(); ((Component)component2).transform.position = new Vector3(10000f, 10000f, 10000f); ((Component)component2).transform.rotation = Quaternion.Euler(5f, 180f, 5f); component2.type = (LightType)1; component2.cullingMask = 8; component2.intensity = lightIntensity; GameObject val = Object.Instantiate(prefab); Transform[] componentsInChildren = val.GetComponentsInChildren(); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.layer = 3; } val.transform.position = Vector3.zero; val.transform.rotation = Quaternion.Euler(23f, 51f, 25.8f); ((Object)val).name = ((Object)prefab).name; MeshRenderer[] componentsInChildren2 = val.GetComponentsInChildren(); Vector3 val2 = componentsInChildren2.Aggregate(Vector3.positiveInfinity, [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Vector3 cur, MeshRenderer renderer) => { //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_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references) Bounds bounds2 = ((Renderer)renderer).bounds; return Vector3.Min(cur, ((Bounds)(ref bounds2)).min); }); Vector3 val3 = componentsInChildren2.Aggregate(Vector3.negativeInfinity, [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Vector3 cur, MeshRenderer renderer) => { //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_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = ((Renderer)renderer).bounds; return Vector3.Max(cur, ((Bounds)(ref bounds)).max); }); val.transform.position = new Vector3(10000f, 10000f, 10000f) - (val2 + val3) / 2f; Vector3 val4 = val3 - val2; val.AddComponent().Trigger(1f); Rect val5 = default(Rect); ((Rect)(ref val5))..ctor(0f, 0f, 128f, 128f); component.targetTexture = RenderTexture.GetTemporary((int)((Rect)(ref val5)).width, (int)((Rect)(ref val5)).height); component.fieldOfView = 20f; float num = (Mathf.Max(val4.x, val4.y) + 0.1f) / Mathf.Tan(component.fieldOfView * ((float)Math.PI / 180f)) * 1.1f; ((Component)component).transform.position = new Vector3(10000f, 10000f, 10000f) + new Vector3(0f, 0f, num); component.Render(); RenderTexture active = RenderTexture.active; RenderTexture.active = component.targetTexture; Texture2D val6 = new Texture2D((int)((Rect)(ref val5)).width, (int)((Rect)(ref val5)).height, (TextureFormat)4, false); val6.ReadPixels(new Rect(0f, 0f, (float)(int)((Rect)(ref val5)).width, (float)(int)((Rect)(ref val5)).height), 0, 0); val6.Apply(); RenderTexture.active = active; prefab.GetComponent().m_icon = Sprite.Create(val6, new Rect(0f, 0f, (float)(int)((Rect)(ref val5)).width, (float)(int)((Rect)(ref val5)).height), Vector2.one / 2f); ((Component)component2).gameObject.SetActive(false); component.targetTexture.Release(); ((Component)component).gameObject.SetActive(false); val.SetActive(false); Object.DestroyImmediate((Object)(object)val); Object.Destroy((Object)(object)component); Object.Destroy((Object)(object)component2); Object.Destroy((Object)(object)((Component)component).gameObject); Object.Destroy((Object)(object)((Component)component2).gameObject); } } private static void DrawConfigTable(ConfigEntryBase cfg) { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object a) => (!(a.GetType().Name == "ConfigurationManagerAttributes")) ? null : ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a))).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault(); List list = new List(); bool flag = false; int num = (int)(configManager?.GetType().GetProperty("RightColumnWidth", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(nonPublic: true) .Invoke(configManager, Array.Empty()) ?? ((object)130)); GUILayout.BeginVertical(Array.Empty()); foreach (Requirement req in new SerializedRequirements((string)cfg.BoxedValue).Reqs) { GUILayout.BeginHorizontal(Array.Empty()); int num2 = req.amount; if (int.TryParse(GUILayout.TextField(num2.ToString(), new GUIStyle(GUI.skin.textField) { fixedWidth = 40f }, Array.Empty()), out var result) && result != num2 && !valueOrDefault) { num2 = result; flag = true; } string text = GUILayout.TextField(req.itemName, new GUIStyle(GUI.skin.textField) { fixedWidth = num - 40 - 67 - 21 - 21 - 12 }, Array.Empty()); string text2 = (valueOrDefault ? req.itemName : text); flag = flag || text2 != req.itemName; bool flag2 = req.recover; if (GUILayout.Toggle(req.recover, "Recover", new GUIStyle(GUI.skin.toggle) { fixedWidth = 67f }, Array.Empty()) != req.recover) { flag2 = !flag2; flag = true; } if (GUILayout.Button("x", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty()) && !valueOrDefault) { flag = true; } else { list.Add(new Requirement { amount = num2, itemName = text2, recover = flag2 }); } if (GUILayout.Button("+", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty()) && !valueOrDefault) { flag = true; list.Add(new Requirement { amount = 1, itemName = "", recover = false }); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = new SerializedRequirements(list).ToString(); } } private static ConfigEntry config<[<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] T>(string group, string name, T value, ConfigDescription description) { ConfigEntry val = plugin.Config.Bind(group, name, value, description); configSync?.GetType().GetMethod("AddConfigEntry").MakeGenericMethod(typeof(T)) .Invoke(configSync, new object[1] { val }); return val; } private static ConfigEntry config<[<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] T>(string group, string name, T value, string description) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty())); } } public static class GoExtensions { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static T GetOrAddComponent<[<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] T>(this GameObject gameObject) where T : Component { return gameObject.GetComponent() ?? gameObject.AddComponent(); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [PublicAPI] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public class LocalizeKey { private static readonly List keys = new List(); public readonly string Key; public readonly Dictionary Localizations = new Dictionary(); public LocalizeKey(string key) { Key = key.Replace("$", ""); keys.Add(this); } public void Alias(string alias) { Localizations.Clear(); if (!alias.Contains("$")) { alias = "$" + alias; } Localizations["alias"] = alias; Localization.instance.AddWord(Key, Localization.instance.Localize(alias)); } public LocalizeKey English(string key) { return addForLang("English", key); } public LocalizeKey Swedish(string key) { return addForLang("Swedish", key); } public LocalizeKey French(string key) { return addForLang("French", key); } public LocalizeKey Italian(string key) { return addForLang("Italian", key); } public LocalizeKey German(string key) { return addForLang("German", key); } public LocalizeKey Spanish(string key) { return addForLang("Spanish", key); } public LocalizeKey Russian(string key) { return addForLang("Russian", key); } public LocalizeKey Romanian(string key) { return addForLang("Romanian", key); } public LocalizeKey Bulgarian(string key) { return addForLang("Bulgarian", key); } public LocalizeKey Macedonian(string key) { return addForLang("Macedonian", key); } public LocalizeKey Finnish(string key) { return addForLang("Finnish", key); } public LocalizeKey Danish(string key) { return addForLang("Danish", key); } public LocalizeKey Norwegian(string key) { return addForLang("Norwegian", key); } public LocalizeKey Icelandic(string key) { return addForLang("Icelandic", key); } public LocalizeKey Turkish(string key) { return addForLang("Turkish", key); } public LocalizeKey Lithuanian(string key) { return addForLang("Lithuanian", key); } public LocalizeKey Czech(string key) { return addForLang("Czech", key); } public LocalizeKey Hungarian(string key) { return addForLang("Hungarian", key); } public LocalizeKey Slovak(string key) { return addForLang("Slovak", key); } public LocalizeKey Polish(string key) { return addForLang("Polish", key); } public LocalizeKey Dutch(string key) { return addForLang("Dutch", key); } public LocalizeKey Portuguese_European(string key) { return addForLang("Portuguese_European", key); } public LocalizeKey Portuguese_Brazilian(string key) { return addForLang("Portuguese_Brazilian", key); } public LocalizeKey Chinese(string key) { return addForLang("Chinese", key); } public LocalizeKey Japanese(string key) { return addForLang("Japanese", key); } public LocalizeKey Korean(string key) { return addForLang("Korean", key); } public LocalizeKey Hindi(string key) { return addForLang("Hindi", key); } public LocalizeKey Thai(string key) { return addForLang("Thai", key); } public LocalizeKey Abenaki(string key) { return addForLang("Abenaki", key); } public LocalizeKey Croatian(string key) { return addForLang("Croatian", key); } public LocalizeKey Georgian(string key) { return addForLang("Georgian", key); } public LocalizeKey Greek(string key) { return addForLang("Greek", key); } public LocalizeKey Serbian(string key) { return addForLang("Serbian", key); } public LocalizeKey Ukrainian(string key) { return addForLang("Ukrainian", key); } private LocalizeKey addForLang(string lang, string value) { Localizations[lang] = value; if (Localization.instance.GetSelectedLanguage() == lang) { Localization.instance.AddWord(Key, value); } else if (lang == "English" && !Localization.instance.m_translations.ContainsKey(Key)) { Localization.instance.AddWord(Key, value); } return this; } [HarmonyPriority(300)] internal static void AddLocalizedKeys(Localization __instance, string language) { foreach (LocalizeKey key in keys) { string value2; if (key.Localizations.TryGetValue(language, out var value) || key.Localizations.TryGetValue("English", out value)) { __instance.AddWord(key.Key, value); } else if (key.Localizations.TryGetValue("alias", out value2)) { __instance.AddWord(key.Key, Localization.instance.Localize(value2)); } } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static class LocalizationCache { private static readonly Dictionary localizations = new Dictionary(); internal static void LocalizationPostfix(Localization __instance, string language) { string key = localizations.FirstOrDefault([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (KeyValuePair l) => l.Value == __instance).Key; if (key != null) { localizations.Remove(key); } if (!localizations.ContainsKey(language)) { localizations.Add(language, __instance); } } public static Localization ForLanguage([<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] string language = null) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if (localizations.TryGetValue(language ?? PlayerPrefs.GetString("language", "English"), out var value)) { return value; } value = new Localization(); if (language != null) { value.SetupLanguage(language); } return value; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class AdminSyncing { private static bool isServer; internal static bool registeredOnClient; [HarmonyPriority(700)] internal static void AdminStatusSync(ZNet __instance) { isServer = __instance.IsServer(); if (BuildPiece._plugin != null) { if (isServer) { ZRoutedRpc.instance.Register(BuildPiece._plugin.Info.Metadata.Name + " PMAdminStatusSync", (Action)RPC_AdminPieceAddRemove); } else if (!registeredOnClient) { ZRoutedRpc.instance.Register(BuildPiece._plugin.Info.Metadata.Name + " PMAdminStatusSync", (Action)RPC_AdminPieceAddRemove); registeredOnClient = true; } } if (isServer) { ((MonoBehaviour)ZNet.instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List peers, bool isAdmin) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(isAdmin); ((MonoBehaviour)ZNet.instance).StartCoroutine(sendZPackage(peers, val)); } static IEnumerator WatchAdminListChanges() { List currentList = new List(ZNet.instance.m_adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!ZNet.instance.m_adminList.GetList().SequenceEqual(currentList)) { currentList = new List(ZNet.instance.m_adminList.GetList()); List list = (from p in ZNet.instance.GetPeers() where ZNet.instance.ListContainsId(ZNet.instance.m_adminList, p.m_rpc.GetSocket().GetHostName()) select p).ToList(); SendAdmin(ZNet.instance.GetPeers().Except(list).ToList(), isAdmin: false); SendAdmin(list, isAdmin: true); } } } } private static IEnumerator sendZPackage(List peers, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] array = package.GetArray(); if (array != null && array.LongLength > 10000) { ZPackage val = new ZPackage(); val.Write(4); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Optimal)) { deflateStream.Write(array, 0, array.Length); } val.Write(memoryStream.ToArray()); package = val; } List> writers = (from peer in peers where peer.IsReady() select peer into p select TellPeerAdminStatus(p, package)).ToList(); writers.RemoveAll((IEnumerator writer) => !writer.MoveNext()); while (writers.Count > 0) { yield return null; writers.RemoveAll((IEnumerator writer) => !writer.MoveNext()); } } private static IEnumerator TellPeerAdminStatus(ZNetPeer peer, ZPackage package) { ZRoutedRpc rpc = ZRoutedRpc.instance; if (rpc != null) { SendPackage(package); } void SendPackage(ZPackage pkg) { BaseUnityPlugin plugin = BuildPiece._plugin; string text = ((plugin != null) ? plugin.Info.Metadata.Name : null) + " PMAdminStatusSync"; if (isServer) { peer.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer.m_server ? 0 : peer.m_uid, text, new object[1] { pkg }); } } yield break; } internal static void RPC_AdminPieceAddRemove(long sender, ZPackage package) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown ZNetPeer peer = ZNet.instance.GetPeer(sender); bool flag = false; try { flag = package.ReadBool(); } catch { } if (isServer) { ZRoutedRpc instance = ZRoutedRpc.instance; long everybody = ZRoutedRpc.Everybody; BaseUnityPlugin plugin = BuildPiece._plugin; instance.InvokeRoutedRPC(everybody, ((plugin != null) ? plugin.Info.Metadata.Name : null) + " PMAdminStatusSync", new object[1] { (object)new ZPackage() }); if (ZNet.instance.ListContainsId(ZNet.instance.m_adminList, peer.m_rpc.GetSocket().GetHostName())) { ZPackage val = new ZPackage(); val.Write(true); ZRpc rpc = peer.m_rpc; BaseUnityPlugin plugin2 = BuildPiece._plugin; rpc.Invoke(((plugin2 != null) ? plugin2.Info.Metadata.Name : null) + " PMAdminStatusSync", new object[1] { val }); } return; } foreach (BuildPiece registeredPiece in BuildPiece.registeredPieces) { if (!registeredPiece.SpecialProperties.AdminOnly) { continue; } Piece component = registeredPiece.Prefab.GetComponent(); string name = component.m_name; Localization.instance.Localize(name).Trim(); if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || (Object)(object)ObjectDB.instance.GetItemPrefab("YmirRemains") == (Object)null) { continue; } Piece[] array = Object.FindObjectsOfType(); foreach (Piece val2 in array) { if (flag) { if (val2.m_name == name) { val2.m_enabled = true; } } else if (val2.m_name == name) { val2.m_enabled = false; } } List pieces = ObjectDB.instance.GetItemPrefab("Hammer").GetComponent().m_itemData.m_shared.m_buildPieces.m_pieces; if (flag) { if (!pieces.Contains(ZNetScene.instance.GetPrefab(((Object)component).name))) { pieces.Add(ZNetScene.instance.GetPrefab(((Object)component).name)); } } else if (pieces.Contains(ZNetScene.instance.GetPrefab(((Object)component).name))) { pieces.Remove(ZNetScene.instance.GetPrefab(((Object)component).name)); } } } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] internal class RegisterClientRPCPatch { private static void Postfix(ZNet __instance, ZNetPeer peer) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown if (!__instance.IsServer()) { ZRpc rpc = peer.m_rpc; BaseUnityPlugin plugin = BuildPiece._plugin; rpc.Register(((plugin != null) ? plugin.Info.Metadata.Name : null) + " PMAdminStatusSync", (Action)RPC_InitialAdminSync); return; } ZPackage val = new ZPackage(); val.Write(__instance.ListContainsId(__instance.m_adminList, peer.m_rpc.GetSocket().GetHostName())); ZRpc rpc2 = peer.m_rpc; BaseUnityPlugin plugin2 = BuildPiece._plugin; rpc2.Invoke(((plugin2 != null) ? plugin2.Info.Metadata.Name : null) + " PMAdminStatusSync", new object[1] { val }); } private static void RPC_InitialAdminSync(ZRpc rpc, ZPackage package) { AdminSyncing.RPC_AdminPieceAddRemove(0L, package); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public static class PiecePrefabManager { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private struct BundleId { [UsedImplicitly] public string assetBundleFileName; [UsedImplicitly] public string folderName; } private static readonly Dictionary bundleCache; private static readonly List piecePrefabs; private static readonly Dictionary PieceCategories; private static readonly Dictionary OtherPieceCategories; private static readonly Dictionary VanillaLabels; internal static bool CategoryRefreshNeeded; static PiecePrefabManager() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0077: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Expected O, but got Unknown //IL_02e9: Expected O, but got Unknown //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Expected O, but got Unknown //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Expected O, but got Unknown //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Expected O, but got Unknown //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Expected O, but got Unknown //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Expected O, but got Unknown //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Expected O, but got Unknown bundleCache = new Dictionary(); piecePrefabs = new List(); PieceCategories = new Dictionary(); OtherPieceCategories = new Dictionary(); VanillaLabels = new Dictionary(); Harmony val = new Harmony("org.bepinex.helpers.PieceManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(BuildPiece), "Patch_FejdStartup", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LocalizeKey), "AddLocalizedKeys", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LocalizationCache), "LocalizationPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "Patch_ObjectDBInit", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(BuildPiece), "Patch_ObjectDBInit", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ObjectDB), "CopyOtherDB", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "Patch_ObjectDBInit", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AdminSyncing), "AdminStatusSync", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "Patch_ZNetSceneAwake", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "RefFixPatch_ZNetSceneAwake", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(PieceTable), "UpdateAvailable", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "UpdateAvailable_Transpiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(PieceTable), "UpdateAvailable", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "UpdateAvailable_Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "UpdateAvailable_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Player), "SetPlaceMode", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "Patch_SetPlaceMode", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Hud), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "Hud_AwakeCreateTabs", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Hud), "UpdateBuild", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "RepositionCatsIfNeeded", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Hud), "LateUpdate", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "RepositionCatsIfNeeded", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Enum), "GetValues", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "EnumGetValuesPatch", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Enum), "GetNames", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "EnumGetNamesPatch", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static AssetBundle RegisterAssetBundle(string assetBundleFileName, string folderName = "assets") { BundleId bundleId = default(BundleId); bundleId.assetBundleFileName = assetBundleFileName; bundleId.folderName = folderName; BundleId key = bundleId; if (!bundleCache.TryGetValue(key, out var value)) { Dictionary dictionary = bundleCache; AssetBundle? obj = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (AssetBundle a) => ((Object)a).name == assetBundleFileName)) ?? AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name + "." + folderName + "." + assetBundleFileName)); AssetBundle result = obj; dictionary[key] = obj; return result; } return value; } public static IEnumerable FixRefs(AssetBundle assetBundle) { return assetBundle.LoadAllAssets(); } public static GameObject RegisterPrefab(string assetBundleFileName, string prefabName, string folderName = "assets") { return RegisterPrefab(RegisterAssetBundle(assetBundleFileName, folderName), prefabName); } public static GameObject RegisterPrefab(AssetBundle assets, string prefabName) { if ((Object)(object)assets == (Object)null) { Debug.LogError((object)"Failed to load asset bundle. Please make sure to mark all asset bundles as embedded resources."); return null; } GameObject val = assets.LoadAsset(prefabName); if ((Object)(object)val == (Object)null) { Debug.LogError((object)("Failed to load prefab " + prefabName + " from asset bundle " + ((Object)assets).name)); return null; } piecePrefabs.Add(val); return val; } public static Sprite RegisterSprite(string assetBundleFileName, string prefabName, string folderName = "assets") { return RegisterSprite(RegisterAssetBundle(assetBundleFileName, folderName), prefabName); } public static Sprite RegisterSprite(AssetBundle assets, string prefabName) { return assets.LoadAsset(prefabName); } private static void EnumGetValuesPatch(Type enumType, ref Array __result) { if (!(enumType != typeof(PieceCategory)) && PieceCategories.Count != 0) { PieceCategory[] array = (PieceCategory[])(object)new PieceCategory[__result.Length + PieceCategories.Count]; __result.CopyTo(array, 0); PieceCategories.Values.CopyTo(array, __result.Length); __result = array; } } private static void EnumGetNamesPatch(Type enumType, ref string[] __result) { if (!(enumType != typeof(PieceCategory)) && PieceCategories.Count != 0) { __result = CollectionExtensions.AddRangeToArray(__result, PieceCategories.Keys.ToArray()); } } public static Dictionary GetPieceCategoriesMap() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) Array values = Enum.GetValues(typeof(PieceCategory)); string[] names = Enum.GetNames(typeof(PieceCategory)); Dictionary dictionary = new Dictionary(); for (int i = 0; i < values.Length; i++) { dictionary[(PieceCategory)values.GetValue(i)] = names[i]; } return dictionary; } public static PieceCategory GetCategory(string name) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) //IL_006b: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (Enum.TryParse(name, ignoreCase: true, out PieceCategory result)) { return result; } if (PieceCategories.TryGetValue(name, out result)) { return result; } if (OtherPieceCategories.TryGetValue(name, out result)) { return result; } Dictionary pieceCategoriesMap = GetPieceCategoriesMap(); foreach (KeyValuePair item in pieceCategoriesMap) { if (item.Value == name) { result = item.Key; OtherPieceCategories[name] = result; return result; } } result = (PieceCategory)(pieceCategoriesMap.Count - 1); PieceCategories[name] = result; string categoryToken = GetCategoryToken(name); Localization.instance.AddWord(categoryToken, name); return result; } internal static void CreateCategoryTabs() { if (Object.op_Implicit((Object)(object)Hud.instance)) { int num = ModifiedMaxCategory(); for (int i = Hud.instance.m_pieceCategoryTabs.Length; i < num; i++) { GameObject val = CreateCategoryTab(); Hud.instance.m_pieceCategoryTabs = CollectionExtensions.AddItem((IEnumerable)Hud.instance.m_pieceCategoryTabs, val).ToArray(); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_buildPieces)) { RepositionCategories(Player.m_localPlayer.m_buildPieces); Player.m_localPlayer.UpdateAvailablePiecesList(); } } } private static GameObject CreateCategoryTab() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) GameObject val = Hud.instance.m_pieceCategoryTabs[0]; GameObject val2 = Object.Instantiate(Hud.instance.m_pieceCategoryTabs[0], val.transform.parent); val2.SetActive(false); UIInputHandler orAddComponent = val2.GetOrAddComponent(); orAddComponent.m_onLeftDown = (Action)Delegate.Combine(orAddComponent.m_onLeftDown, new Action(Hud.instance.OnLeftClickCategory)); TMP_Text[] componentsInChildren = val2.GetComponentsInChildren(); foreach (TMP_Text obj in componentsInChildren) { obj.rectTransform.offsetMin = new Vector2(3f, 1f); obj.rectTransform.offsetMax = new Vector2(-3f, -1f); obj.enableAutoSizing = true; obj.fontSizeMin = 12f; obj.fontSizeMax = 20f; obj.lineSpacing = 0.8f; obj.textWrappingMode = (TextWrappingModes)1; obj.overflowMode = (TextOverflowModes)3; } return val2; } private static int ModifiedMaxCategory() { return Enum.GetValues(typeof(PieceCategory)).Length - 1; } private static int GetMaxCategoryOrDefault() { try { return (int)Enum.Parse(typeof(PieceCategory), "Max"); } catch (ArgumentException) { Debug.LogWarning((object)"Could not find Piece.PieceCategory.Max, using fallback value 4"); return 4; } } private static List TranspileMaxCategory(IEnumerable instructions, int maxOffset) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown int num = GetMaxCategoryOrDefault() + maxOffset; List list = new List(); foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.LoadsConstant(instruction, (long)num)) { list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(PiecePrefabManager), "ModifiedMaxCategory", (Type[])null, (Type[])null))); if (maxOffset != 0) { list.Add(new CodeInstruction(OpCodes.Ldc_I4, (object)maxOffset)); list.Add(new CodeInstruction(OpCodes.Add, (object)null)); } } else { list.Add(instruction); } } return list; } private static IEnumerable UpdateAvailable_Transpiler(IEnumerable instructions) { return TranspileMaxCategory(instructions, 0); } private static HashSet CategoriesInPieceTable(PieceTable pieceTable) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(); Piece val = default(Piece); foreach (GameObject item in pieceTable.m_pieces.Where([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (GameObject pieceFab) => (Object)(object)pieceFab != (Object)null)) { if (item.TryGetComponent(ref val)) { hashSet.Add(val.m_category); } } return hashSet; } private static void RepositionCatsIfNeeded() { if (CategoryRefreshNeeded) { CategoryRefreshNeeded = false; CreateCategoryTabs(); RepositionCats(); } } private static void RepositionCats() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_buildPieces)) { RepositionCategories(Player.m_localPlayer.m_buildPieces); } } private static void RepositionCategories(PieceTable pieceTable) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0026: 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_0040: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)Hud.instance.m_pieceCategoryTabs[0].transform; RectTransform val2 = (RectTransform)Hud.instance.m_pieceCategoryRoot.transform; RectTransform val3 = (RectTransform)Hud.instance.m_pieceSelectionWindow.transform; HorizontalLayoutGroup val4 = default(HorizontalLayoutGroup); if (((Component)((Transform)val).parent).TryGetComponent(ref val4)) { Object.DestroyImmediate((Object)(object)val4); } Rect rect = val.rect; Vector2 size = ((Rect)(ref rect)).size; GridLayoutGroup val5 = default(GridLayoutGroup); GridLayoutGroup obj = (((Component)((Transform)val).parent).TryGetComponent(ref val5) ? val5 : ((Component)((Transform)val).parent).gameObject.AddComponent()); obj.cellSize = size; obj.spacing = new Vector2(0f, 1f); obj.constraint = (Constraint)1; obj.constraintCount = 5; ((LayoutGroup)obj).childAlignment = (TextAnchor)4; HashSet hashSet = CategoriesInPieceTable(pieceTable); UpdatePieceTableCategories(pieceTable, hashSet); rect = val2.rect; int num = Mathf.Max((int)(((Rect)(ref rect)).width / size.x), 1); int count = pieceTable.m_categories.Count; float num2 = (0f - size.x) * (float)num / 2f + size.x / 2f; float num3 = (size.y + 1f) * Mathf.Floor((float)(count - 1) / (float)num) + 5f; new Vector2(num2, num3); int num4 = Mathf.CeilToInt((float)count / (float)num); float num5 = (size.y + 1f) * (float)num4; RectTransform component = ((Component)((Transform)val).parent).GetComponent(); component.anchoredPosition = new Vector2(component.anchoredPosition.x, num5 / 2f); int num6 = 0; for (int i = 0; i < Hud.instance.m_pieceCategoryTabs.Length; i++) { GameObject val6 = Hud.instance.m_pieceCategoryTabs[i]; if ((Object)(object)val6 == (Object)null) { continue; } if (i >= pieceTable.m_categories.Count) { val6.SetActive(false); continue; } PieceCategory item = pieceTable.m_categories[i]; string text = pieceTable.m_categoryLabels[i]; if (hashSet.Contains(item)) { num6++; } val6.GetComponentInChildren().text = Localization.instance.Localize(text); } Transform obj2 = ((Transform)val3).Find("Bkg2"); RectTransform val7 = (RectTransform)((obj2 != null) ? ((Component)obj2).transform : null); if (Object.op_Implicit((Object)(object)val7)) { float num7 = (size.y + 1f) * (float)Mathf.Max(0, Mathf.FloorToInt((float)(num6 - 1) / (float)num)); val7.offsetMax = new Vector2(val7.offsetMax.x, num7); } else { Debug.LogWarning((object)"RefreshCategories: Could not find background image"); } ((Component)Hud.instance).GetComponentInParent().RefreshLocalization(); } private static void UpdatePieceTableCategories(PieceTable pieceTable, HashSet visibleCategories) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_00a6: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < GetMaxCategoryOrDefault(); i++) { PieceCategory val = (PieceCategory)i; if (visibleCategories.Contains(val) && !pieceTable.m_categories.Contains(val)) { pieceTable.m_categories.Add(val); pieceTable.m_categoryLabels.Add(GetVanillaLabel(val)); } if (!visibleCategories.Contains(val) && pieceTable.m_categories.Contains(val)) { int index = pieceTable.m_categories.IndexOf(val); pieceTable.m_categories.RemoveAt(index); pieceTable.m_categoryLabels.RemoveAt(index); } } foreach (KeyValuePair pieceCategory in PieceCategories) { string key = pieceCategory.Key; PieceCategory value = pieceCategory.Value; if (visibleCategories.Contains(value) && !pieceTable.m_categories.Contains(value)) { pieceTable.m_categories.Add(value); pieceTable.m_categoryLabels.Add("$" + GetCategoryToken(key)); } if (visibleCategories.Contains(value) && !pieceTable.m_categoryLabels.Contains("$" + GetCategoryToken(key))) { pieceTable.m_categoryLabels.Add("$" + GetCategoryToken(key)); } if (!visibleCategories.Contains(value) && pieceTable.m_categories.Contains(value)) { int index2 = pieceTable.m_categories.IndexOf(value); pieceTable.m_categories.RemoveAt(index2); pieceTable.m_categoryLabels.RemoveAt(index2); } } } private static string GetVanillaLabel(PieceCategory category) { //IL_0005: 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) if (!VanillaLabels.ContainsKey(category)) { SearchVanillaLabels(); } if (!VanillaLabels.TryGetValue(category, out var value)) { return string.Empty; } return value; } private static void SearchVanillaLabels() { //IL_0019: 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_0033: 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) PieceTable[] array = Resources.FindObjectsOfTypeAll(); foreach (PieceTable val in array) { for (int j = 0; j < val.m_categories.Count; j++) { PieceCategory key = val.m_categories[j]; if (j < val.m_categoryLabels.Count && !VanillaLabels.ContainsKey(key) && !string.IsNullOrEmpty(val.m_categoryLabels[j])) { VanillaLabels[key] = val.m_categoryLabels[j]; } } } } private static string GetCategoryToken(string name) { char[] endChars = Localization.instance.m_endChars; string text = string.Concat(name.ToLower().Split(endChars)); return "piecemanager_cat_" + text; } private static void Patch_SetPlaceMode(Player __instance) { if (Object.op_Implicit((Object)(object)__instance.m_buildPieces)) { RepositionCategories(__instance.m_buildPieces); } } private static void UpdateAvailable_Prefix(PieceTable __instance) { if (__instance.m_availablePieces.Count > 0) { int num = ModifiedMaxCategory() - __instance.m_availablePieces.Count; for (int i = 0; i < num; i++) { __instance.m_availablePieces.Add(new List()); } } } private static void UpdateAvailable_Postfix(PieceTable __instance) { Array.Resize(ref __instance.m_selectedPiece, __instance.m_availablePieces.Count); Array.Resize(ref __instance.m_lastSelectedPiece, __instance.m_availablePieces.Count); } [HarmonyPriority(200)] private static void Hud_AwakeCreateTabs() { CreateCategoryTabs(); } [HarmonyPriority(700)] private static void Patch_ZNetSceneAwake(ZNetScene __instance) { foreach (GameObject piecePrefab in piecePrefabs) { if (!__instance.m_prefabs.Contains(piecePrefab)) { __instance.m_prefabs.Add(piecePrefab); } } } [HarmonyPriority(700)] private static void RefFixPatch_ZNetSceneAwake(ZNetScene __instance) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject piecePrefab in piecePrefabs) { if (__instance.m_prefabs.Contains(piecePrefab) && Object.op_Implicit((Object)(object)piecePrefab.GetComponent())) { piecePrefab.GetComponent().m_isUpgrade = true; piecePrefab.GetComponent().m_connectionPrefab = __instance.GetPrefab("piece_workbench_ext3").GetComponent().m_connectionPrefab; piecePrefab.GetComponent().m_connectionOffset = __instance.GetPrefab("piece_workbench_ext3").GetComponent().m_connectionOffset; } } } [HarmonyPriority(300)] private static void Patch_ObjectDBInit(ObjectDB __instance) { foreach (BuildPiece registeredPiece in BuildPiece.registeredPieces) { string[] activeTools = registeredPiece.activeTools; foreach (string text in activeTools) { GameObject itemPrefab = __instance.GetItemPrefab(text); PieceTable val = ((itemPrefab != null) ? itemPrefab.GetComponent().m_itemData.m_shared.m_buildPieces : null); if (val != null && !val.m_pieces.Contains(registeredPiece.Prefab)) { val.m_pieces.Add(registeredPiece.Prefab); } } } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] public class Conversion { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] internal class ConversionConfig { public ConfigEntry input; public ConfigEntry output; } public string Input; public string Output; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] internal ConversionConfig config; public Conversion(BuildPiece conversionPiece) { conversionPiece.Conversions.Add(this); } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class SnapPointMaker { private static List _objectsToApplySnaps; static SnapPointMaker() { _objectsToApplySnaps = new List(); } public static void AddObjectForSnapPoints(GameObject obj) { _objectsToApplySnaps.Add(obj); } public static void ApplySnapPoints() { foreach (GameObject objectsToApplySnap in _objectsToApplySnaps) { GrabVerticesAssignSnaps(objectsToApplySnap); } } private static void GrabVerticesAssignSnaps(GameObject obj) { Vector3[] colliderVertexPosRotated = GetColliderVertexPosRotated(obj); AttachSnapPoints(obj, colliderVertexPosRotated); } private static Vector3[] GetColliderVertexPosRotated(GameObject obj) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[8]; BoxCollider componentInChildren = obj.GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { return array; } Transform transform = obj.transform; Vector3 val = componentInChildren.center - componentInChildren.size * 0.5f; Vector3 val2 = componentInChildren.center + componentInChildren.size * 0.5f; array[0] = transform.TransformPoint(new Vector3(val.x, val.y, val.z)); array[1] = transform.TransformPoint(new Vector3(val.x, val.y, val2.z)); array[2] = transform.TransformPoint(new Vector3(val.x, val2.y, val.z)); array[3] = transform.TransformPoint(new Vector3(val.x, val2.y, val2.z)); array[4] = transform.TransformPoint(new Vector3(val2.x, val.y, val.z)); array[5] = transform.TransformPoint(new Vector3(val2.x, val.y, val2.z)); array[6] = transform.TransformPoint(new Vector3(val2.x, val2.y, val.z)); array[7] = transform.TransformPoint(new Vector3(val2.x, val2.y, val2.z)); return array; } private static void AttachSnapPoints(GameObject objecttosnap, Vector3[] vector3S) { //IL_0008: 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_000e: 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) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown foreach (Vector3 val in vector3S) { Object.Instantiate(new GameObject { name = "_snappoint", tag = "snappoint", layer = 10 }, val, Quaternion.identity, objecttosnap.transform).SetActive(false); } } } } namespace LocalizationManager { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [PublicAPI] public class Localizer { private static readonly Dictionary>> PlaceholderProcessors; private static readonly Dictionary> loadedTexts; private static readonly ConditionalWeakTable localizationLanguage; private static readonly List> localizationObjects; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static BaseUnityPlugin _plugin; private static readonly List fileExtensions; private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out var value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out var value2)) { text = value2.Aggregate(text, [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (string current, KeyValuePair> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder(string key, string placeholder, ConfigEntry config, [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 2, 1, 1 })] Func convertConfigValue = null) { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary>(); } config.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List> list = new List>(); foreach (WeakReference localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference item in list) { localizationObjects.Remove(item); } } public static void Load() { LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference(__instance)); } localizationLanguage.Add(__instance, language); Dictionary dictionary = new Dictionary(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } byte[] array = LoadTranslationFromAssembly("English"); if (array == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize>(Encoding.UTF8.GetString(array)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.ContainsKey(language)) { text2 = File.ReadAllText(dictionary[language]); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text2 = Encoding.UTF8.GetString(array2); } } } if (text2 == null && dictionary.ContainsKey("English")) { text2 = File.ReadAllText(dictionary["English"]); } if (text2 != null) { foreach (KeyValuePair item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize>(text2) ?? new Dictionary()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_004d: 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_008c: Expected O, but got Unknown PlaceholderProcessors = new Dictionary>>(); loadedTexts = new Dictionary>(); localizationLanguage = new ConditionalWeakTable(); localizationObjects = new List>(); fileExtensions = new List { ".json", ".yml" }; new Harmony("org.bepinex.helpers.LocalizationManager").Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } [return: <5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static byte[] LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] public static byte[] ReadEmbeddedFileBytes([<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(1)] string resourceFileName, Assembly containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace ItemManager { [PublicAPI] public enum CraftingTable { Disabled, Inventory, [InternalName("piece_workbench")] Workbench, [InternalName("piece_cauldron")] Cauldron, [InternalName("piece_MeadCauldron")] MeadCauldron, [InternalName("forge")] Forge, [InternalName("piece_artisanstation")] ArtisanTable, [InternalName("piece_stonecutter")] StoneCutter, [InternalName("piece_magetable")] MageTable, [InternalName("piece_preptable")] PrepTable, [InternalName("blackforge")] BlackForge, Custom } [PublicAPI] public enum ConversionPiece { Disabled, [InternalName("smelter")] Smelter, [InternalName("charcoal_kiln")] CharcoalKiln, [InternalName("blastfurnace")] BlastFurnace, [InternalName("windmill")] Windmill, [InternalName("piece_spinningwheel")] SpinningWheel, [InternalName("eitrrefinery")] EitrRefinery, Custom } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] public class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class RequiredResourceList { public readonly List Requirements = new List(); public bool Free; public void Add(string itemName, int amount, int quality = 0) { Requirements.Add(new Requirement { itemName = itemName, amount = amount, quality = quality }); } public void Add(string itemName, ConfigEntry amountConfig, int quality = 0) { Requirements.Add(new Requirement { itemName = itemName, amountConfig = amountConfig, quality = quality }); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] public class CraftingStationList { public readonly List Stations = new List(); public void Add(CraftingTable table, int level) { Stations.Add(new CraftingStationConfig { Table = table, level = level }); } public void Add(string customTable, int level) { Stations.Add(new CraftingStationConfig { Table = CraftingTable.Custom, level = level, custom = customTable }); } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [PublicAPI] public class ItemRecipe { public readonly RequiredResourceList RequiredItems = new RequiredResourceList(); public readonly RequiredResourceList RequiredUpgradeItems = new RequiredResourceList(); public readonly CraftingStationList Crafting = new CraftingStationList(); public int CraftAmount = 1; public bool RequireOnlyOneIngredient; public float QualityResultAmountMultiplier = 1f; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public ConfigEntryBase RecipeIsActive; } [PublicAPI] public class Trade { public Trader Trader; public uint Price; public uint Stack = 1u; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public string RequiredGlobalKey; } [Flags] [PublicAPI] public enum Trader { None = 0, Haldor = 1, Hildir = 2 } public struct Requirement { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(1)] public string itemName; public int amount; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public ConfigEntry amountConfig; [Description("Set to a non-zero value to apply the requirement only for a specific quality")] public int quality; } public struct CraftingStationConfig { public CraftingTable Table; public int level; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public string custom; } [Flags] public enum Configurability { Disabled = 0, Recipe = 1, Stats = 2, Drop = 4, Trader = 8, Full = 0xF } [PublicAPI] [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] public class DropTargets { public readonly List Drops = new List(); public void Add(string creatureName, float chance, int min = 1, int? max = null, bool levelMultiplier = true) { Drops.Add(new DropTarget { creature = creatureName, chance = chance, min = min, max = max.GetValueOrDefault(min), levelMultiplier = levelMultiplier }); } } public struct DropTarget { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(1)] public string creature; public int min; public int max; public float chance; public bool levelMultiplier; } public enum Toggle { On = 1, Off = 0 } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(1)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] [PublicAPI] public class Item { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class ItemConfig { [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 2, 1 })] public ConfigEntry craft; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 2, 1 })] public ConfigEntry upgrade; public ConfigEntry table; public ConfigEntry tableLevel; public ConfigEntry customTable; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public ConfigEntry maximumTableLevel; public ConfigEntry requireOneIngredient; public ConfigEntry qualityResultAmountMultiplier; } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class TraderConfig { public ConfigEntry trader; public ConfigEntry price; public ConfigEntry stack; public ConfigEntry requiredGlobalKey; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private class RequirementQuality { public int quality; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string Category; [UsedImplicitly] [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 2, 1 })] public Action CustomDrawer; public Func browsability; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [PublicAPI] public enum DamageModifier { Normal, Resistant, Weak, Immune, Ignore, VeryResistant, VeryWeak, None } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] private delegate void setDmgFunc(ref DamageTypes dmg, float value); [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class SerializedRequirements { public readonly List Reqs; public SerializedRequirements(List reqs) { Reqs = reqs; } public SerializedRequirements(string reqs) : this(reqs.Split(new char[1] { ',' }).Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (string r) => { string[] array = r.Split(new char[1] { ':' }); Requirement result = default(Requirement); result.itemName = array[0]; result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2); result.quality = ((array.Length > 2 && int.TryParse(array[2], out var result3)) ? result3 : 0); return result; }).ToList()) { } public override string ToString() { return string.Join(",", Reqs.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement r) => $"{r.itemName}:{r.amount}" + ((r.quality > 0) ? $":{r.quality}" : ""))); } [return: <5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] public static ItemDrop fetchByName(ObjectDB objectDB, string name) { GameObject itemPrefab = objectDB.GetItemPrefab(name); ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent() : null); if ((Object)(object)obj == (Object)null) { Debug.LogWarning((object)("The required item '" + name + "' does not exist.")); } return obj; } public static Requirement[] toPieceReqs(ObjectDB objectDB, SerializedRequirements craft, SerializedRequirements upgrade) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown //IL_0194: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown Dictionary dictionary = craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func)([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement r) => r.itemName), (Func)([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement r) => { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown ItemDrop val6 = ResItem(r); return (val6 != null) ? new Requirement { m_amount = (r.amountConfig?.Value ?? r.amount), m_resItem = val6, m_amountPerLevel = 0 } : ((Requirement)null); })); List list = dictionary.Values.Where([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Requirement v) => v != null).ToList(); foreach (Requirement item in upgrade.Reqs.Where((Requirement r) => r.itemName != "")) { if (item.quality > 0) { ItemDrop val = ResItem(item); if (val != null) { Requirement val2 = new Requirement { m_resItem = val, m_amountPerLevel = (item.amountConfig?.Value ?? item.amount), m_amount = 0 }; list.Add(val2); requirementQuality.Add(val2, new RequirementQuality { quality = item.quality }); } continue; } if (!dictionary.TryGetValue(item.itemName, out var value) || value == null) { ItemDrop val3 = ResItem(item); if (val3 != null) { string itemName = item.itemName; Requirement val4 = new Requirement { m_resItem = val3, m_amount = 0 }; Requirement val5 = val4; dictionary[itemName] = val4; value = val5; list.Add(value); } } if (value != null) { value.m_amountPerLevel = item.amountConfig?.Value ?? item.amount; } } return list.ToArray(); [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] ItemDrop ResItem(Requirement r) { return fetchByName(objectDB, r.itemName); } } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] private class SerializedDrop { public readonly List Drops; public SerializedDrop(List drops) { Drops = drops; } public SerializedDrop(string drops) { Drops = ((drops == "") ? ((IEnumerable)Array.Empty()) : ((IEnumerable)drops.Split(new char[1] { ',' }))).Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (string r) => { string[] array = r.Split(new char[1] { ':' }); if (array.Length <= 2 || !int.TryParse(array[2], out var result)) { result = 1; } if (array.Length <= 3 || !int.TryParse(array[3], out var result2)) { result2 = result; } bool levelMultiplier = array.Length <= 4 || array[4] != "0"; DropTarget result3 = default(DropTarget); result3.creature = array[0]; result3.chance = ((array.Length > 1 && float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) ? result4 : 1f); result3.min = result; result3.max = result2; result3.levelMultiplier = levelMultiplier; return result3; }).ToList(); } public override string ToString() { return string.Join(",", Drops.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (DropTarget r) => $"{r.creature}:{r.chance.ToString(CultureInfo.InvariantCulture)}:{r.min}:" + ((r.min == r.max) ? "" : $"{r.max}") + (r.levelMultiplier ? "" : ":0"))); } [return: <5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static Character fetchByName(ZNetScene netScene, string name) { GameObject prefab = netScene.GetPrefab(name); Character obj = ((prefab != null) ? prefab.GetComponent() : null); if ((Object)(object)obj == (Object)null) { Debug.LogWarning((object)("The drop target character '" + name + "' does not exist.")); } return obj; } public Dictionary toCharacterDrops(ZNetScene netScene, GameObject item) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Dictionary dictionary = new Dictionary(); foreach (DropTarget drop in Drops) { Character val = fetchByName(netScene, drop.creature); if (val != null) { dictionary[val] = new Drop { m_prefab = item, m_amountMin = drop.min, m_amountMax = drop.max, m_chance = drop.chance, m_levelMultiplier = drop.levelMultiplier }; } } return dictionary; } } private static readonly List registeredItems = new List(); private static readonly Dictionary itemDropMap = new Dictionary(); private static Dictionary>> activeRecipes = new Dictionary>>(); [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 1, 1, 2 })] private static Dictionary hiddenCraftRecipes = new Dictionary(); [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 1, 1, 2 })] private static Dictionary hiddenUpgradeRecipes = new Dictionary(); private static Dictionary> itemCraftConfigs = new Dictionary>(); private static Dictionary> itemDropConfigs = new Dictionary>(); private Dictionary characterDrops = new Dictionary(); private readonly Dictionary statsConfigs = new Dictionary(); private static readonly ConditionalWeakTable requirementQuality = new ConditionalWeakTable(); public static Configurability DefaultConfigurability = Configurability.Full; public Configurability? Configurable; private Configurability configurationVisible = Configurability.Full; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private TraderConfig traderConfig; public readonly GameObject Prefab; [Description("Specifies the maximum required crafting station level to upgrade and repair the item.\nDefault is calculated from crafting station level and maximum quality.")] public int MaximumRequiredStationLevel = int.MaxValue; [Description("Assigns the item as a drop item to a creature.\nUses a creature name, a drop chance and a minimum and maximum amount.")] public readonly DropTargets DropsFrom = new DropTargets(); [Description("Configures whether the item can be bought at the trader.\nDon't forget to set cost to something above 0 or the item will be sold for free.")] public readonly Trade Trade = new Trade(); internal List Conversions = new List(); internal List conversions = new List(); public Dictionary Recipes = new Dictionary(); [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private LocalizeKey _name; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private LocalizeKey _description; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static object configManager; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static Localization _english; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static BaseUnityPlugin _plugin; private static bool hasConfigSync = true; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static object _configSync; private Configurability configurability => Configurable ?? DefaultConfigurability; [Description("Specifies the resources needed to craft the item.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the item should need.")] public RequiredResourceList RequiredItems => this[""].RequiredItems; [Description("Specifies the resources needed to upgrade the item.\nUse .Add to add resources with their internal ID and an amount. This amount will be multipled by the item quality level.\nUse one .Add for each resource type the upgrade should need.")] public RequiredResourceList RequiredUpgradeItems => this[""].RequiredUpgradeItems; [Description("Specifies the crafting station needed to craft the item.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.\nUse one .Add for each crafting station.")] public CraftingStationList Crafting => this[""].Crafting; [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] [Description("Specifies a config entry which toggles whether a recipe is active.")] public ConfigEntryBase RecipeIsActive { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] get { return this[""].RecipeIsActive; } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] set { this[""].RecipeIsActive = value; } } [Description("Specifies the number of items that should be given to the player with a single craft of the item.\nDefaults to 1.")] public int CraftAmount { get { return this[""].CraftAmount; } set { this[""].CraftAmount = value; } } public bool RequireOnlyOneIngredient { get { return this[""].RequireOnlyOneIngredient; } set { this[""].RequireOnlyOneIngredient = value; } } public float QualityResultAmountMultiplier { get { return this[""].QualityResultAmountMultiplier; } set { this[""].QualityResultAmountMultiplier = value; } } public ItemRecipe this[string name] { get { if (Recipes.TryGetValue(name, out var value)) { return value; } return Recipes[name] = new ItemRecipe(); } } public LocalizeKey Name { get { LocalizeKey name = _name; if (name != null) { return name; } SharedData shared = Prefab.GetComponent().m_itemData.m_shared; if (shared.m_name.StartsWith("$")) { _name = new LocalizeKey(shared.m_name); } else { string text = "$item_" + ((Object)Prefab).name.Replace(" ", "_"); _name = new LocalizeKey(text).English(shared.m_name); shared.m_name = text; } return _name; } } public LocalizeKey Description { get { LocalizeKey description = _description; if (description != null) { return description; } SharedData shared = Prefab.GetComponent().m_itemData.m_shared; if (shared.m_description.StartsWith("$")) { _description = new LocalizeKey(shared.m_description); } else { string text = "$itemdesc_" + ((Object)Prefab).name.Replace(" ", "_"); _description = new LocalizeKey(text).English(shared.m_description); shared.m_description = text; } return _description; } } private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English")); private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(2)] private static object configSync { [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(2)] get { if (_configSync == null && hasConfigSync) { Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync"); if ((object)type != null) { _configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " ItemManager"); type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString()); type.GetProperty("IsLocked").SetValue(_configSync, true); } else { hasConfigSync = false; } } return _configSync; } } private static bool GeneratedConfigsEnabled() { try { return !(((object)plugin).GetType().GetField("EnableGeneratedConfigs", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) is bool flag) || flag; } catch { return true; } } public Item(string assetBundleFileName, string prefabName, string folderName = "assets") : this(PrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName) { } public Item(AssetBundle bundle, string prefabName) : this(PrefabManager.RegisterPrefab(bundle, prefabName, addToObjectDb: true), skipRegistering: true) { } public Item(GameObject prefab, bool skipRegistering = false) { if (!skipRegistering) { PrefabManager.RegisterPrefab(prefab, addToObjectDb: true); } Prefab = prefab; registeredItems.Add(this); itemDropMap[Prefab.GetComponent()] = this; Prefab.GetComponent().m_itemData.m_dropPrefab = Prefab; } public void ToggleConfigurationVisibility(Configurability visible) { configurationVisible = visible; if (itemDropConfigs.TryGetValue(this, out var value)) { Toggle((ConfigEntryBase)(object)value, Configurability.Drop); } if (itemCraftConfigs.TryGetValue(this, out var value2)) { foreach (ItemConfig value4 in value2.Values) { ToggleObj(value4, Configurability.Recipe); } } foreach (Conversion conversion in Conversions) { if (conversion.config != null) { ToggleObj(conversion.config, Configurability.Recipe); } } foreach (KeyValuePair statsConfig in statsConfigs) { Toggle(statsConfig.Key, Configurability.Stats); if ((visible & Configurability.Stats) != 0) { statsConfig.Value(); } } reloadConfigDisplay(); void Toggle(ConfigEntryBase cfg, Configurability check) { object[] tags = cfg.Description.Tags; for (int j = 0; j < tags.Length; j++) { if (tags[j] is ConfigurationManagerAttributes configurationManagerAttributes) { configurationManagerAttributes.Browsable = (visible & check) != 0 && (configurationManagerAttributes.browsability == null || configurationManagerAttributes.browsability()); } } } void ToggleObj(object obj, Configurability check) { FieldInfo[] fields = obj.GetType().GetFields(); for (int i = 0; i < fields.Length; i++) { object? value3 = fields[i].GetValue(obj); ConfigEntryBase val = (ConfigEntryBase)((value3 is ConfigEntryBase) ? value3 : null); if (val != null) { Toggle(val, check); } } } } internal static void reloadConfigDisplay() { object obj = configManager?.GetType().GetProperty("DisplayingWindow").GetValue(configManager); if (obj is bool && (bool)obj) { configManager.GetType().GetMethod("BuildSettingList").Invoke(configManager, Array.Empty()); } } private void UpdateItemTableConfig(string recipeKey, CraftingTable table, string customTableValue) { if (activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(recipeKey, out var value)) { value.First().m_enabled = table != CraftingTable.Disabled; if ((uint)table <= 1u) { value.First().m_craftingStation = null; } else if (table == CraftingTable.Custom) { Recipe obj = value.First(); GameObject prefab = ZNetScene.instance.GetPrefab(customTableValue); obj.m_craftingStation = ((prefab != null) ? prefab.GetComponent() : null); } else { value.First().m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName(table)).GetComponent(); } } } private void UpdateCraftConfig(string recipeKey, SerializedRequirements craftRequirements, SerializedRequirements upgradeRequirements) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !activeRecipes.ContainsKey(this) || !activeRecipes[this].TryGetValue(recipeKey, out var value)) { return; } foreach (Recipe item in value) { item.m_resources = SerializedRequirements.toPieceReqs(ObjectDB.instance, craftRequirements, upgradeRequirements); } } internal static void Patch_FejdStartup() { //IL_0c3a: Unknown result type (might be due to invalid IL or missing references) //IL_0c3f: Unknown result type (might be due to invalid IL or missing references) //IL_17e0: Unknown result type (might be due to invalid IL or missing references) //IL_17ea: Expected O, but got Unknown //IL_0ca2: Unknown result type (might be due to invalid IL or missing references) //IL_0ca5: Unknown result type (might be due to invalid IL or missing references) //IL_0cfb: Expected I4, but got Unknown //IL_0929: Unknown result type (might be due to invalid IL or missing references) //IL_0933: Expected O, but got Unknown //IL_0dce: Unknown result type (might be due to invalid IL or missing references) //IL_0dd1: Unknown result type (might be due to invalid IL or missing references) //IL_0dd3: Invalid comparison between Unknown and I4 //IL_0dd5: Unknown result type (might be due to invalid IL or missing references) //IL_0dd9: Invalid comparison between Unknown and I4 //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Expected O, but got Unknown //IL_0ddb: Unknown result type (might be due to invalid IL or missing references) //IL_0ddf: Invalid comparison between Unknown and I4 //IL_0f18: Unknown result type (might be due to invalid IL or missing references) //IL_0f1b: Unknown result type (might be due to invalid IL or missing references) //IL_0f1d: Invalid comparison between Unknown and I4 //IL_0a4c: Unknown result type (might be due to invalid IL or missing references) //IL_0a56: Expected O, but got Unknown //IL_0af7: Unknown result type (might be due to invalid IL or missing references) //IL_0b01: Expected O, but got Unknown //IL_0f1f: Unknown result type (might be due to invalid IL or missing references) //IL_0f23: Unknown result type (might be due to invalid IL or missing references) //IL_0f25: Invalid comparison between Unknown and I4 //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Expected O, but got Unknown //IL_0bab: Unknown result type (might be due to invalid IL or missing references) //IL_0bb5: Expected O, but got Unknown //IL_0f27: Unknown result type (might be due to invalid IL or missing references) //IL_0f2b: Invalid comparison between Unknown and I4 //IL_0f9a: Unknown result type (might be due to invalid IL or missing references) //IL_0f9d: Invalid comparison between Unknown and I4 //IL_05aa: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Expected O, but got Unknown //IL_119a: Unknown result type (might be due to invalid IL or missing references) //IL_11a1: Invalid comparison between Unknown and I4 //IL_126a: Unknown result type (might be due to invalid IL or missing references) //IL_126f: Unknown result type (might be due to invalid IL or missing references) //IL_1271: Unknown result type (might be due to invalid IL or missing references) //IL_1275: Unknown result type (might be due to invalid IL or missing references) //IL_1277: Invalid comparison between Unknown and I4 //IL_12e6: Unknown result type (might be due to invalid IL or missing references) //IL_12e9: Unknown result type (might be due to invalid IL or missing references) //IL_12eb: Invalid comparison between Unknown and I4 //IL_12ed: Unknown result type (might be due to invalid IL or missing references) //IL_12f1: Invalid comparison between Unknown and I4 //IL_12f3: Unknown result type (might be due to invalid IL or missing references) //IL_12f7: Invalid comparison between Unknown and I4 //IL_16a2: Unknown result type (might be due to invalid IL or missing references) //IL_16a5: Invalid comparison between Unknown and I4 Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager"); if (DefaultConfigurability != 0) { bool saveOnConfigSet = plugin.Config.SaveOnConfigSet; plugin.Config.SaveOnConfigSet = false; foreach (Item item4 in registeredItems.Where([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Item i) => i.configurability != Configurability.Disabled)) { Item item3 = item4; if (!GeneratedConfigsEnabled()) { if (item3.Trade.Trader != 0) { PrefabManager.AddItemToTrader(item3.Prefab, item3.Trade.Trader, item3.Trade.Price, item3.Trade.Stack, item3.Trade.RequiredGlobalKey); } continue; } string name2 = item3.Prefab.GetComponent().m_itemData.m_shared.m_name; string englishName = new Regex("[=\\n\\t\\\\\"\\'\\[\\]]*").Replace(english.Localize(name2), "").Trim(); string localizedName = Localization.instance.Localize(name2).Trim(); int order = 0; if ((item3.configurability & Configurability.Recipe) != 0) { itemCraftConfigs[item3] = new Dictionary(); foreach (string item5 in item3.Recipes.Keys.DefaultIfEmpty("")) { string configKey = item5; string text = ((configKey == "") ? "" : (" (" + configKey + ")")); if (!item3.Recipes.ContainsKey(configKey) || item3.Recipes[configKey].Crafting.Stations.Count <= 0) { continue; } ItemConfig itemConfig2 = (itemCraftConfigs[item3][configKey] = new ItemConfig()); ItemConfig cfg = itemConfig2; List hideWhenNoneAttributes = new List(); cfg.table = config(englishName, "Crafting Station" + text, item3.Recipes[configKey].Crafting.Stations.First().Table, new ConfigDescription("Crafting station where " + englishName + " is available.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName } })); ConfigurationManagerAttributes customTableAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = CustomTableBrowsability, Browsable = (CustomTableBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; cfg.customTable = config(englishName, "Custom Crafting Station" + text, item3.Recipes[configKey].Crafting.Stations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); cfg.table.SettingChanged += TableConfigChanged; cfg.customTable.SettingChanged += TableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = TableLevelBrowsability, Browsable = (TableLevelBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; hideWhenNoneAttributes.Add(configurationManagerAttributes); cfg.tableLevel = config(englishName, "Crafting Station Level" + text, item3.Recipes[configKey].Crafting.Stations.First().level, new ConfigDescription("Required crafting station level to craft " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes })); cfg.tableLevel.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value3)) { value3.First().m_minStationLevel = cfg.tableLevel.Value; } }; if ((!item3.Recipes[configKey].RequiredItems.Free || item3.Recipes[configKey].RequiredItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredItems.Requirements.All((Requirement r) => r.amountConfig == null)) { cfg.craft = itemConfig("Crafting Costs" + text, new SerializedRequirements(item3.Recipes[configKey].RequiredItems.Requirements).ToString(), "Item costs to craft " + englishName, isUpgrade: false); } if (item3.Prefab.GetComponent().m_itemData.m_shared.m_maxQuality > 1 && (!item3.Recipes[configKey].RequiredUpgradeItems.Free || item3.Recipes[configKey].RequiredUpgradeItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredUpgradeItems.Requirements.All((Requirement r) => r.amountConfig == null)) { cfg.upgrade = itemConfig("Upgrading Costs" + text, new SerializedRequirements(item3.Recipes[configKey].RequiredUpgradeItems.Requirements).ToString(), "Item costs per level to upgrade " + englishName, isUpgrade: true); } if (cfg.craft != null) { cfg.craft.SettingChanged += ConfigChanged; } if (cfg.upgrade != null) { cfg.upgrade.SettingChanged += ConfigChanged; } void ConfigChanged(object o, EventArgs e) { item3.UpdateCraftConfig(configKey, new SerializedRequirements(cfg.craft?.Value ?? ""), new SerializedRequirements(cfg.upgrade?.Value ?? "")); } bool CustomTableBrowsability() { return cfg.table.Value == CraftingTable.Custom; } bool ItemBrowsability() { return cfg.table.Value != CraftingTable.Disabled; } void TableConfigChanged(object o, EventArgs e) { item3.UpdateItemTableConfig(configKey, cfg.table.Value, cfg.customTable.Value); customTableAttributes.Browsable = cfg.table.Value == CraftingTable.Custom; foreach (ConfigurationManagerAttributes item6 in hideWhenNoneAttributes) { item6.Browsable = cfg.table.Value != CraftingTable.Disabled; } reloadConfigDisplay(); } bool TableLevelBrowsability() { return cfg.table.Value != CraftingTable.Disabled; } ConfigEntry itemConfig(string name, string value, string desc, bool isUpgrade) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes3 = new ConfigurationManagerAttributes { CustomDrawer = drawRequirementsConfigTable(item3, isUpgrade), Order = (order -= 1), browsability = ItemBrowsability, Browsable = (ItemBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; hideWhenNoneAttributes.Add(configurationManagerAttributes3); return config(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes3 })); } } if ((item3.configurability & Configurability.Drop) != 0) { ConfigEntry val3 = (itemDropConfigs[item3] = config(englishName, "Drops from", new SerializedDrop(item3.DropsFrom.Drops).ToString(), new ConfigDescription(englishName + " drops from this creature.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = drawDropsConfigTable, Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Drop) != 0) } }))); val3.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { item3.UpdateCharacterDrop(); }; } for (int j = 0; j < item3.Conversions.Count; j++) { string text2 = ((item3.Conversions.Count > 1) ? $"{j + 1}. " : ""); Conversion conversion = item3.Conversions[j]; conversion.config = new Conversion.ConversionConfig(); int index = j; conversion.config.input = config(englishName, text2 + "Conversion Input Item", conversion.Input, new ConfigDescription("Input item to create " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0) } })); conversion.config.input.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { if (index < item3.conversions.Count) { ObjectDB instance = ObjectDB.instance; if (instance != null) { ItemDrop from = SerializedRequirements.fetchByName(instance, conversion.config.input.Value); item3.conversions[index].m_from = from; UpdatePiece(); } } }; conversion.config.piece = config(englishName, text2 + "Conversion Piece", conversion.Piece, new ConfigDescription("Conversion piece used to create " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0) } })); conversion.config.piece.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { UpdatePiece(); }; conversion.config.customPiece = config(englishName, text2 + "Conversion Custom Piece", conversion.customPiece ?? "", new ConfigDescription("Custom conversion piece to create " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0) } })); conversion.config.customPiece.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { UpdatePiece(); }; void UpdatePiece() { if (index < item3.conversions.Count && Object.op_Implicit((Object)(object)ZNetScene.instance)) { string text3 = ((conversion.config.piece.Value == ConversionPiece.Disabled) ? null : ((conversion.config.piece.Value == ConversionPiece.Custom) ? conversion.config.customPiece.Value : getInternalName(conversion.config.piece.Value))); string activePiece = conversion.config.activePiece; if (conversion.config.activePiece != null) { int num = ZNetScene.instance.GetPrefab(conversion.config.activePiece).GetComponent().m_conversion.IndexOf(item3.conversions[index]); if (num >= 0) { Smelter[] array2 = Resources.FindObjectsOfTypeAll(); foreach (Smelter val4 in array2) { if (Utils.GetPrefabName(((Component)val4).gameObject) == activePiece) { val4.m_conversion.RemoveAt(num); } } } conversion.config.activePiece = null; } if (item3.conversions[index].m_from != null && conversion.config.piece.Value != 0) { GameObject prefab = ZNetScene.instance.GetPrefab(text3); if (((prefab != null) ? prefab.GetComponent() : null) != null) { conversion.config.activePiece = text3; Smelter[] array2 = Resources.FindObjectsOfTypeAll(); foreach (Smelter val5 in array2) { if (Utils.GetPrefabName(((Component)val5).gameObject) == text3) { val5.m_conversion.Add(item3.conversions[index]); } } } } } } } } if ((item3.configurability & Configurability.Stats) != 0) { item3.statsConfigs.Clear(); SharedData shared2 = item3.Prefab.GetComponent().m_itemData.m_shared; ItemType itemType = shared2.m_itemType; statcfg("Trader Value", "Trader value of " + englishName + ".", (SharedData shared) => shared.m_value, delegate(SharedData shared, int value) { shared.m_value = value; }); bool flag; switch (itemType - 3) { case 0: case 1: case 2: case 3: case 4: case 8: case 9: case 11: case 14: case 16: case 19: flag = true; break; default: flag = false; break; } if (flag) { statcfg("Durability", "Durability of " + englishName + ".", (SharedData shared) => shared.m_maxDurability, delegate(SharedData shared, float value) { shared.m_maxDurability = value; }); statcfg("Movement Speed Modifier", "Movement speed modifier of " + englishName + ".", (SharedData shared) => shared.m_movementModifier, delegate(SharedData shared, float value) { shared.m_movementModifier = value; }); } if ((itemType - 3 <= 2 || (int)itemType == 14 || (int)itemType == 22) ? true : false) { statcfg("Block Armor", "Block armor of " + englishName + ".", (SharedData shared) => shared.m_blockPower, delegate(SharedData shared, float value) { shared.m_blockPower = value; }); statcfg("Block Force", "Block force of " + englishName + ".", (SharedData shared) => shared.m_deflectionForce, delegate(SharedData shared, float value) { shared.m_deflectionForce = value; }); statcfg("Parry Bonus", "Parry bonus of " + englishName + ".", (SharedData shared) => shared.m_timedBlockBonus, delegate(SharedData shared, float value) { shared.m_timedBlockBonus = value; }); } else if ((itemType - 6 <= 1 || itemType - 11 <= 1 || (int)itemType == 17) ? true : false) { statcfg("Armor", "Armor of " + englishName + ".", (SharedData shared) => shared.m_armor, delegate(SharedData shared, float value) { shared.m_armor = value; }); } if ((int)itemType == 2 && shared2.m_food > 0f) { statcfg("Health", "Health value of " + englishName + ".", (SharedData shared) => shared.m_food, delegate(SharedData shared, float value) { shared.m_food = value; }); statcfg("Stamina", "Stamina value of " + englishName + ".", (SharedData shared) => shared.m_foodStamina, delegate(SharedData shared, float value) { shared.m_foodStamina = value; }); statcfg("Eitr", "Eitr value of " + englishName + ".", (SharedData shared) => shared.m_foodEitr, delegate(SharedData shared, float value) { shared.m_foodEitr = value; }); statcfg("Duration", "Duration of " + englishName + ".", (SharedData shared) => shared.m_foodBurnTime, delegate(SharedData shared, float value) { shared.m_foodBurnTime = value; }); statcfg("Health Regen", "Health regen value of " + englishName + ".", (SharedData shared) => shared.m_foodRegen, delegate(SharedData shared, float value) { shared.m_foodRegen = value; }); } if ((int)shared2.m_skillType == 10) { statcfg("Health Cost", "Health cost of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackHealth, delegate(SharedData shared, float value) { shared.m_attack.m_attackHealth = value; }); statcfg("Health Cost Percentage", "Health cost percentage of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackHealthPercentage, delegate(SharedData shared, float value) { shared.m_attack.m_attackHealthPercentage = value; }); } SkillType skillType = shared2.m_skillType; if (skillType - 9 <= 1) { statcfg("Eitr Cost", "Eitr cost of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackEitr, delegate(SharedData shared, float value) { shared.m_attack.m_attackEitr = value; }); } if ((itemType - 3 <= 1 || (int)itemType == 14 || (int)itemType == 22) ? true : false) { statcfg("Attack Stamina", "Attack stamina of " + englishName + ".", (SharedData shared) => shared.m_attack.m_attackStamina, delegate(SharedData shared, float value) { shared.m_attack.m_attackStamina = value; }); SetDmg("True", (DamageTypes dmg) => dmg.m_damage, delegate(ref DamageTypes dmg, float val) { dmg.m_damage = val; }); SetDmg("Slash", (DamageTypes dmg) => dmg.m_slash, delegate(ref DamageTypes dmg, float val) { dmg.m_slash = val; }); SetDmg("Pierce", (DamageTypes dmg) => dmg.m_pierce, delegate(ref DamageTypes dmg, float val) { dmg.m_pierce = val; }); SetDmg("Blunt", (DamageTypes dmg) => dmg.m_blunt, delegate(ref DamageTypes dmg, float val) { dmg.m_blunt = val; }); SetDmg("Chop", (DamageTypes dmg) => dmg.m_chop, delegate(ref DamageTypes dmg, float val) { dmg.m_chop = val; }); SetDmg("Pickaxe", (DamageTypes dmg) => dmg.m_pickaxe, delegate(ref DamageTypes dmg, float val) { dmg.m_pickaxe = val; }); SetDmg("Fire", (DamageTypes dmg) => dmg.m_fire, delegate(ref DamageTypes dmg, float val) { dmg.m_fire = val; }); SetDmg("Poison", (DamageTypes dmg) => dmg.m_poison, delegate(ref DamageTypes dmg, float val) { dmg.m_poison = val; }); SetDmg("Frost", (DamageTypes dmg) => dmg.m_frost, delegate(ref DamageTypes dmg, float val) { dmg.m_frost = val; }); SetDmg("Lightning", (DamageTypes dmg) => dmg.m_lightning, delegate(ref DamageTypes dmg, float val) { dmg.m_lightning = val; }); SetDmg("Spirit", (DamageTypes dmg) => dmg.m_spirit, delegate(ref DamageTypes dmg, float val) { dmg.m_spirit = val; }); if ((int)itemType == 4) { statcfg("Stamina Drain", "Stamina drain per second while drawing " + englishName + ".", (SharedData shared) => shared.m_attack.m_drawStaminaDrain, delegate(SharedData shared, float value) { shared.m_attack.m_drawStaminaDrain = value; }); } } } List traderAttributes; if ((item3.configurability & Configurability.Trader) != 0) { traderAttributes = new List(); item3.traderConfig = new TraderConfig { trader = config(englishName, "Trader Selling", item3.Trade.Trader, new ConfigDescription("Which traders sell " + englishName + ".", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Browsable = ((item3.configurationVisible & Configurability.Trader) != 0), Category = localizedName } })) }; item3.traderConfig.trader.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { item3.ReloadTraderConfiguration(); foreach (ConfigurationManagerAttributes item7 in traderAttributes) { item7.Browsable = TraderBrowsability(); } reloadConfigDisplay(); }; item3.traderConfig.price = traderConfig("Trader Price", item3.Trade.Price, "Price of " + englishName + " at the trader."); if (item3.traderConfig.trader.Value != 0) { PrefabManager.AddItemToTrader(item3.Prefab, item3.traderConfig.trader.Value, item3.traderConfig.price.Value, item3.Trade.Stack, item3.Trade.RequiredGlobalKey); } } else if (item3.Trade.Trader != 0) { PrefabManager.AddItemToTrader(item3.Prefab, item3.Trade.Trader, item3.Trade.Price, item3.Trade.Stack, item3.Trade.RequiredGlobalKey); } void SetDmg(string dmgType, Func readDmg, setDmgFunc setDmg) { statcfg(dmgType + " Damage", dmgType + " damage dealt by " + englishName + ".", (SharedData shared) => readDmg(shared.m_damages), delegate(SharedData shared, float val) { setDmg(ref shared.m_damages, val); }); statcfg(dmgType + " Damage Per Level", dmgType + " damage dealt increase per level for " + englishName + ".", (SharedData shared) => readDmg(shared.m_damagesPerLevel), delegate(SharedData shared, float val) { setDmg(ref shared.m_damagesPerLevel, val); }); } bool TraderBrowsability() { return item3.traderConfig.trader.Value != Trader.None; } void statcfg(string configName, string description, [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 1, 1, 0 })] Func readDefault, [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 1, 1, 0 })] Action setValue) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown SharedData shared3 = item3.Prefab.GetComponent().m_itemData.m_shared; ConfigEntry cfg2 = config(englishName, configName, readDefault(shared3), new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Stats) != 0) } })); if ((item3.configurationVisible & Configurability.Stats) != 0) { setValue(shared3, cfg2.Value); } item3.statsConfigs.Add((ConfigEntryBase)(object)cfg2, ApplyConfig); cfg2.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { if ((item3.configurationVisible & Configurability.Stats) != 0) { ApplyConfig(); } }; void ApplyConfig() { item3.ApplyToAllInstances(delegate(ItemData item) { setValue(item.m_shared, cfg2.Value); }); } } [return: <5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 1, 0 })] ConfigEntry traderConfig(string name, [<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(0)] T value, string desc) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes2 = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = TraderBrowsability, Browsable = (TraderBrowsability() && (item3.configurationVisible & Configurability.Trader) != 0), Category = localizedName }; traderAttributes.Add(configurationManagerAttributes2); ConfigEntry obj = config(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes2 })); obj.SettingChanged += [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (object _, EventArgs _) => { item3.ReloadTraderConfiguration(); }; return obj; } } if (saveOnConfigSet) { plugin.Config.SaveOnConfigSet = true; plugin.Config.Save(); } } configManager = ((type == null) ? null : Chainloader.ManagerObject.GetComponent(type)); foreach (Item registeredItem in registeredItems) { Item item2 = registeredItem; foreach (KeyValuePair recipe in item2.Recipes) { KeyValuePair kv = recipe; RequiredResourceList[] array = new RequiredResourceList[2] { kv.Value.RequiredItems, kv.Value.RequiredUpgradeItems }; foreach (RequiredResourceList requiredResourceList in array) { for (int l = 0; l < requiredResourceList.Requirements.Count; l++) { ConfigEntry amountCfg; int resourceIndex; if ((item2.configurability & Configurability.Recipe) != 0) { amountCfg = requiredResourceList.Requirements[l].amountConfig; if (amountCfg != null) { resourceIndex = l; amountCfg.SettingChanged += ConfigChanged; } } void ConfigChanged(object o, EventArgs e) { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && activeRecipes.ContainsKey(item2) && activeRecipes[item2].TryGetValue(kv.Key, out var value2)) { foreach (Recipe item8 in value2) { item8.m_resources[resourceIndex].m_amount = amountCfg.Value; } } } } } } item2.InitializeNewRegisteredItem(); } } private void InitializeNewRegisteredItem() { foreach (KeyValuePair recipe in Recipes) { KeyValuePair kv = recipe; ConfigEntryBase enabledCfg = kv.Value.RecipeIsActive; if (enabledCfg != null) { ((object)enabledCfg).GetType().GetEvent("SettingChanged").AddEventHandler(enabledCfg, new EventHandler(ConfigChanged)); } void ConfigChanged(object o, EventArgs e) { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(kv.Key, out var value)) { foreach (Recipe item in value) { item.m_enabled = (int)enabledCfg.BoxedValue != 0; } } } } } public void ReloadCraftingConfiguration() { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && ObjectDB.instance.GetItemPrefab(StringExtensionMethods.GetStableHashCode(((Object)Prefab).name)) == null) { registerRecipesInObjectDB(ObjectDB.instance); ObjectDB.instance.m_items.Add(Prefab); ObjectDB.instance.m_itemByHash.Add(StringExtensionMethods.GetStableHashCode(((Object)Prefab).name), Prefab); ZNetScene.instance.m_prefabs.Add(Prefab); ZNetScene.instance.m_namedPrefabs.Add(StringExtensionMethods.GetStableHashCode(((Object)Prefab).name), Prefab); } foreach (string item in Recipes.Keys.DefaultIfEmpty("")) { if (Recipes.TryGetValue(item, out var value) && value.Crafting.Stations.Count > 0) { UpdateItemTableConfig(item, value.Crafting.Stations.First().Table, value.Crafting.Stations.First().custom ?? ""); UpdateCraftConfig(item, new SerializedRequirements(value.RequiredItems.Requirements), new SerializedRequirements(value.RequiredUpgradeItems.Requirements)); } } } private void ReloadTraderConfiguration() { if (traderConfig.trader.Value == Trader.None) { PrefabManager.RemoveItemFromTrader(Prefab); } else { PrefabManager.AddItemToTrader(Prefab, traderConfig.trader.Value, traderConfig.price.Value, Trade.Stack, Trade.RequiredGlobalKey); } } public static void ApplyToAllInstances(GameObject prefab, Action callback) { callback(prefab.GetComponent().m_itemData); string name = prefab.GetComponent().m_itemData.m_shared.m_name; Inventory[] source = (from c in Player.s_players.Select([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Player p) => ((Humanoid)p).GetInventory()).Concat(from c in Object.FindObjectsOfType() select c.GetInventory()) where c != null select c).ToArray(); foreach (ItemData item in (from i in (from p in ObjectDB.instance.m_items select p.GetComponent() into c where Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((Component)c).GetComponent()) select c).Concat(ItemDrop.s_instances) select i.m_itemData).Concat(source.SelectMany([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (Inventory i) => i.GetAllItems()))) { if (item.m_shared.m_name == name) { callback(item); } } } public void ApplyToAllInstances(Action callback) { ApplyToAllInstances(Prefab, callback); } [<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] [return: <5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(1)] private static string getInternalName(T value) where T : struct { return ((InternalName)typeof(T).GetMember(value.ToString())[0].GetCustomAttributes(typeof(InternalName)).First()).internalName; } private void registerRecipesInObjectDB(ObjectDB objectDB) { //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Expected O, but got Unknown activeRecipes[this] = new Dictionary>(); itemCraftConfigs.TryGetValue(this, out var value); foreach (KeyValuePair recipe in Recipes) { List list = new List(); foreach (CraftingStationConfig station in recipe.Value.Crafting.Stations) { ItemConfig itemConfig = value?[recipe.Key]; Recipe val = ScriptableObject.CreateInstance(); string name = ((Object)Prefab).name; CraftingTable table = station.Table; ((Object)val).name = name + "_Recipe_" + table; val.m_amount = recipe.Value.CraftAmount; bool enabled; if (itemConfig != null) { enabled = itemConfig.table.Value != CraftingTable.Disabled; } else { ConfigEntryBase recipeIsActive = recipe.Value.RecipeIsActive; enabled = (int)(((recipeIsActive != null) ? recipeIsActive.BoxedValue : null) ?? ((object)1)) != 0; } val.m_enabled = enabled; val.m_item = Prefab.GetComponent(); val.m_resources = SerializedRequirements.toPieceReqs(objectDB, (itemConfig?.craft == null) ? new SerializedRequirements(recipe.Value.RequiredItems.Requirements) : new SerializedRequirements(itemConfig.craft.Value), (itemConfig?.upgrade == null) ? new SerializedRequirements(recipe.Value.RequiredUpgradeItems.Requirements) : new SerializedRequirements(itemConfig.upgrade.Value)); table = ((itemConfig == null || list.Count > 0) ? station.Table : itemConfig.table.Value); if ((uint)table <= 1u) { val.m_craftingStation = null; } else if (((itemConfig == null || list.Count > 0) ? station.Table : itemConfig.table.Value) == CraftingTable.Custom) { GameObject prefab = ZNetScene.instance.GetPrefab((itemConfig == null || list.Count > 0) ? station.custom : itemConfig.customTable.Value); if (prefab != null) { val.m_craftingStation = prefab.GetComponent(); } else { Debug.LogWarning((object)("Custom crafting station '" + ((itemConfig == null || list.Count > 0) ? station.custom : itemConfig.customTable.Value) + "' does not exist")); } } else { val.m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName((itemConfig == null || list.Count > 0) ? station.Table : itemConfig.table.Value)).GetComponent(); } val.m_minStationLevel = ((itemConfig == null || list.Count > 0) ? station.level : itemConfig.tableLevel.Value); val.m_requireOnlyOneIngredient = recipe.Value.RequireOnlyOneIngredient; val.m_qualityResultAmountMultiplier = recipe.Value.QualityResultAmountMultiplier; list.Add(val); RequiredResourceList requiredItems = recipe.Value.RequiredItems; if (requiredItems != null && !requiredItems.Free) { List requirements = requiredItems.Requirements; if (requirements != null && requirements.Count == 0) { hiddenCraftRecipes.Add(val, recipe.Value.RecipeIsActive); } } requiredItems = recipe.Value.RequiredUpgradeItems; if (requiredItems != null && !requiredItems.Free) { List requirements = requiredItems.Requirements; if (requirements != null && requirements.Count == 0) { hiddenUpgradeRecipes.Add(val, recipe.Value.RecipeIsActive); } } } activeRecipes[this].Add(recipe.Key, list); objectDB.m_recipes.AddRange(list); } conversions = new List(); for (int i = 0; i < Conversions.Count; i++) { Conversion conversion = Conversions[i]; conversions.Add(new ItemConversion { m_from = SerializedRequirements.fetchByName(ObjectDB.instance, conversion.config?.input.Value ?? conversion.Input), m_to = Prefab.GetComponent() }); ConversionPiece conversionPiece = conversion.config?.piece.Value ?? conversion.Piece; string text = null; if (conversionPiece != 0 && conversions[i].m_from != null) { text = ((conversionPiece != ConversionPiece.Custom) ? getInternalName(conversionPiece) : (conversion.config?.customPiece.Value ?? conversion.customPiece)); GameObject prefab2 = ZNetScene.instance.GetPrefab(text); Smelter val2 = ((prefab2 != null) ? prefab2.GetComponent() : null); if (val2 != null) { val2.m_conversion.Add(conversions[i]); } else { text = null; } } if (conversion.config != null) { conversion.config.activePiece = text; } } } [HarmonyPriority(0)] internal static void Patch_ObjectDBInit(ObjectDB __instance) { if ((Object)(object)__instance.GetItemPrefab("YagluthDrop") == (Object)null) { return; } hiddenCraftRecipes.Clear(); hiddenUpgradeRecipes.Clear(); foreach (Item registeredItem in registeredItems) { registeredItem.registerRecipesInObjectDB(__instance); } } internal static void Patch_TraderGetAvailableItems(Trader __instance, ref List __result) { string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); Trader trader2 = ((prefabName == "Haldor") ? Trader.Haldor : ((prefabName == "Hildir") ? Trader.Hildir : Trader.None)); Trader trader = trader2; __result.AddRange(from tuple in PrefabManager.CustomTradeItems.Values where (tuple.Item1 & trader) != 0 select tuple.Item2 into tradeItem where string.IsNullOrEmpty(tradeItem.m_requiredGlobalKey) || ZoneSystem.instance.GetGlobalKey(tradeItem.m_requiredGlobalKey) select tradeItem); } internal static void Patch_OnAddSmelterInput(ItemData item, bool __result) { if (__result) { ((Humanoid)Player.m_localPlayer).UnequipItem(item, true); } } internal static void Patch_MaximumRequiredStationLevel(Recipe __instance, ref int __result, int quality) { if (!itemDropMap.TryGetValue(__instance.m_item, out var value)) { return; } IEnumerable source; if (!itemCraftConfigs.TryGetValue(value, out var value2)) { source = Enumerable.Empty(); } else { CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation(); if (currentCraftingStation != null) { string stationName = Utils.GetPrefabName(((Component)currentCraftingStation).gameObject); source = from c in value2.Where([<702532f4-32dc-46a6-8d9a-cabd38c9424b>NullableContext(0)] (KeyValuePair c) => { switch (c.Value.table.Value) { case CraftingTable.Disabled: case CraftingTable.Inventory: return false; case CraftingTable.Custom: return c.Value.customTable.Value == stationName; default: return getInternalName(c.Value.table.Value) == stationName; } }) select c.Value; } else { source = value2.Values; } } __result = Mathf.Min(Mathf.Max(1, __instance.m_minStationLevel) + (quality - 1), (from cfg in source where cfg.maximumTableLevel != null select cfg.maximumTableLevel.Value).DefaultIfEmpty(value.MaximumRequiredStationLevel).Max()); } internal static void Patch_GetAvailableRecipesPrefix([<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 2, 1, 1, 1, 2 })] ref Dictionary> __state) { if (__state == null) { __state = new Dictionary>(); } Dictionary dictionary; if (InventoryGui.instance.InCraftTab()) { dictionary = hiddenCraftRecipes; } else { if (!InventoryGui.instance.InUpradeTab()) { return; } dictionary = hiddenUpgradeRecipes; } foreach (Recipe key in dictionary.Keys) { key.m_enabled = false; } __state[Assembly.GetExecutingAssembly()] = dictionary; } internal static void Patch_GetAvailableRecipesFinalizer([<5ea91132-7291-4072-bba1-fdb04647c6e6>Nullable(new byte[] { 1, 1, 1, 1, 2 })] Dictionary> __state) { if (!__state.TryGetValue(Assembly.GetExecutingAssembly(), out var value)) { return; } foreach (KeyValuePair item in value) { Recipe key = item.Key; ConfigEntryBase value2 = item.Value; key.m_enabled = (int)(((value2 != null) ? value2.BoxedValue : null) ?? ((object)1)) != 0; } } internal static IEnumerable Transpile_SetupRequirementList(IEnumerable instructionsEnumerable, ILGenerator ilg) { //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Expected O, but got Unknown //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown List list = instructionsEnumerable.ToList(); MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(InventoryGui), "SetupRequirement", (Type[])null, (Type[])null); CodeInstruction val = null; CodeInstruction val2 = null; LocalBuilder localBuilder = ilg.DeclareLocal(typeof(int)); Dictionary dictionary = new Dictionary(); bool flag = false; int num = 0; int value = 0; Label? label = default(Label?); for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], methodInfo)) { val = list[i + 2]; val2 = list[i + 5]; flag = true; } if (flag) { if (CodeInstructionExtensions.Branches(list[i], ref label) && dictionary.TryGetValue(label.Value, out value)) { num = i; break; } continue; } foreach (Label label4 in list[i].labels) { dictionary[label4] = i; } } if (list[value - 3].opcode == OpCodes.Dup) { return list; } Label label2 = ilg.DefineLabel(); Label label3 = ilg.DefineLabel(); list[num + 1].labels.Add(label2); list.InsertRange(num + 1, (IEnumerable)(object)new CodeInstruction[11] { new CodeInstruction(OpCodes.Ldloc, (object)localBuilder), new CodeInstruction(OpCodes.Brfalse, (object)label2), val.Clone(), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(InventoryGui), "m_recipeRequirementList")), new CodeInstruction(OpCodes.Ldlen, (object)null), new CodeInstruction(OpCodes.Bgt, (object)label2), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), val2.Clone(), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Br, (object)label3) }); list.InsertRange(value - 2, (IEnumerable)(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Dup, (object)null) { labels = new List