Decompiled source of PerspexModpack v1.2.20
BepInEx/plugins/Building.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using SkillManager; using TMPro; using UnityEngine; [assembly: Guid("9BF5432D-9518-4D36-A6C2-A8C62D36B921")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("Building")] [assembly: AssemblyCompany("")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/Building")] [assembly: AssemblyTitle("Building")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyConfiguration("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<977eed0d-c853-44d0-91ff-4cb8fe69933a>Embedded] internal sealed class <977eed0d-c853-44d0-91ff-4cb8fe69933a>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<977eed0d-c853-44d0-91ff-4cb8fe69933a>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <d01731d2-401a-4d69-91d0-be2439379d5f>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <d01731d2-401a-4d69-91d0-be2439379d5f>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <d01731d2-401a-4d69-91d0-be2439379d5f>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [<977eed0d-c853-44d0-91ff-4cb8fe69933a>Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <938d2326-56ad-4947-9bb0-9ced4308b262>NullableContextAttribute : Attribute { public readonly byte Flag; public <938d2326-56ad-4947-9bb0-9ced4308b262>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace Building { [BepInIncompatibility("org.bepinex.plugins.valheim_plus")] [BepInPlugin("org.bepinex.plugins.building", "Building", "1.2.5")] [<d01731d2-401a-4d69-91d0-be2439379d5f>Nullable(0)] [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] public class Building : BaseUnityPlugin { [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] private enum Toggle { On = 1, Off = 0 } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ShowRangeAsPercent; } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static class ChangeStaminaUsage { private static float stamina; [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] private static void Prefix(Player __instance, [<d01731d2-401a-4d69-91d0-be2439379d5f>Nullable(2)] out ItemData __state) { __state = ((Humanoid)__instance).GetRightItem(); if (__state?.m_shared.m_name == "$item_hammer") { stamina = __state.m_shared.m_attack.m_attackStamina; Attack attack = __state.m_shared.m_attack; attack.m_attackStamina *= Mathf.Max(0f, 1f - ((Character)(object)__instance).GetSkillFactor("Building") * (float)staminaReductionPerLevel.Value); } } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(2)] private static void Finalizer(ItemData __state) { if (__state?.m_shared.m_name == "$item_hammer") { __state.m_shared.m_attack.m_attackStamina = stamina; } } } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] [HarmonyPatch(typeof(WearNTear), "OnPlaced")] public class AddZDO { public static bool forFree; [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] [UsedImplicitly] private static void Postfix(WearNTear __instance) { ((Component)__instance).GetComponent<ZNetView>().GetZDO().Set("BuildingSkill Level", ((Character)(object)Player.m_localPlayer).GetSkillFactor("Building")); __instance.m_health *= 1f + ((Component)__instance).GetComponent<ZNetView>().GetZDO().GetFloat("BuildingSkill Level", 0f) * (healthFactor.Value - 1f); if (freeBuildLevelRequirement.Value > 0) { forFree = Random.Range((float)freeBuildLevelRequirement.Value / 100f, 5.5f) <= ((Character)(object)Player.m_localPlayer).GetSkillFactor("Building"); } ((Component)__instance).GetComponent<ZNetView>().GetZDO().Set("BuildingSkill FreeBuild", forFree); if (((Humanoid)Player.m_localPlayer).GetRightItem() != null && !((Humanoid)Player.m_localPlayer).GetRightItem().m_shared.m_name.ToLower().Contains("blueprint")) { ((Character)(object)Player.m_localPlayer).RaiseSkill("Building"); } } } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] [HarmonyPatch(typeof(WearNTear), "Awake")] private class IncreaseHealth { [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] [UsedImplicitly] private static void Prefix(WearNTear __instance) { float health = __instance.m_health; float num = 1f; ZDO zDO = ((Component)__instance).GetComponent<ZNetView>().GetZDO(); __instance.m_health = health * (num + ((zDO != null) ? new float?(zDO.GetFloat("BuildingSkill Level", 0f)) : null) * (healthFactor.Value - 1f)).GetValueOrDefault(1f); } } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] [HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")] private class BuildHigher { [UsedImplicitly] [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] private static void Postfix(WearNTear __instance, ref float maxSupport, ref float minSupport, ref float horizontalLoss, ref float verticalLoss) { ZNetView nview = __instance.m_nview; float? obj; if (nview == null) { obj = null; } else { ZDO zDO = nview.GetZDO(); obj = ((zDO != null) ? new float?(zDO.GetFloat("BuildingSkill Level", 0f)) : null); } float num = obj ?? ((Character)(object)Player.m_localPlayer)?.GetSkillFactor("Building") ?? 0f; maxSupport *= 1f + num * (maximumSupportFactor.Value - 1f); horizontalLoss *= 1f - num * (1f - supportLossFactor.Value); verticalLoss *= 1f - num * (1f - supportLossFactor.Value); } } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] [HarmonyPatch(typeof(Player), "UpdatePlacement")] private class ResetFlag { private static void Finalizer() { AddZDO.forFree = false; } } [HarmonyPatch(typeof(Player), "ConsumeResources")] [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] private class BuildingIsFree { private class SkipConsumeResourcesException : Exception { } [HarmonyPriority(800)] private static void Prefix() { if (AddZDO.forFree) { throw new SkipConsumeResourcesException(); } } [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] [return: <d01731d2-401a-4d69-91d0-be2439379d5f>Nullable(2)] private static Exception Finalizer(Exception __exception) { if (!(__exception is SkipConsumeResourcesException)) { return __exception; } return null; } } [HarmonyPatch(typeof(Piece), "DropResources")] [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] private class RecoverResources { [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(1)] private static bool Prefix(Piece __instance) { return !((Component)__instance).GetComponent<ZNetView>().GetZDO().GetBool("BuildingSkill FreeBuild", false); } } [<d01731d2-401a-4d69-91d0-be2439379d5f>Nullable(0)] [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static class ReduceHammerDurabilityLoss { private static bool reduced; private static void Prefix(Player __instance) { reduced = false; if (durabilityUsageLevelRequirement.Value > 0 && (float)durabilityUsageLevelRequirement.Value <= ((Character)(object)__instance).GetSkillFactor("Building") * 100f) { ItemData rightItem = ((Humanoid)__instance).GetRightItem(); if (rightItem != null) { SharedData shared = rightItem.m_shared; shared.m_useDurabilityDrain *= 0.7f; reduced = true; } } } private static void Finalizer(Player __instance) { ItemData rightItem = ((Humanoid)__instance).GetRightItem(); if (rightItem != null && reduced) { SharedData shared = rightItem.m_shared; shared.m_useDurabilityDrain /= 0.7f; } } } private const string ModName = "Building"; private const string ModVersion = "1.2.5"; private const string ModGUID = "org.bepinex.plugins.building"; private static readonly ConfigSync configSync = new ConfigSync("org.bepinex.plugins.building") { DisplayName = "Building", CurrentVersion = "1.2.5", MinimumRequiredVersion = "1.2.5" }; private static ConfigEntry<Toggle> serverConfigLocked = null; private static ConfigEntry<float> maximumSupportFactor = null; private static ConfigEntry<float> supportLossFactor = null; private static ConfigEntry<float> healthFactor = null; private static ConfigEntry<int> freeBuildLevelRequirement = null; private static ConfigEntry<int> durabilityUsageLevelRequirement = null; private static ConfigEntry<float> experienceGainedFactor = null; private static ConfigEntry<int> experienceLoss = null; private static ConfigEntry<int> staminaReductionPerLevel = null; private static Skill building = null; private ConfigEntry<T> config<[<d01731d2-401a-4d69-91d0-be2439379d5f>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description); configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting; return val; } private ConfigEntry<T> config<[<d01731d2-401a-4d69-91d0-be2439379d5f>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } public void Awake() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Expected O, but got Unknown //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) building = new Skill("Building", "building-icon.png"); building.Description.English("Increases the health of pieces built by you and you can build higher."); building.Name.German("Bauen"); building.Description.German("Erhöht die Lebenspunkte von Bauten, die von dir errichtet wurden und du kannst höher bauen."); building.Configurable = false; serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked); maximumSupportFactor = config("2 - Building", "Maximum Support Factor", 1.5f, new ConfigDescription("Maximum support factor for building pieces at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); supportLossFactor = config("2 - Building", "Support Loss Factor", 0.75f, new ConfigDescription("Support loss factor for vertical and horizontal building at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>())); healthFactor = config("2 - Building", "Health Factor", 3f, new ConfigDescription("Health factor for building pieces at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); freeBuildLevelRequirement = config("2 - Building", "Free Build Level Requirement", 50, new ConfigDescription("Minimum required skill level to be able to receive free building pieces. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1] { new ConfigurationManagerAttributes { ShowRangeAsPercent = false } })); durabilityUsageLevelRequirement = config("2 - Building", "Durability Increase Level Requirement", 30, new ConfigDescription("Minimum required skill level to reduce the durability usage of hammers by 30%. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1] { new ConfigurationManagerAttributes { ShowRangeAsPercent = false } })); staminaReductionPerLevel = config("2 - Building", "Stamina Reduction per Level", 1, new ConfigDescription("Reduces the stamina usage while building. Percentage stamina reduction per level. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); experienceGainedFactor = config("3 - Other", "Skill Experience Gain Factor", 1f, new ConfigDescription("Factor for experience gained for the building skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>())); experienceGainedFactor.SettingChanged += [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] (object _, EventArgs _) => { building.SkillGainFactor = experienceGainedFactor.Value; }; building.SkillGainFactor = experienceGainedFactor.Value; experienceLoss = config("3 - Other", "Skill Experience Loss", 0, new ConfigDescription("How much experience to lose in the building skill on death.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); experienceLoss.SettingChanged += [<938d2326-56ad-4947-9bb0-9ced4308b262>NullableContext(0)] (object _, EventArgs _) => { building.SkillLoss = experienceLoss.Value; }; building.SkillLoss = experienceLoss.Value; Assembly executingAssembly = Assembly.GetExecutingAssembly(); new Harmony("org.bepinex.plugins.building").PatchAll(executingAssembly); } } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<e52d898c-2dea-414b-a39e-63ce1f453974>Embedded] internal sealed class <e52d898c-2dea-414b-a39e-63ce1f453974>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<e52d898c-2dea-414b-a39e-63ce1f453974>Embedded] internal sealed class <1725a767-56f4-45e7-970f-3089dc995b62>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <1725a767-56f4-45e7-970f-3089dc995b62>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <1725a767-56f4-45e7-970f-3089dc995b62>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [<e52d898c-2dea-414b-a39e-63ce1f453974>Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContextAttribute : Attribute { public readonly byte Flag; public <4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContextAttribute(byte P_0) { Flag = P_0; } } [<e52d898c-2dea-414b-a39e-63ce1f453974>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [CompilerGenerated] internal sealed class <10b0b599-e852-4dce-b713-4e0984a2c333>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <10b0b599-e852-4dce-b713-4e0984a2c333>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SkillManager { [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(1)] [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(0)] [PublicAPI] internal class Skill { [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(0)] public static class LocalizationCache { private static readonly Dictionary<string, Localization> localizations = new Dictionary<string, Localization>(); internal static void LocalizationPostfix(Localization __instance, string language) { string key = localizations.FirstOrDefault([<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] (KeyValuePair<string, Localization> l) => l.Value == __instance).Key; if (key != null) { localizations.Remove(key); } if (!localizations.ContainsKey(language)) { localizations.Add(language, __instance); } } public static Localization ForLanguage([<1725a767-56f4-45e7-970f-3089dc995b62>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; } } [PublicAPI] [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(0)] public class LocalizeKey { private static readonly List<LocalizeKey> keys = new List<LocalizeKey>(); public readonly string Key; public readonly Dictionary<string, string> Localizations = new Dictionary<string, string>(); 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)); } } } } [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] private class ConfigurationManagerAttributes { [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] [UsedImplicitly] public string Category; } [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] [HarmonyPatch(typeof(Skills), "IsSkillValid")] private static class Patch_Skills_IsSkillValid { private static void Postfix(SkillType type, ref bool __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!__result && skills.ContainsKey(type)) { __result = true; } } } private static readonly Dictionary<SkillType, Skill> skills; internal static readonly Dictionary<string, Skill> skillByName; private readonly string skillName; private readonly string internalSkillName; private readonly SkillDef skillDef; public readonly LocalizeKey Name; public readonly LocalizeKey Description; private float skillEffectFactor = 1f; private int skillLoss = 5; public bool Configurable; private static bool InitializedTerminal; [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] private static Localization _english; [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] private static BaseUnityPlugin _plugin; private static bool hasConfigSync; [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] private static object _configSync; public float SkillGainFactor { get { return skillDef.m_increseStep; } set { skillDef.m_increseStep = value; this.SkillGainFactorChanged?.Invoke(value); } } public float SkillEffectFactor { get { return skillEffectFactor; } set { skillEffectFactor = value; this.SkillEffectFactorChanged?.Invoke(value); } } public int SkillLoss { get { return skillLoss; } set { skillLoss = value; this.SkillLossChanged?.Invoke(value); } } private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English")); private static BaseUnityPlugin plugin { get { //IL_0041: 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_004c: Expected O, but got Unknown object obj = _plugin; if (obj == null) { BaseUnityPlugin val = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)Assembly.GetExecutingAssembly().DefinedTypes.First([<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); _plugin = val; obj = (object)val; } return (BaseUnityPlugin)obj; } } [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] private static object configSync { [<4cd033a6-260d-4d69-97cc-f94c181d531a>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 + " SkillManager"); type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString()); type.GetProperty("IsLocked").SetValue(_configSync, true); } else { hasConfigSync = false; } } return _configSync; } } [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] [method: <4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(2)] [field: <1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] public event Action<float> SkillGainFactorChanged; [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] [method: <4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(2)] [field: <1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] public event Action<float> SkillEffectFactorChanged; [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] [method: <4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(2)] [field: <1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] public event Action<float> SkillLossChanged; public Skill(string englishName, string icon) : this(englishName, loadSprite(icon, 64, 64)) { } public Skill(string englishName, Sprite icon) { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_006b: 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_0077: 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_0082: Expected O, but got Unknown SkillType val = fromName(englishName); string text = new Regex("[^a-zA-Z]").Replace(englishName, "_"); skills[val] = this; skillByName[englishName] = this; skillDef = new SkillDef { m_description = "$skilldesc_" + text, m_icon = icon, m_increseStep = 1f, m_skill = val }; internalSkillName = text; skillName = englishName; Name = new LocalizeKey("skill_" + ((object)(SkillType)(ref val)).ToString()).English(englishName); Description = new LocalizeKey("skilldesc_" + text); } public static SkillType fromName(string englishName) { return (SkillType)Math.Abs(StringExtensionMethods.GetStableHashCode(englishName)); } static Skill() { //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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0066: 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) //IL_00a1: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown //IL_01ab: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown //IL_023c: Expected O, but got Unknown skills = new Dictionary<SkillType, Skill>(); skillByName = new Dictionary<string, Skill>(); InitializedTerminal = false; hasConfigSync = true; Harmony val = new Harmony("org.bepinex.helpers.skillmanager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_FejdStartup", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "GetSkillDef", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_GetSkillDef", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "CheatRaiseSkill", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_CheatRaiseskill", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "CheatResetSkill", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_CheatResetSkill", (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(Terminal), "InitTerminal", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Terminal_InitTerminal_Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Terminal_InitTerminal", (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(Skills), "OnDeath", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_OnDeath_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_OnDeath_Finalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null); } private static void Patch_FejdStartup() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown foreach (Skill skill in skills.Values) { if (skill.Configurable) { string key = skill.Name.Key; string group = new Regex("['[\"\\]]").Replace(english.Localize(key), "").Trim(); string category = Localization.instance.Localize(key).Trim(); ConfigEntry<float> skillGain = config(group, "Skill gain factor", skill.SkillGainFactor, new ConfigDescription("The rate at which you gain experience for the skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), new object[1] { new ConfigurationManagerAttributes { Category = category } })); skill.SkillGainFactor = skillGain.Value; skillGain.SettingChanged += [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] (object _, EventArgs _) => { skill.SkillGainFactor = skillGain.Value; }; ConfigEntry<float> skillEffect = config(group, "Skill effect factor", skill.SkillEffectFactor, new ConfigDescription("The power of the skill, based on the default power.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), new object[1] { new ConfigurationManagerAttributes { Category = category } })); skill.SkillEffectFactor = skillEffect.Value; skillEffect.SettingChanged += [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] (object _, EventArgs _) => { skill.SkillEffectFactor = skillEffect.Value; }; ConfigEntry<int> skillLoss = config(group, "Skill loss", skill.skillLoss, new ConfigDescription("How much experience to lose on death.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1] { new ConfigurationManagerAttributes { Category = category } })); skill.skillLoss = skillLoss.Value; skillLoss.SettingChanged += [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] (object _, EventArgs _) => { skill.skillLoss = skillLoss.Value; }; } } } private static void Patch_Skills_GetSkillDef([<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] ref SkillDef __result, List<SkillDef> ___m_skills, SkillType type) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (__result == null) { SkillDef val = GetSkillDef(type); if (val != null) { ___m_skills.Add(val); __result = val; } } } private static bool Patch_Skills_CheatRaiseskill(Skills __instance, string name, float value, Player ___m_player) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) foreach (SkillType key in skills.Keys) { SkillType current = key; Skill skill = skills[current]; if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase)) { Skill skill2 = __instance.GetSkill(current); skill2.m_level += value; skill2.m_level = Mathf.Clamp(skill2.m_level, 0f, 100f); ((Character)___m_player).Message((MessageType)1, "Skill increased " + Localization.instance.Localize("$skill_" + ((object)(SkillType)(ref current)).ToString()) + ": " + (int)skill2.m_level, 0, skill2.m_info.m_icon); Console.instance.Print("Skill " + skill.internalSkillName + " = " + skill2.m_level); return false; } } return true; } private static bool Patch_Skills_CheatResetSkill(Skills __instance, string name) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) foreach (SkillType key in skills.Keys) { Skill skill = skills[key]; if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase)) { __instance.ResetSkill(key); Console.instance.Print("Skill " + skill.internalSkillName + " reset"); return false; } } return true; } private static void Patch_Skills_OnDeath_Prefix(Skills __instance, [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(new byte[] { 2, 1 })] ref Dictionary<SkillType, Skill> __state) { //IL_002b: 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_0091: Unknown result type (might be due to invalid IL or missing references) if (__state == null) { __state = new Dictionary<SkillType, Skill>(); } foreach (KeyValuePair<SkillType, Skill> skill in skills) { if (__instance.m_skillData.TryGetValue(skill.Key, out var value)) { __state[skill.Key] = value; if (skill.Value.skillLoss > 0) { Skill obj = value; obj.m_level -= value.m_level * (float)skill.Value.SkillLoss / 100f; value.m_accumulator = 0f; } __instance.m_skillData.Remove(skill.Key); } } } private static void Patch_Skills_OnDeath_Finalizer(Skills __instance, [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(new byte[] { 2, 1 })] ref Dictionary<SkillType, Skill> __state) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (__state == null) { return; } foreach (KeyValuePair<SkillType, Skill> item in __state) { __instance.m_skillData[item.Key] = item.Value; } __state = null; } private static void Patch_Terminal_InitTerminal_Prefix() { InitializedTerminal = Terminal.m_terminalInitialized; } private static void Patch_Terminal_InitTerminal() { if (!InitializedTerminal) { AddSkill(Terminal.commands["raiseskill"]); AddSkill(Terminal.commands["resetskill"]); } static void AddSkill(ConsoleCommand command) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown ConsoleOptionsFetcher fetcher = command.m_tabOptionsFetcher; command.m_tabOptionsFetcher = (ConsoleOptionsFetcher)([<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] () => { List<string> list = fetcher.Invoke(); list.AddRange(skills.Values.Select([<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(0)] (Skill skill) => skill.internalSkillName)); return list; }); } } [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(2)] private static SkillDef GetSkillDef(SkillType skillType) { //IL_0005: 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) if (!skills.ContainsKey(skillType)) { return null; } return skills[skillType].skillDef; } private static byte[] ReadEmbeddedFileBytes(string name) { using MemoryStream memoryStream = new MemoryStream(); Assembly.GetExecutingAssembly().GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name + "." + name).CopyTo(memoryStream); return memoryStream.ToArray(); } private static Texture2D loadTexture(string name) { //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_001d: Expected O, but got Unknown //IL_001f: Expected O, but got Unknown Texture2D val = new Texture2D(0, 0); ImageConversion.LoadImage(val, ReadEmbeddedFileBytes("icons." + name)); return val; } private static Sprite loadSprite(string name, int width, int height) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) return Sprite.Create(loadTexture(name), new Rect(0f, 0f, (float)width, (float)height), Vector2.zero); } private static ConfigEntry<T> config<[<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(2)] T>(string group, string name, T value, ConfigDescription description) { ConfigEntry<T> val = plugin.Config.Bind<T>(group, name, value, description); configSync?.GetType().GetMethod("AddConfigEntry").MakeGenericMethod(typeof(T)) .Invoke(configSync, new object[1] { val }); return val; } private static ConfigEntry<T> config<[<1725a767-56f4-45e7-970f-3089dc995b62>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<object>())); } } [<4cd033a6-260d-4d69-97cc-f94c181d531a>NullableContext(1)] [<1725a767-56f4-45e7-970f-3089dc995b62>Nullable(0)] [PublicAPI] internal static class SkillExtensions { public static float GetSkillFactor(this Character character, string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return character.GetSkillFactor(Skill.fromName(name)) * Skill.skillByName[name].SkillEffectFactor; } public static float GetSkillFactor(this Skills skills, string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return skills.GetSkillFactor(Skill.fromName(name)) * Skill.skillByName[name].SkillEffectFactor; } public static void RaiseSkill(this Character character, string name, float value = 1f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) character.RaiseSkill(Skill.fromName(name), value); } public static void RaiseSkill(this Skills skill, string name, float value = 1f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) skill.RaiseSkill(Skill.fromName(name), value); } public static void LowerSkill(this Character character, string name, float factor = 1f) { character.GetSkills().LowerSkill(name, factor); } public static void LowerSkill(this Skills skills, string name, float factor) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (factor > 0f && skills.m_skillData.TryGetValue(Skill.fromName(name), out var value)) { Skill obj = value; obj.m_level -= value.m_level * factor; value.m_accumulator = 0f; } } } } namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<ConfigSync> configSyncs; private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>(); private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>(); private static bool isServer; private static bool lockExempt; private OwnConfigEntryBase? lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>(); private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; public event Action<bool>? SourceOfTruthChanged; private event Action? lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet<ConfigSync>(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry) { ConfigEntry<T> configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv) { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value)) { value = new SortedDictionary<int, byte[]>(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteArray()); if (value.Count < num2) { return false; } configValueCache.Remove(text2); package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray()); b = package.ReadByte(); } ProcessingServerUpdate = true; if ((b & 4u) != 0) { byte[] buffer = package.ReadByteArray(); MemoryStream stream = new MemoryStream(buffer); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress)) { deflateStream.CopyTo(memoryStream); } package = new ZPackage(memoryStream.ToArray()); b = package.ReadByte(); } if ((b & 1) == 0) { resetConfigsFromServer(); } ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package); ConfigFile val2 = null; bool saveOnConfigSet = false; foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues) { if (!isServer && configValue.Key.LocalBaseValue == null) { configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue; } if (val2 == null) { val2 = configValue.Key.BaseConfig.ConfigFile; saveOnConfigSet = val2.SaveOnConfigSet; val2.SaveOnConfigSet = false; } configValue.Key.BaseConfig.BoxedValue = configValue.Value; } if (val2 != null) { val2.SaveOnConfigSet = saveOnConfigSet; val2.Save(); } foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues) { if (!isServer) { CustomSyncedValueBase key2 = customValue.Key; if (key2.LocalBaseValue == null) { key2.LocalBaseValue = customValue.Key.BoxedValue; } } customValue.Key.BoxedValue = customValue.Value; } Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name)); if (!isServer) { serverLockedSettingChanged(); } return true; } finally { ProcessingServerUpdate = false; } } private ParsedConfigs ReadConfigsFromPackage(ZPackage package) { ParsedConfigs parsedConfigs = new ParsedConfigs(); Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c); Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string text = package.ReadString(); string text2 = package.ReadString(); string text3 = package.ReadString(); Type type = Type.GetType(text3); if (text3 == "" || type != null) { object obj; try { obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type)); } catch (InvalidDeserializationTypeException ex) { Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected)); continue; } OwnConfigEntryBase value2; if (text == "Internal") { CustomSyncedValueBase value; if (text2 == "serverversion") { if (obj?.ToString() != CurrentVersion) { Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown"))); } } else if (text2 == "lockexempt") { if (obj is bool flag) { lockExempt = flag; } } else if (dictionary2.TryGetValue(text2, out value)) { if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3) { parsedConfigs.customValues[value] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName)); } } else if (dictionary.TryGetValue(text + "_" + text2, out value2)) { Type type2 = configType(value2.BaseConfig); if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3) { parsedConfigs.configValues[value2] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName)); } else { Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match.")); } continue; } Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs")); return new ParsedConfigs(); } return parsedConfigs; } private static bool isWritableConfig(OwnConfigEntryBase config) { OwnConfigEntryBase config2 = config; ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2)); if (configSync == null) { return true; } return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt)); } private void serverLockedSettingChanged() { foreach (OwnConfigEntryBase allConfig in allConfigs) { configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig); } } private void resetConfigsFromServer() { ConfigFile val = null; bool saveOnConfigSet = false; foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null)) { if (val == null) { val = item.BaseConfig.ConfigFile; saveOnConfigSet = val.SaveOnConfigSet; val.SaveOnConfigSet = false; } item.BaseConfig.BoxedValue = item.LocalBaseValue; item.LocalBaseValue = null; } if (val != null) { val.SaveOnConfigSet = saveOnConfigSet; } foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null)) { item2.BoxedValue = item2.LocalBaseValue; item2.LocalBaseValue = null; } lockedConfigChanged -= serverLockedSettingChanged; serverLockedSettingChanged(); } private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package) { ZNetPeer peer2 = peer; ZRoutedRpc rpc = ZRoutedRpc.instance; if (rpc == null) { yield break; } byte[] data = package.GetArray(); if (data != null && data.LongLength > 250000) { int fragments = (int)(1 + (data.LongLength - 1) / 250000); long packageIdentifier = ++packageCounter; int fragment = 0; while (fragment < fragments) { foreach (bool item in waitForQueue()) { yield return item; } if (peer2.m_socket.IsConnected()) { ZPackage fragmentedPackage = new ZPackage(); fragmentedPackage.Write((byte)2); fragmentedPackage.Write(packageIdentifier); fragmentedPackage.Write(fragment); fragmentedPackage.Write(fragments); fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray()); SendPackage(fragmentedPackage); if (fragment != fragments - 1) { yield return true; } int num = fragment + 1; fragment = num; continue; } break; } yield break; } foreach (bool item2 in waitForQueue()) { yield return item2; } SendPackage(package); void SendPackage(ZPackage pkg) { string text = Name + " ConfigSync"; if (isServer) { peer2.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg }); } } IEnumerable<bool> waitForQueue() { float timeout = Time.time + 30f; while (peer2.m_socket.GetSendQueueSize() > 20000) { if (Time.time > timeout) { Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout"); peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 }); ZNet.instance.Disconnect(peer2); break; } yield return false; } } } private IEnumerator sendZPackage(long target, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return Enumerable.Empty<object>().GetEnumerator(); } List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance); if (target != ZRoutedRpc.Everybody) { list = list.Where((ZNetPeer p) => p.m_uid == target).ToList(); } return sendZPackage(list, package); } private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package) { ZPackage package2 = package; if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] rawData = package2.GetArray(); if (rawData != null && rawData.LongLength > 10000) { ZPackage compressedPackage = new ZPackage(); compressedPackage.Write((byte)4); MemoryStream output = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal)) { deflateStream.Write(rawData, 0, rawData.Length); } compressedPackage.Write(output.ToArray()); package2 = compressedPackage; } List<IEnumerator<bool>> writers = (from peer in peers where peer.IsReady() select peer into p select distributeConfigToPeers(p, package2)).ToList(); writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); while (writers.Count > 0) { yield return null; writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); } } private void Broadcast(long target, params ConfigEntryBase[] configs) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(configs); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private void Broadcast(long target, params CustomSyncedValueBase[] customValues) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(null, customValues); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private static OwnConfigEntryBase? configData(ConfigEntryBase config) { return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault(); } public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config) { return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault(); } private static T configAttribute<T>(ConfigEntryBase config) { return config.Description.Tags.OfType<T>().First(); } private static Type configType(ConfigEntryBase config) { return configType(config.SettingType); } private static Type configType(Type type) { return type.IsEnum ? Enum.GetUnderlyingType(type) : type; } private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>(); List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>(); ZPackage val = new ZPackage(); val.Write((byte)(partial ? 1 : 0)); val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0)); foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>()) { AddEntryToPackage(val, item); } foreach (CustomSyncedValueBase item2 in list2) { AddEntryToPackage(val, new PackageEntry { section = "Internal", key = item2.Identifier, type = item2.Type, value = item2.BoxedValue }); } foreach (ConfigEntryBase item3 in list) { AddEntryToPackage(val, new PackageEntry { section = item3.Definition.Section, key = item3.Definition.Key, type = configType(item3), value = item3.BoxedValue }); } return val; } private static void AddEntryToPackage(ZPackage package, PackageEntry entry) { package.Write(entry.section); package.Write(entry.key); package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type)); AddValueToZPackage(package, entry.value); } private static string GetZPackageTypeString(Type type) { return type.AssemblyQualifiedName; } private static void AddValueToZPackage(ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { AddValueToZPackage(package, item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetZPackageTypeString(fieldInfo.FieldType)); AddValueToZPackage(package, fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetZPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetZPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = ReadValueWithTypeFromZPackage(package, type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List<string>) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List<object> source = new List<object>(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.First(); } } [PublicAPI] [HarmonyPatch] internal class VersionCheck { private static readonly HashSet<VersionCheck> versionChecks; private static readonly Dictionary<string, string> notProcessedNames; public string Name; private string? displayName; private string? currentVersion; private string? minimumRequiredVersion; public bool ModRequired = true; private string? ReceivedCurrentVersion; private string? ReceivedMinimumRequiredVersion; private readonly List<ZRpc> ValidatedClients = new List<ZRpc>(); private ConfigSync? ConfigSync; public string DisplayName { get { return displayName ?? Name; } set { displayName = value; } } public string CurrentVersion { get { return currentVersion ?? "0.0.0"; } set { currentVersion = value; } } public string MinimumRequiredVersion { get { return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0"); } set { minimumRequiredVersion = value; } } private static void PatchServerSync() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null)); if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0) { return; } Harmony val = new Harmony("org.bepinex.helpers.ServerSync"); foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) }) where t.IsClass select t) { val.PatchAll(item); } } static VersionCheck() { versionChecks = new HashSet<VersionCheck>(); notProcessedNames = new Dictionary<string, string>(); typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1] { new Action(PatchServerSync) }); } public VersionCheck(string name) { Name = name; ModRequired = true; versionChecks.Add(this); } public VersionCheck(ConfigSync configSync) { ConfigSync = configSync; Name = ConfigSync.Name; versionChecks.Add(this); } public void Initialize() { ReceivedCurrentVersion = null; ReceivedMinimumRequiredVersion = null; if (ConfigSync != null) { Name = ConfigSync.Name; DisplayName = ConfigSync.DisplayName; CurrentVersion = ConfigSync.CurrentVersion; MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion; ModRequired = ConfigSync.ModRequired; } } private bool IsVersionOk() { if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null) { return !ModRequired; } bool flag = new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion); bool flag2 = new Version(ReceivedCurrentVersion) >= new Version(MinimumRequiredVersion); return flag && flag2; } private string ErrorClient() { if (ReceivedMinimumRequiredVersion == null) { return DisplayName + " is not installed on the server."; } return (new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion)) ? (DisplayName + " may not be higher than version " + ReceivedCurrentVersion + ". You have version " + CurrentVersion + ".") : (DisplayName + " needs to be at least version " + ReceivedMinimumRequiredVersion + ". You have version " + CurrentVersion + "."); } private string ErrorServer(ZRpc rpc) { return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion; } private string Error(ZRpc? rpc = null) { return (rpc == null) ? ErrorClient() : ErrorServer(rpc); } private static VersionCheck[] GetFailedClient() { return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray(); } private static VersionCheck[] GetFailedServer(ZRpc rpc) { ZRpc rpc2 = rpc; return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray(); } private static void Logout() { Game.instance.Logout(true, true); AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3); } private static void DisconnectClient(ZRpc rpc) { rpc.Invoke("Error", new object[1] { 3 }); } private static void CheckVersion(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, null); } private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); string text3 = pkg.ReadString(); bool flag = false; foreach (VersionCheck versionCheck in versionChecks) { if (!(text != versionCheck.Name)) { Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + ".")); versionCheck.ReceivedMinimumRequiredVersion = text2; versionCheck.ReceivedCurrentVersion = text3; if (ZNet.instance.IsServer() && versionCheck.IsVersionOk()) { versionCheck.ValidatedClients.Add(rpc); } flag = true; } } if (flag) { return; } pkg.SetPos(0); if (original != null) { original(rpc, pkg); if (pkg.GetPos() == 0) { notProcessedNames.Add(text, text3); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance) { VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient()); if (array.Length == 0) { return true; } VersionCheck[] array2 = array; foreach (VersionCheck versionCheck in array2) { Debug.LogWarning((object)versionCheck.Error(rpc)); } if (__instance.IsServer()) { DisconnectClient(rpc); } else { Logout(); } return false; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPrefix] private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance) { //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown notProcessedNames.Clear(); IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc); if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck"))) { object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")]; Action<ZRpc, ZPackage> action = (Action<ZRpc, ZPackage>)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, action); }); } else { peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)CheckVersion); } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.Initialize(); if (versionCheck.ModRequired || __instance.IsServer()) { Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + ".")); ZPackage val = new ZPackage(); val.Write(versionCheck.Name); val.Write(versionCheck.MinimumRequiredVersion); val.Write(versionCheck.CurrentVersion); peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val }); } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPrefix] private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance) { if (!__instance.IsServer()) { return; } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.ValidatedClients.Remove(peer.m_rpc); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] [HarmonyPostfix] private static void ShowConnectionError(FejdStartup __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0219: 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_0229: Unknown result type (might be due to invalid IL or missing references) if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3) { return; } bool flag = false; VersionCheck[] failedClient = GetFailedClient(); if (failedClient.Length != 0) { string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error())); TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + text; flag = true; } foreach (KeyValuePair<string, string> item in notProcessedNames.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> kv) => kv.Key)) { if (!__instance.m_connectionFailedError.text.Contains(item.Key)) { TMP_Text connectionFailedError2 = __instance.m_connectionFailedError; connectionFailedError2.text = connectionFailedError2.text + "\nServer expects you to have " + item.Key + " (Version: " + item.Value + ") installed."; flag = true; } } if (flag) { RectTransform component = ((Component)__instance.m_connectionFailedPanel.transform.Find("Image")).GetComponent<RectTransform>(); Vector2 sizeDelta = component.sizeDelta; sizeDelta.x = 675f; component.sizeDelta = sizeDelta; __instance.m_connectionFailedError.ForceMeshUpdate(false, false); float num = __instance.m_connectionFailedError.renderedHeight + 105f; RectTransform component2 = ((Component)((Component)component).transform.Find("ButtonOk")).GetComponent<RectTransform>(); component2.anchoredPosition = new Vector2(component2.anchoredPosition.x, component2.anchoredPosition.y - (num - component.sizeDelta.y) / 2f); sizeDelta = component.sizeDelta; sizeDelta.y = num; component.sizeDelta = sizeDelta; } } } }
BepInEx/plugins/BuildingDemolish.dll
Decompiled a day agousing System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BuildingDemolish")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BuildingDemolish")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("5d65d6a3-c00b-4cf1-a8e3-55e65f6deb37")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] public class AedenthornUtils { public static bool IgnoreKeyPresses(bool extra = false) { if (!extra) { if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog()) { Chat instance = Chat.instance; if (instance == null) { return false; } return instance.HasFocus(); } return true; } if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog()) { Chat instance2 = Chat.instance; if ((instance2 == null || !instance2.HasFocus()) && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible()) { TextViewer instance3 = TextViewer.instance; if (instance3 == null) { return false; } return instance3.IsVisible(); } } return true; } public static bool CheckKeyDown(string value) { try { return Input.GetKeyDown(value.ToLower()); } catch { return false; } } public static bool CheckKeyHeld(string value, bool req = true) { try { return Input.GetKey(value.ToLower()); } catch { return !req; } } } namespace BuildingDemolish; [BepInPlugin("aedenthorn.BuildingDemolish", "Building Demolish", "0.6.0")] public class BepInExPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Terminal), "InputText")] private static class InputText_Patch { private static bool Prefix(Terminal __instance) { if (!modEnabled.Value) { return true; } string text = ((TMP_InputField)__instance.m_input).text; if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " reset")) { ((BaseUnityPlugin)context).Config.Reload(); ((BaseUnityPlugin)context).Config.Save(); __instance.AddString(text); __instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " config reloaded"); return false; } if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " demolish")) { __instance.AddString(text); int num = DemolishPieces(destroyRadius.Value); __instance.AddString($"{((BaseUnityPlugin)context).Info.Metadata.Name} demolished {num} pieces"); return false; } if (text.ToLower().StartsWith(typeof(BepInExPlugin).Namespace.ToLower() + " demolish ")) { __instance.AddString(text); if (int.TryParse(text.Split(new char[1] { ' ' })[2], out var result)) { int num2 = DemolishPieces(result); __instance.AddString($"{((BaseUnityPlugin)context).Info.Metadata.Name} demolished {num2} pieces"); } else { __instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " syntax error"); } return false; } return true; } } private static readonly bool isDebug = true; private static BepInExPlugin context; public static ConfigEntry<bool> modEnabled; public static ConfigEntry<int> nexusID; public static ConfigEntry<bool> allowDestroyUncreated; public static ConfigEntry<bool> requireCraftingStation; public static ConfigEntry<float> destroyRadius; public static ConfigEntry<string> hotKey; public static int destroyMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle" }); public static void Dbgl(string str = "", bool pref = true) { if (isDebug) { Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str)); } } private void Awake() { context = this; modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod"); nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 516, "Nexus mod ID for updates"); destroyRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DestroyRadius", 20f, "Radius of destruction"); allowDestroyUncreated = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowDestroyUncreated", false, "Allow destroying buildings not created by any player"); requireCraftingStation = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireCraftingStation", true, "Require a nearby crafting station to destroy corresponding pieces (this is a vanilla requirement)"); hotKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HotKey", ";", "Hotkey to initiate destruction"); if (modEnabled.Value) { Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } } private void Update() { if (!AedenthornUtils.IgnoreKeyPresses(extra: true) && AedenthornUtils.CheckKeyDown(hotKey.Value)) { int num = DemolishPieces(destroyRadius.Value); Dbgl($"Demolished {num} pieces."); } } private static int DemolishPieces(float radius) { //IL_0018: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_0174: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return 0; } int num = 0; Collider[] array = Physics.OverlapSphere(((Component)localPlayer).transform.position, radius, destroyMask); for (int i = 0; i < array.Length; i++) { Piece componentInParent = ((Component)array[i]).GetComponentInParent<Piece>(); if (!Object.op_Implicit((Object)(object)componentInParent) || (!componentInParent.IsCreator() && (componentInParent.GetCreator() != 0L || !allowDestroyUncreated.Value)) || !componentInParent.m_canBeRemoved || Location.IsInsideNoBuildLocation(((Component)componentInParent).transform.position) || !PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, true, false) || (requireCraftingStation.Value && !Traverse.Create((object)localPlayer).Method("CheckCanRemovePiece", new object[1] { componentInParent }).GetValue<bool>())) { continue; } ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && componentInParent.CanBeRemoved()) { num++; WearNTear component2 = ((Component)componentInParent).GetComponent<WearNTear>(); if (Object.op_Implicit((Object)(object)component2)) { component2.Remove(false); continue; } component.ClaimOwnership(); componentInParent.DropResources((HitData)null); componentInParent.m_placeEffect.Create(((Component)componentInParent).transform.position, ((Component)componentInParent).transform.rotation, ((Component)componentInParent).gameObject.transform, 1f, -1); localPlayer.m_removeEffects.Create(((Component)componentInParent).transform.position, Quaternion.identity, (Transform)null, 1f, -1); ZNetScene.instance.Destroy(((Component)componentInParent).gameObject); } } return num; } }
BepInEx/plugins/GroupCoinSplit.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using Groups; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("GroupCoinSplit")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("GroupCoinSplit")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("632effe9-d4d8-49a4-9193-7a12b43e51ee")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace GroupCoinSplit { internal static class GcsFlags { public const string PlayerDropped = "gcs_player_dropped"; public const string MobLoot = "gcs_mob_loot"; } internal static class PrefabName { public static string Of(GameObject go) { if ((Object)(object)go == (Object)null) { return ""; } string text = ((Object)go).name ?? ""; if (!text.EndsWith("(Clone)", StringComparison.Ordinal)) { return text; } return text.Replace("(Clone)", "").Trim(); } } [HarmonyPatch] internal static class MarkPlayerDroppedCoinsPatch { private static MethodBase TargetMethod() { List<MethodInfo> list = (from m in typeof(ItemDrop).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "DropItem" where m.ReturnType == typeof(GameObject) || m.ReturnType == typeof(ItemDrop) select m).ToList(); if (list.Count > 0) { return list.FirstOrDefault((MethodInfo m) => m.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(ItemData))) ?? list[0]; } return AccessTools.Method(typeof(ItemDrop), "DropItem", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void Postfix(object __result) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = null; GameObject val2 = (GameObject)((__result is GameObject) ? __result : null); if (val2 != null) { val = val2; } else { ItemDrop val3 = (ItemDrop)((__result is ItemDrop) ? __result : null); if (val3 != null) { val = ((Component)val3).gameObject; } } if ((Object)(object)val == (Object)null || !string.Equals(PrefabName.Of(val), "Coins", StringComparison.OrdinalIgnoreCase)) { return; } ZNetView component = val.GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.Set("gcs_player_dropped", 1); GroupCoinSplitPlugin.Dbg($"Flagged Coins as PLAYER_DROPPED zdo={zDO.m_uid}"); } } } catch { } } } [HarmonyPatch(typeof(CharacterDrop))] internal static class CharacterDropScopePatch { private static int _depth; private static MethodBase[] _targets = Array.Empty<MethodBase>(); internal static bool InMobDropScope => _depth > 0; [HarmonyPrepare] private static bool Prepare() { try { _targets = (from m in typeof(CharacterDrop).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.ReturnType == typeof(void) select m).Where(delegate(MethodInfo m) { string name = m.Name; bool flag = name.IndexOf("Drop", StringComparison.OrdinalIgnoreCase) >= 0; bool flag2 = name.IndexOf("Item", StringComparison.OrdinalIgnoreCase) >= 0; bool flag3 = name.IndexOf("Loot", StringComparison.OrdinalIgnoreCase) >= 0; return flag && (flag2 || flag3); }).Cast<MethodBase>().ToArray(); if (_targets.Length == 0) { GroupCoinSplitPlugin.LogWarning("[GCS] CharacterDrop drop methods not found on this build. MOB_LOOT flagging will be limited (coins may be treated as NOT mob loot)."); return false; } GroupCoinSplitPlugin.LogInfo("[GCS] CharacterDrop scope targets: " + string.Join(" | ", _targets.Select((MethodBase t) => t.Name + "(" + string.Join(", ", from p in t.GetParameters() select p.ParameterType.Name) + ")"))); return true; } catch (Exception arg) { GroupCoinSplitPlugin.LogError($"[GCS] CharacterDropScopePatch.Prepare error: {arg}"); return false; } } private static IEnumerable<MethodBase> TargetMethods() { return _targets; } [HarmonyPrefix] private static void Prefix() { _depth++; } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception) { _depth = Math.Max(0, _depth - 1); return __exception; } } [HarmonyPatch(typeof(ItemDrop), "Awake")] internal static class MarkMobLootCoinsOnAwakePatch { [HarmonyPostfix] private static void Postfix(ItemDrop __instance) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || !CharacterDropScopePatch.InMobDropScope) { return; } GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null || !string.Equals(PrefabName.Of(gameObject), "Coins", StringComparison.OrdinalIgnoreCase)) { return; } ZNetView component = gameObject.GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.Set("gcs_mob_loot", 1); GroupCoinSplitPlugin.Dbg($"Marked Coins as MOB_LOOT zdo={zDO.m_uid}"); } } } catch { } } } [HarmonyPatch] internal static class HumanoidPickupClientPatch { [CompilerGenerated] private sealed class <DoSplitNextFrame>d__6 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Player looter; public int totalGained; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DoSplitNextFrame>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0123: 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_014a: 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_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; try { if (GroupCoinSplitPlugin.CfgMode == null || GroupCoinSplitPlugin.CfgMode.Value == DivisionMode.None) { return false; } if (!API.IsLoaded()) { GroupCoinSplitPlugin.Dbg("DoSplit: Groups API not loaded -> skip"); return false; } List<PlayerReference> list = API.GroupPlayers(); if (list == null || list.Count <= 1) { GroupCoinSplitPlugin.Dbg("DoSplit: no group or only one member -> skip"); return false; } Dictionary<long, Player> dictionary = (Player.GetAllPlayers() ?? new List<Player>()).Where((Player pl) => (Object)(object)pl != (Object)null).GroupBy(delegate(Player pl) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID4 = ((Character)pl).GetZDOID(); return ((ZDOID)(ref zDOID4)).UserID; }).ToDictionary((IGrouping<long, Player> g) => g.Key, (IGrouping<long, Player> g) => g.First()); ZDOID zDOID = ((Character)looter).GetZDOID(); long userID = ((ZDOID)(ref zDOID)).UserID; float value = GroupCoinSplitPlugin.CfgRange.Value; Vector3 position = ((Component)looter).transform.position; List<long> list2 = list.Select((PlayerReference r) => r.peerId).Distinct().ToList(); if (!list2.Contains(userID)) { list2.Add(userID); } List<Player> list3 = new List<Player>(); foreach (long item in list2) { if (dictionary.TryGetValue(item, out var value2) && !((Object)(object)value2 == (Object)null) && !(((Character)value2).GetHealth() <= 0f) && Vector3.Distance(((Component)value2).transform.position, position) <= value) { list3.Add(value2); } } if (!list3.Contains(looter)) { list3.Add(looter); } list3 = list3.Distinct().OrderBy(delegate(Player pl) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID3 = ((Character)pl).GetZDOID(); return ((ZDOID)(ref zDOID3)).UserID; }).ToList(); if (list3.Count <= 1) { GroupCoinSplitPlugin.Dbg("DoSplit: recipients<=1 after range -> skip"); return false; } DivisionMode value3 = GroupCoinSplitPlugin.CfgMode.Value; Dictionary<long, int> dictionary2 = ComputeShares(userID, list3.Select(delegate(Player r) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID2 = ((Character)r).GetZDOID(); return ((ZDOID)(ref zDOID2)).UserID; }).ToList(), value3, totalGained); int value4; int num = (dictionary2.TryGetValue(userID, out value4) ? value4 : totalGained); int num2 = totalGained - num; if (num2 <= 0) { GroupCoinSplitPlugin.Dbg($"DoSplit: nothing to give away (myShare={num}, total={totalGained})"); return false; } if (!RemoveCoins(looter, num2)) { GroupCoinSplitPlugin.LogWarning($"DoSplit: failed to remove {num2} Coins from looter inventory. Aborting distribution."); return false; } GroupCoinSplitPlugin.Dbg($"DoSplit: removed from looter={num2}. Will drop for others."); foreach (KeyValuePair<long, int> item2 in dictionary2.OrderBy((KeyValuePair<long, int> k) => k.Key)) { long key = item2.Key; int value5 = item2.Value; if (key != userID && value5 > 0 && dictionary.TryGetValue(key, out var value6) && !((Object)(object)value6 == (Object)null)) { Vector3 pos = ((Component)value6).transform.position + Random.insideUnitSphere * 0.5f; pos.y = ((Component)value6).transform.position.y + 0.2f; DropCoinsAt(pos, value5); GroupCoinSplitPlugin.Dbg($"DoSplit: dropped {value5} near uid={key}"); } } } catch (Exception arg) { GroupCoinSplitPlugin.LogError($"DoSplit error: {arg}"); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static int _coinsBefore; private static bool _armed; private static bool _eligibleObject; private static MethodBase TargetMethod() { return typeof(Humanoid).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo x) { if (x.Name != "Pickup") { return false; } ParameterInfo[] parameters = x.GetParameters(); return parameters.Length == 3 && parameters[0].ParameterType == typeof(GameObject) && parameters[1].ParameterType == typeof(bool) && parameters[2].ParameterType == typeof(bool); }) ?? AccessTools.Method(typeof(Humanoid), "Pickup", (Type[])null, (Type[])null); } [HarmonyPrefix] private static void Prefix(Humanoid __instance, GameObject go, bool autoequip, bool autoPickupDelay) { try { _armed = false; _eligibleObject = false; Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || (Object)(object)go == (Object)null || GroupCoinSplitPlugin.CfgMode == null || GroupCoinSplitPlugin.CfgMode.Value == DivisionMode.None || !string.Equals(PrefabName.Of(go), "Coins", StringComparison.OrdinalIgnoreCase)) { return; } ZNetView component = go.GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (zDO != null) { if (zDO.GetInt("gcs_player_dropped", 0) == 1) { GroupCoinSplitPlugin.Dbg("PickupCoins: IGNORE (player_dropped=1)"); return; } if (zDO.GetInt("gcs_mob_loot", 0) != 1) { GroupCoinSplitPlugin.Dbg("PickupCoins: IGNORE (not mob loot)"); return; } _coinsBefore = CountCoins(val); _armed = true; _eligibleObject = true; GroupCoinSplitPlugin.Dbg($"PickupCoins: armed coinsBefore={_coinsBefore}"); } } catch (Exception arg) { GroupCoinSplitPlugin.LogError($"Pickup Prefix error: {arg}"); } } [HarmonyPostfix] private static void Postfix(Humanoid __instance, GameObject go, bool autoequip, bool autoPickupDelay) { try { if (!_armed || !_eligibleObject) { return; } _armed = false; Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { int num = CountCoins(val); int num2 = num - _coinsBefore; if (num2 <= 0) { GroupCoinSplitPlugin.Dbg($"PickupCoins: gained<=0 (before={_coinsBefore}, after={num}) -> skip"); return; } GroupCoinSplitPlugin.Dbg($"PickupCoins: gained={num2} (before={_coinsBefore}, after={num})"); ((MonoBehaviour)val).StartCoroutine(DoSplitNextFrame(val, num2)); } } catch (Exception arg) { GroupCoinSplitPlugin.LogError($"Pickup Postfix error: {arg}"); } } [IteratorStateMachine(typeof(<DoSplitNextFrame>d__6))] private static IEnumerator DoSplitNextFrame(Player looter, int totalGained) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DoSplitNextFrame>d__6(0) { looter = looter, totalGained = totalGained }; } private static Dictionary<long, int> ComputeShares(long looterUid, List<long> recipientUids, DivisionMode mode, int total) { List<long> list = (from u in recipientUids.Where((long u) => u > 0).Distinct() orderby u select u).ToList(); Dictionary<long, int> dictionary = new Dictionary<long, int>(); if (list.Count == 0 || total <= 0) { return dictionary; } int count = list.Count; int num = total / count; int num2 = total % count; if (num <= 0) { dictionary[looterUid] = total; return dictionary; } for (int i = 0; i < list.Count; i++) { int num3 = num; switch (mode) { case DivisionMode.EvenRemainderToPicker: if (list[i] == looterUid) { num3 += num2; } break; case DivisionMode.RoundRobin: if (i < num2) { num3++; } break; } if (num3 > 0) { dictionary[list[i]] = num3; } } return dictionary; } private static int CountCoins(Player p) { try { Inventory inventory = ((Humanoid)p).GetInventory(); if (inventory == null) { return 0; } return inventory.CountItems("Coins", -1, true); } catch { return 0; } } private static bool RemoveCoins(Player p, int amount) { try { if (amount <= 0) { return true; } Inventory inventory = ((Humanoid)p).GetInventory(); if (inventory == null) { return false; } int num = inventory.CountItems("Coins", -1, true); inventory.RemoveItem("Coins", amount, -1, true); int num2 = inventory.CountItems("Coins", -1, true); return num - num2 >= amount; } catch { return false; } } private static void DropCoinsAt(Vector3 pos, int amount) { //IL_00ba: 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_010a: 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) try { if (amount <= 0 || (Object)(object)ObjectDB.instance == (Object)null) { return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins"); if ((Object)(object)itemPrefab == (Object)null) { return; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { return; } ItemData val = component.m_itemData.Clone(); val.m_stack = amount; MethodInfo methodInfo = typeof(ItemDrop).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo x) { if (x.Name != "DropItem") { return false; } ParameterInfo[] parameters = x.GetParameters(); return parameters.Length >= 4 && parameters[0].ParameterType == typeof(ItemData) && parameters[1].ParameterType == typeof(int) && parameters[2].ParameterType == typeof(Vector3) && parameters[3].ParameterType == typeof(Quaternion); }); object obj = null; obj = ((!(methodInfo != null)) ? AccessTools.Method(typeof(ItemDrop), "DropItem", (Type[])null, (Type[])null)?.Invoke(null, new object[4] { val, amount, pos, Quaternion.identity }) : methodInfo.Invoke(null, new object[4] { val, amount, pos, Quaternion.identity })); GameObject val2 = null; GameObject val3 = (GameObject)((obj is GameObject) ? obj : null); if (val3 != null) { val2 = val3; } else { ItemDrop val4 = (ItemDrop)((obj is ItemDrop) ? obj : null); if (val4 != null) { val2 = ((Component)val4).gameObject; } } if ((Object)(object)val2 == (Object)null) { return; } ZNetView component2 = val2.GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.IsValid()) { ZDO zDO = component2.GetZDO(); if (zDO != null) { zDO.Set("gcs_player_dropped", 1); } } } catch { } } } public enum DivisionMode { None, EvenRemainderToPicker, RoundRobin } [BepInPlugin("twentyonez.groupcoinsplit", "Group Coin Split (Client Only)", "2.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class GroupCoinSplitPlugin : BaseUnityPlugin { public const string ModGuid = "twentyonez.groupcoinsplit"; public const string ModName = "Group Coin Split (Client Only)"; public const string ModVersion = "2.0.0"; internal static GroupCoinSplitPlugin I; internal static ConfigEntry<bool> CfgEnabled; internal static ConfigEntry<DivisionMode> CfgMode; internal static ConfigEntry<float> CfgRange; internal static ConfigEntry<bool> CfgDebug; private Harmony _harmony; private void Awake() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown I = this; CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Se true, o client redistribui Coins (loot de mobs) dropando perto dos colegas do grupo."); CfgMode = ((BaseUnityPlugin)this).Config.Bind<DivisionMode>("General", "DivisionMode", DivisionMode.EvenRemainderToPicker, "None: sem divisão\nEvenRemainderToPicker: divide igualmente, resto fica com quem pegou\nRoundRobin: resto distribuído 1 a 1 (ordem estável por UID)"); CfgRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RangeMeters", 20f, "Raio (em metros) para considerar membros do grupo próximos."); CfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLog", false, "Se true, escreve logs de debug no client (e no server também, se o mod estiver instalado lá)."); _harmony = new Harmony("twentyonez.groupcoinsplit"); _harmony.PatchAll(); LogInfo($"Loaded. Enabled={CfgEnabled.Value} Mode={CfgMode.Value} Range={CfgRange.Value} Debug={CfgDebug.Value}"); } internal static bool Enabled() { if (CfgEnabled != null && CfgEnabled.Value) { return CfgMode.Value != DivisionMode.None; } return false; } internal static void LogInfo(string msg) { if ((Object)(object)I != (Object)null) { ((BaseUnityPlugin)I).Logger.LogInfo((object)msg); } else { Debug.Log((object)("[GCS] " + msg)); } } internal static void LogWarning(string msg) { if ((Object)(object)I != (Object)null) { ((BaseUnityPlugin)I).Logger.LogWarning((object)msg); } else { Debug.LogWarning((object)("[GCS] " + msg)); } } internal static void LogError(string msg) { if ((Object)(object)I != (Object)null) { ((BaseUnityPlugin)I).Logger.LogError((object)msg); } else { Debug.LogError((object)("[GCS] " + msg)); } } internal static void Dbg(string msg) { if (CfgDebug != null && CfgDebug.Value) { LogInfo("[DBG] " + msg); } } } }
BepInEx/plugins/Hearthstone.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Valheim HearthStone Mod")] [assembly: AssemblyDescription("Adds a ConsumableItem that will bring you home")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HearthStone")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("97d58a4d-8886-44f9-ba81-73da0e389949")] [assembly: AssemblyFileVersion("1.0.5.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.5.0")] [module: UnverifiableCode] namespace Hearthstone; [BepInPlugin("twentyoneZ.mods.Hearthstone_Revolution", "Hearthstone Revolution by TwentyOneZ", "1.0.5")] [BepInDependency("com.jotunn.jotunn", "2.9.0")] public class Hearthstone : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "OnDeath")] private static class Patch_Player_OnDeath { private static void Prefix(Player __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { SetLastDeathPosition(((Component)__instance).transform.position); } } catch (Exception ex) { Debug("Failed to capture last death position: " + ex.Message); } } } [HarmonyPatch(typeof(TombStone), "Interact")] private static class Patch_TombStone_Interact_ClearLastDeath { private static void Postfix(TombStone __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { try { bool flag = __1; if (__result && !flag) { Player val = (Player)(object)((__0 is Player) ? __0 : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { ClearLastDeathPosition(); Debug("Cleared last death position after tombstone interaction."); } } } catch (Exception ex) { Debug("TombStone.Interact postfix failed: " + ex.Message); } } } [HarmonyPatch(typeof(Humanoid), "UseItem")] private static class Patch_Humanoid_UseItem { private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: 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_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: 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_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || item == null) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null) { return true; } if ((Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } string text = item.m_shared?.m_name; if (string.IsNullOrEmpty(text)) { return true; } bool flag = text == "Hearthstone"; bool flag2 = text == "Marketstone"; bool flag3 = text == "Deathstone" || text == "LastDeathStone"; if (!flag && !flag2 && !flag3) { return true; } if (!((Humanoid)val).IsTeleportable() && !allowTeleportWithoutRestriction.Value) { ((Character)val).Message((MessageType)2, "You can't teleport carrying those items", 0, (Sprite)null); return false; } if (val.IsTargeted() && !allowTeleportWhileTargeted.Value) { ((Character)val).Message((MessageType)2, "You can't teleport while spotted by anyone", 0, (Sprite)null); return false; } if (((Character)val).IsEncumbered() && !allowTeleportWhileEncumbered.Value) { ((Character)val).Message((MessageType)2, "You can't teleport while encumbered", 0, (Sprite)null); return false; } if (((Character)val).InWater() && !allowTeleportWhileInWater.Value) { ((Character)val).Message((MessageType)2, "You can't teleport while in water", 0, (Sprite)null); return false; } if (needsToBeResting.Value && !((Character)val).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("Resting"))) { ((Character)val).Message((MessageType)2, "You have to be resting to teleport", 0, (Sprite)null); return false; } if (flag) { Vector3 hearthStonePosition = GetHearthStonePosition(); if (hearthStonePosition == Vector3.zero) { ((Character)val).Message((MessageType)2, "You need to set hearthstone spawn point", 0, (Sprite)null); return false; } ConsumeOne(val, inventory, item); ((Character)val).TeleportTo(hearthStonePosition, ((Component)val).transform.rotation, true); return false; } if (flag2) { LocationInstance val2 = default(LocationInstance); if (ZoneSystem.instance.FindClosestLocation("Vendor_BlackForest", Vector3.zero, ref val2)) { Vector3 val3 = val2.m_position + Vector3.up; ConsumeOne(val, inventory, item); ((Character)val).TeleportTo(val3, ((Component)val).transform.rotation, true); return false; } Vector3 val4 = default(Vector3); if (ZoneSystem.instance.GetLocationIcon("Vendor_BlackForest", ref val4)) { Vector3 val3 = val4 + Vector3.up; ConsumeOne(val, inventory, item); ((Character)val).TeleportTo(val3, ((Component)val).transform.rotation, true); return false; } ((Character)val).Message((MessageType)2, "I have to find the market first.", 0, (Sprite)null); return false; } if (flag3) { Vector3 lastDeathPosition = GetLastDeathPosition(); if (lastDeathPosition == Vector3.zero) { ((Character)val).Message((MessageType)2, "No death position recorded yet.", 0, (Sprite)null); return false; } ConsumeOne(val, inventory, item); ((Character)val).TeleportTo(lastDeathPosition + Vector3.up, ((Component)val).transform.rotation, true); return false; } return true; } catch (Exception arg) { Debug.Log((object)$"[Hearthstone] UseItem failed: {arg}"); return true; } } private static void ConsumeOne(Player p, Inventory inventory, ItemData item) { Inventory val = inventory ?? ((Humanoid)p).GetInventory(); if (val != null && item.m_stack > 0) { val.RemoveItem(item, 1); } } } public const string sharedName = "Hearthstone"; public const string sharedLastDeathName = "LastDeathStone"; public const string PluginGUID = "twentyoneZ.mods.Hearthstone_Revolution"; private Harmony harmony = new Harmony("twentyoneZ.mods.Hearthstone_Revolution"); public static ConfigEntry<string> item1; public static ConfigEntry<string> item2; public static ConfigEntry<string> item3; public static ConfigEntry<int> itemCost1; public static ConfigEntry<int> itemCost2; public static ConfigEntry<int> itemCost3; public static ConfigEntry<bool> allowTeleportWithoutRestriction; public static ConfigEntry<bool> allowTeleportWhileTargeted; public static ConfigEntry<bool> allowTeleportWhileEncumbered; public static ConfigEntry<bool> allowTeleportWhileInWater; public static ConfigEntry<bool> needsToBeResting; public static ConfigEntry<bool> writeDebugOutput; private static CustomItem m_hearthStoneItem; private static CustomItem m_lastDeathStoneItem; private static string m_lastPositionString; private static string m_lastDeathPositionString; private const string ZdoKey_HearthPos = "HS_HearthPos"; public static bool IsOwner { get; set; } private static string PositionFile { get { string text = Path.Combine(Paths.ConfigPath, "Hearthstone"); Directory.CreateDirectory(text); long num = 0L; try { if ((Object)(object)Player.m_localPlayer != (Object)null) { num = Player.m_localPlayer.GetPlayerID(); } } catch { num = 0L; } if (num == 0L) { return Path.Combine(text, "HSPosition.txt"); } return Path.Combine(text, $"HSPosition_{num}.txt"); } } private static string LastDeathPositionFile { get { string text = Path.Combine(Paths.ConfigPath, "Hearthstone"); Directory.CreateDirectory(text); long num = 0L; try { if ((Object)(object)Player.m_localPlayer != (Object)null) { num = Player.m_localPlayer.GetPlayerID(); } } catch { num = 0L; } if (num == 0L) { return Path.Combine(text, "HSLastDeath.txt"); } return Path.Combine(text, $"HSLastDeath_{num}.txt"); } } private static ZNetView GetLocalPlayerNView() { try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { return component; } FieldInfo fieldInfo = AccessTools.Field(typeof(Character), "m_nview"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(localPlayer); component = (ZNetView)((value is ZNetView) ? value : null); if ((Object)(object)component != (Object)null) { return component; } } return null; } catch { return null; } } public static void Debug(string value) { if (writeDebugOutput.Value) { Logger.LogMessage((object)value); } } private void Awake() { //IL_0046: 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_0053: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0081: 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_008e: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00fc: 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_0109: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //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_0183: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Expected O, but got Unknown //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Expected O, but got Unknown //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Expected O, but got Unknown //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.SettingChanged += delegate { GenerateRecipe(); }; item1 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RecipeItem1", "Stone", new ConfigDescription("Recipe item 1 - leave blank for none", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); itemCost1 = ((BaseUnityPlugin)this).Config.Bind<int>("General", "itemCost1", 2, new ConfigDescription("Amount of item 1 required to craft the Hearthstone", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); item2 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RecipeItem2", "Coins", new ConfigDescription("Recipe item 2 - leave blank for none", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); itemCost2 = ((BaseUnityPlugin)this).Config.Bind<int>("General", "itemCost2", 10, new ConfigDescription("Amount of item 2 required to craft the Hearthstone", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); item3 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RecipeItem3", "Carrot", new ConfigDescription("Recipe item 3 - leave blank for none", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); itemCost3 = ((BaseUnityPlugin)this).Config.Bind<int>("General", "itemCost3", 5, new ConfigDescription("Amount of item 3 required to craft the Hearthstone", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); writeDebugOutput = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "writeDebugOutput", true, new ConfigDescription("Write debug output?", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); allowTeleportWithoutRestriction = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWithoutRestriction", false, new ConfigDescription("Allow teleport without restriction", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); allowTeleportWhileTargeted = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWhileTargeted", true, new ConfigDescription("Allow teleport while targeted", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); allowTeleportWhileEncumbered = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWhileEncumbered", false, new ConfigDescription("Allow teleport while encumbered", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); allowTeleportWhileInWater = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWhileInWater", false, new ConfigDescription("Allow teleport while in water", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); needsToBeResting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "needsToBeResting", true, new ConfigDescription("Require to be resting to teleport (make a safe campfire and sit around)", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); harmony.PatchAll(); PrefabManager.OnVanillaPrefabsAvailable += AddOrUpdateHearthStoneItem; ItemManager.OnItemsRegistered += ItemManager_OnItemsRegistered; SynchronizationManager.OnConfigurationSynchronized += SynchronizationManager_OnConfigurationSynchronized; SynchronizationManager.OnAdminStatusChanged += SynchronizationManager_OnAdminStatusChanged; } private void SynchronizationManager_OnAdminStatusChanged() { Debug(SynchronizationManager.Instance.PlayerIsAdmin ? "No Admin anymore" : "You are admin"); } private void SynchronizationManager_OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e) { Debug(e.InitialSynchronization ? "Recieved Initial Config" : "Updated Config"); GenerateRecipe(); } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject(); if (!((Object)(object)hoverObject == (Object)null)) { Interactable componentInParent = hoverObject.GetComponentInParent<Interactable>(); if (IsOwner && componentInParent is Bed && Input.GetKeyDown((KeyCode)112)) { SetHearthStonePosition(); ((Character)Player.m_localPlayer).Message((MessageType)2, "You have updated your HearthStone location", 0, (Sprite)null); } } } private void ItemManager_OnItemsRegistered() { ItemManager.OnItemsRegistered -= ItemManager_OnItemsRegistered; GenerateRecipe(); } private void GenerateRecipe() { List<Requirement> rqs; if ((m_hearthStoneItem != null || m_lastDeathStoneItem != null) && ObjectDB.instance.m_items.Any()) { EnsureRecipe(m_hearthStoneItem, "Recipe_Hearthstone"); EnsureRecipe(m_lastDeathStoneItem, "Recipe_LastDeathStone"); rqs = new List<Requirement>(); AddRq(item1, itemCost1); AddRq(item2, itemCost2); AddRq(item3, itemCost3); CustomItem hearthStoneItem = m_hearthStoneItem; object obj; if (hearthStoneItem == null) { obj = null; } else { CustomRecipe recipe = hearthStoneItem.Recipe; obj = ((recipe != null) ? recipe.Recipe : null); } if ((Object)obj != (Object)null) { m_hearthStoneItem.Recipe.Recipe.m_resources = rqs.ToArray(); } CustomItem lastDeathStoneItem = m_lastDeathStoneItem; object obj2; if (lastDeathStoneItem == null) { obj2 = null; } else { CustomRecipe recipe2 = lastDeathStoneItem.Recipe; obj2 = ((recipe2 != null) ? recipe2.Recipe : null); } if ((Object)obj2 != (Object)null) { m_lastDeathStoneItem.Recipe.Recipe.m_resources = rqs.ToArray(); } } void AddRq(ConfigEntry<string> item, ConfigEntry<int> amount) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown try { if (item != null && !string.IsNullOrEmpty(item.Value) && amount.Value > 0) { ItemDrop component = ObjectDB.instance.GetItemPrefab(item.Value).GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { rqs.Add(new Requirement { m_amount = amount.Value, m_resItem = component }); } } } catch (Exception ex) { Debug(ex.Message); } } static void EnsureRecipe(CustomItem ci, string recipeName) { //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_0033: Expected O, but got Unknown if (ci != null && ci.Recipe == null) { Recipe obj3 = ScriptableObject.CreateInstance<Recipe>(); ((Object)obj3).name = recipeName; obj3.m_item = ci.ItemDrop; CustomRecipe recipe3 = new CustomRecipe(obj3, true, true) { FixRequirementReferences = true }; ci.Recipe = recipe3; } } } private void AddOrUpdateHearthStoneItem() { //IL_0079: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_01c6: 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_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown if (m_hearthStoneItem != null) { return; } AssetBundle val = AssetUtils.LoadAssetBundleFromResources("hs", typeof(Hearthstone).Assembly); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)"Bundle could not be loaded!"); return; } GameObject val2 = val.LoadAsset<GameObject>("Assets/_Custom/Hearthstone.prefab"); if ((Object)(object)val2 == (Object)null) { Logger.LogWarning((object)"Prefab could not be loaded!"); return; } ItemDrop component = val2.GetComponent<ItemDrop>(); SharedData shared = component.m_itemData.m_shared; if (shared == null) { Logger.LogWarning((object)"Shared ItemData could not be loaded!"); return; } ItemConfig val3 = new ItemConfig { Name = shared.m_name, Requirements = BuildRequirementConfigs(), Icons = shared.m_icons, Description = shared.m_description }; m_hearthStoneItem = new CustomItem(val, "Assets/_Custom/Hearthstone.prefab", true, val3); ItemManager.Instance.AddItem(m_hearthStoneItem); try { if (m_lastDeathStoneItem == null) { GameObject val4 = PrefabManager.Instance.CreateClonedPrefab("LastDeathStone", val2); ItemDrop component2 = val4.GetComponent<ItemDrop>(); if ((Object)(object)component2 == (Object)null) { Debug("LastDeathStone clone has no ItemDrop component!"); return; } if (component2.m_itemData == null) { component2.m_itemData = new ItemData(); } if (component2.m_itemData.m_shared == null) { component2.m_itemData.m_shared = new SharedData(); } component2.m_itemData.m_dropPrefab = val4; if (component2.m_itemData.m_shared.m_icons == null || component2.m_itemData.m_shared.m_icons.Length == 0) { component2.m_itemData.m_shared.m_icons = component.m_itemData.m_shared.m_icons; } component2.m_itemData.m_shared.m_name = "Pedra do Último Óbito"; component2.m_itemData.m_shared.m_description = "Retorna você ao local onde morreu pela última vez."; ItemConfig val5 = new ItemConfig { Name = component2.m_itemData.m_shared.m_name, Requirements = BuildRequirementConfigs(), Icons = component2.m_itemData.m_shared.m_icons, Description = component2.m_itemData.m_shared.m_description }; m_lastDeathStoneItem = new CustomItem(val4, true, val5); ItemManager.Instance.AddItem(m_lastDeathStoneItem); } } catch (Exception arg) { Debug($"Failed to create Last Death Stone: {arg}"); } GenerateRecipe(); } private static RequirementConfig[] BuildRequirementConfigs() { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00e1: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); if (itemCost1.Value > 0 && !string.IsNullOrEmpty(item1.Value)) { list.Add(new RequirementConfig { Amount = itemCost1.Value, Item = item1.Value }); } if (itemCost2.Value > 0 && !string.IsNullOrEmpty(item2.Value)) { list.Add(new RequirementConfig { Amount = itemCost2.Value, Item = item2.Value }); } if (itemCost3.Value > 0 && !string.IsNullOrEmpty(item3.Value)) { list.Add(new RequirementConfig { Amount = itemCost3.Value, Item = item3.Value }); } return list.ToArray(); } private static ZDO GetLocalPlayerZDO() { try { ZNetView localPlayerNView = GetLocalPlayerNView(); if ((Object)(object)localPlayerNView == (Object)null) { return null; } return localPlayerNView.GetZDO(); } catch { return null; } } private static bool TryGetHearthPosFromZDO(out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0034: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; try { ZDO localPlayerZDO = GetLocalPlayerZDO(); if (localPlayerZDO == null) { return false; } pos = localPlayerZDO.GetVec3("HS_HearthPos", Vector3.zero); return pos != Vector3.zero; } catch { return false; } } private static void SetHearthPosToZDO(Vector3 pos) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) try { ZDO localPlayerZDO = GetLocalPlayerZDO(); if (localPlayerZDO != null) { localPlayerZDO.Set("HS_HearthPos", pos); } } catch { } } public static Vector3 GetHearthStonePosition() { //IL_0066: 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_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_0009: 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_006f: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) if (TryGetHearthPosFromZDO(out var pos)) { return pos; } CultureInfo provider = new CultureInfo("en-US"); Vector3 zero = Vector3.zero; string hearthStonePositionString = GetHearthStonePositionString(); if (string.IsNullOrEmpty(hearthStonePositionString)) { return zero; } string[] array = hearthStonePositionString.Split(new char[1] { '|' }); try { zero = new Vector3(float.Parse(array[0], provider), float.Parse(array[1], provider), float.Parse(array[2], provider)); } catch { zero = Vector3.zero; } if (zero != Vector3.zero) { SetHearthPosToZDO(zero); } return zero; } private static string GetHearthStonePositionString() { if (string.IsNullOrEmpty(m_lastPositionString) && File.Exists(PositionFile)) { m_lastPositionString = File.ReadAllText(PositionFile); } return m_lastPositionString; } private static void SetHearthStonePosition() { //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) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Vector3 position = ((Component)localPlayer).transform.position; SetHearthPosToZDO(position); CultureInfo cultureInfo = new CultureInfo("en-US"); string text = position.x.ToString(cultureInfo) + "|" + position.y.ToString(cultureInfo) + "|" + position.z.ToString(cultureInfo); File.WriteAllText(PositionFile, text); m_lastPositionString = text; } } public static Vector3 GetLastDeathPosition() { //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_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_001f: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) CultureInfo provider = new CultureInfo("en-US"); Vector3 zero = Vector3.zero; string lastDeathPositionString = GetLastDeathPositionString(); if (string.IsNullOrEmpty(lastDeathPositionString)) { return zero; } string[] array = lastDeathPositionString.Split(new char[1] { '|' }); try { return new Vector3(float.Parse(array[0], provider), float.Parse(array[1], provider), float.Parse(array[2], provider)); } catch { return Vector3.zero; } } private static string GetLastDeathPositionString() { if (string.IsNullOrEmpty(m_lastDeathPositionString) && File.Exists(LastDeathPositionFile)) { m_lastDeathPositionString = File.ReadAllText(LastDeathPositionFile); } return m_lastDeathPositionString; } public static void SetLastDeathPosition(Vector3 position) { CultureInfo cultureInfo = new CultureInfo("en-US"); string text = position.x.ToString(cultureInfo) + "|" + position.y.ToString(cultureInfo) + "|" + position.z.ToString(cultureInfo); File.WriteAllText(LastDeathPositionFile, text); m_lastDeathPositionString = text; } private static bool IsResting(Player p) { try { string[] array = new string[4] { "InRestingArea", "InComfortZone", "InShelter", "InSafeZone" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(((object)p).GetType(), text, (Type[])null, (Type[])null); if (methodInfo != null && methodInfo.ReturnType == typeof(bool) && methodInfo.GetParameters().Length == 0) { return (bool)methodInfo.Invoke(p, null); } } return true; } catch { return true; } } public static void ClearLastDeathPosition() { try { m_lastDeathPositionString = null; if (File.Exists(LastDeathPositionFile)) { File.Delete(LastDeathPositionFile); } } catch (Exception ex) { Debug("Failed to clear last death position: " + ex.Message); } } } internal class Patches { [HarmonyPatch(typeof(Bed), "GetHoverText")] private static class Bed_GetHoverText_Patch { private static void Postfix(Bed __instance, ref string __result, ZNetView ___m_nview) { if ((Object)(object)Player.m_localPlayer == (Object)null) { Hearthstone.IsOwner = false; } else if (___m_nview.GetZDO().GetLong("owner", 0L) == Player.m_localPlayer.GetPlayerID() || __instance.IsCurrent()) { Hearthstone.IsOwner = true; __result += "\n[<color=yellow><b>P</b></color>] Set hearthstone"; } else { Hearthstone.IsOwner = false; } } } [HarmonyPatch(typeof(ItemStand), "CanAttach")] public static class AttachPatch { [HarmonyPostfix] private static void Postfix(ItemStand __instance, ItemData item, ref bool __result) { if (!__result) { string text = item?.m_shared?.m_name; if (!string.IsNullOrEmpty(text)) { __result = text == "Hearthstone"; } } } } }
BepInEx/plugins/Professions.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Professions; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Professions")] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/Professions")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Professions")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("6A561CBA-69AC-46B3-9095-15E99C3121EC")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public class ProfessionPanel : MonoBehaviour { [Header("Stuff To replace")] public Image SelectionBKG; public Image ContentBkg; public Text header; public Image linebreak; public Text description; [Header("Skill Element")] public GameObject SkillElementGO; public Skill_Element skill_element; public RectTransform panelToInstantiateIn; public GameObject InstantiateSkill(Sprite icon, string title, string desc, string buttontext) { GameObject obj = Object.Instantiate<GameObject>(SkillElementGO, (Transform)(object)panelToInstantiateIn); Skill_Element component = obj.GetComponent<Skill_Element>(); component.m_icon.sprite = icon; component.m_desc.text = desc; component.m_Title.text = title; component.buttontxt.text = buttontext; return obj; } public void Awake() { Transform parent = ((Component)this).transform.parent.parent.parent; Image component = ((Component)parent.Find("Menu/MenuRoot/Menu/ornament")).gameObject.GetComponent<Image>(); Image component2 = ((Component)parent.Find("Inventory_screen/root/Player/Bkg")).gameObject.GetComponent<Image>(); TMP_FontAsset font = ((TMP_Text)((Component)parent.Find("Inventory_screen/root/Player/Armor/ac_text")).gameObject.GetComponent<TextMeshProUGUI>()).font; description.font = font.sourceFontFile; header.font = font.sourceFontFile; header.text = "Select Profession"; linebreak.sprite = component.sprite; ContentBkg.sprite = component2.sprite; ((Graphic)ContentBkg).material = ((Graphic)component2).material; ((Graphic)SelectionBKG).material = ((Graphic)component2).material; SelectionBKG.sprite = component2.sprite; } } public class Skill_Element : MonoBehaviour { [Header("Stuff To replace")] public Image m_icon; public Text m_Title; public Text m_desc; public Button Select; public Text buttontxt; public Image[] configOptions; private Text[] _configTexts; public global::Professions.Professions.Profession profession; public static Sprite blockUsage; public static Sprite blockExperience; public static GameObject tooltipPrefab; public void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_0118: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) Button component = ((Component)((Component)Menu.instance).transform.Find("MenuRoot/ExitConfirm/dialog/Button_yes")).GetComponent<Button>(); ((Selectable)Select).spriteState = ((Selectable)component).spriteState; ((Selectable)Select).transition = (Transition)2; ((Component)Select).GetComponent<Image>().sprite = ((Component)component).GetComponent<Image>().sprite; Image[] array = configOptions; for (int i = 0; i < array.Length; i++) { ((Component)array[i]).GetComponent<UITooltip>().m_tooltipPrefab = tooltipPrefab; } _configTexts = (Text[])(object)new Text[configOptions.Length]; for (int j = 0; j < configOptions.Length; j++) { Image val = configOptions[j]; ((Behaviour)val).enabled = false; GameObject val2 = new GameObject("ConfigText"); val2.transform.SetParent(((Component)val).transform, false); Text val3 = val2.AddComponent<Text>(); val3.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val3.alignment = (TextAnchor)4; ((Graphic)val3).raycastTarget = false; val3.text = ""; val3.resizeTextForBestFit = true; val3.resizeTextMinSize = 10; val3.resizeTextMaxSize = 30; RectTransform rectTransform = ((Graphic)val3).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; _configTexts[j] = val3; ((Component)val).GetComponent<UITooltip>().m_tooltipPrefab = tooltipPrefab; } } public void UpdateImageDisplay(global::Professions.Professions.ProfessionToggle toggle) { //IL_0079: 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_00ef: 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) int num = 0; for (int i = 0; i < configOptions.Length; i++) { ((Component)configOptions[i]).gameObject.SetActive(false); if (_configTexts != null && i < _configTexts.Length && (Object)(object)_configTexts[i] != (Object)null) { _configTexts[i].text = ""; } } if (!((Object)(object)Player.m_localPlayer == (Object)null)) { SkillType skillTypeFromProfession = global::Professions.Professions.GetSkillTypeFromProfession(profession); bool flag = Helper.getActiveProfessions().Contains(profession); float num2 = 0f; Dictionary<global::Professions.Professions.Profession, float> inactiveProfessions = Helper.getInactiveProfessions(); if (inactiveProfessions != null && inactiveProfessions.TryGetValue(profession, out var value) && value > 0f) { num2 = value; } float num3 = 0f; Skill value2 = null; bool flag2 = Player.m_localPlayer.m_skills?.m_skillData != null && Player.m_localPlayer.m_skills.m_skillData.TryGetValue(skillTypeFromProfession, out value2) && value2 != null; if (flag2) { num3 = value2.m_level; } float num4 = ((!flag && num2 > 0f) ? num2 : ((!flag) ? (flag2 ? num3 : 0f) : (flag2 ? num3 : Player.m_localPlayer.m_skills.GetSkill(skillTypeFromProfession).m_level))); int num5 = Mathf.FloorToInt(num4); switch (toggle) { case global::Professions.Professions.ProfessionToggle.BlockUsage: { UITooltip component2 = ((Component)configOptions[num]).GetComponent<UITooltip>(); component2.m_text = "If you do not pick this profession, you will not be able to perform these actions."; component2.m_topic = "Usage blocked"; ((Component)configOptions[num]).gameObject.SetActive(true); _configTexts[num].text = num5.ToString(); num++; break; } case global::Professions.Professions.ProfessionToggle.BlockExperience: { UITooltip component = ((Component)configOptions[num]).GetComponent<UITooltip>(); component.m_text = "If you do not pick this profession, you will still be able to perform these actions, but will not gain experience."; component.m_topic = "Experience blocked"; ((Component)configOptions[num]).gameObject.SetActive(true); _configTexts[num].text = num5.ToString(); num++; break; } } } } public void Toggle(bool selected, bool maxProfessionsReached) { if (selected) { ((Selectable)Select).interactable = global::Professions.Professions.allowUnselect.Value == global::Professions.Professions.Toggle.On; buttontxt.text = ((global::Professions.Professions.allowUnselect.Value == global::Professions.Professions.Toggle.On) ? "Unlearn" : "Selected"); } else { ((Selectable)Select).interactable = true; buttontxt.text = (maxProfessionsReached ? "Unlock" : "Select"); } } } namespace Professions { public static class Blockers { [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] private class BlockBlacksmithing { private static bool CheckBlacksmithingItem(SharedData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected I4, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 ItemType itemType = item.m_itemType; bool flag; switch (itemType - 4) { case 0: case 1: case 2: case 3: case 7: case 8: case 10: case 13: flag = true; break; default: flag = false; break; } if (!flag) { if ((int)item.m_itemType == 3) { return !item.m_attack.m_consumeItem; } return false; } return true; } [HarmonyPriority(0)] private static void Postfix(InventoryGui __instance) { if (__instance.InCraftTab() || __instance.InUpradeTab()) { ItemDrop val = ((RecipeDataPair)(ref __instance.m_selectedRecipe)).Recipe?.m_item; if (val != null && CheckBlacksmithingItem(val.m_itemData.m_shared) && !isAllowed(Professions.Profession.Blacksmithing)) { ((Selectable)__instance.m_craftButton).interactable = false; ((TMP_Text)((Component)__instance.m_craftButton).GetComponentInChildren<TextMeshProUGUI>()).text = "You cannot perform this action, because you are not a blacksmith."; } } } } [HarmonyPatch] public static class BlockBlacksmithingSmelter { private static IEnumerable<MethodInfo> TargetMethods() { return new MethodInfo[2] { AccessTools.DeclaredMethod(typeof(Smelter), "OnAddOre", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Smelter), "OnAddFuel", (Type[])null, (Type[])null) }; } private static bool Prefix(Smelter __instance, ref bool __result) { switch (((Component)__instance).GetComponent<Piece>()?.m_name) { case "$piece_smelter": case "$piece_blastfurnace": if (isAllowed(Professions.Profession.Blacksmithing)) { return true; } __result = false; ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a blacksmith.", 0, (Sprite)null); return false; case "$piece_windmill": if (isAllowed(Professions.Profession.Farming)) { return true; } __result = false; ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a farmer.", 0, (Sprite)null); return false; default: return true; } } } [HarmonyPatch(typeof(PieceTable), "SetCategory")] private class BlockBuilding { private static bool Prefix(int index) { if ((index != 2 && index != 3) || isAllowed(Professions.Profession.Building)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a builder.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(PieceTable), "PrevCategory")] private class BlockBuildingHotkeyPrev { private static void Postfix(PieceTable __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 PieceCategory selectedCategory = __instance.m_selectedCategory; bool flag = selectedCategory - 2 <= 1; if (flag && !isAllowed(Professions.Profession.Building)) { __instance.PrevCategory(); } } } [HarmonyPatch(typeof(PieceTable), "NextCategory")] private class BlockBuildingHotkeyNext { private static void Postfix(PieceTable __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 PieceCategory selectedCategory = __instance.m_selectedCategory; bool flag = selectedCategory - 2 <= 1; if (flag && !isAllowed(Professions.Profession.Building)) { __instance.NextCategory(); } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] private class BlockCookingCrafting { [HarmonyPriority(0)] private static void Postfix(InventoryGui __instance) { ItemDrop val = ((RecipeDataPair)(ref __instance.m_selectedRecipe)).Recipe?.m_item; if (val == null) { return; } if (!(val.m_itemData.m_shared.m_food > 0f) || !(val.m_itemData.m_shared.m_foodStamina > 0f)) { ItemDrop appendToolTip = val.m_itemData.m_shared.m_appendToolTip; if (!Object.op_Implicit((Object)(object)((appendToolTip != null) ? ((Component)appendToolTip).GetComponent<Feast>() : null))) { return; } } if (!isAllowed(Professions.Profession.Cooking)) { ((Selectable)__instance.m_craftButton).interactable = false; ((TMP_Text)((Component)__instance.m_craftButton).GetComponentInChildren<TextMeshProUGUI>()).text = "You cannot perform this action, because you are not a cook."; } } } [HarmonyPatch(typeof(CookingStation), "Interact")] private class BlockCookingStation { private static bool Prefix() { if (isAllowed(Professions.Profession.Cooking)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a cook.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(ItemData), "IsEquipable")] private class BlockFarmingCultivator { private static void Postfix(ItemData __instance, ref bool __result) { if (__instance.m_shared.m_name == "$item_cultivator" && !isAllowed(Professions.Profession.Farming)) { __result = false; } } } [HarmonyPatch(typeof(Pickable), "Interact")] private class BlockFarmingPickingPlants { private static bool Prefix(Pickable __instance) { if (!__instance.m_nview.GetZDO().GetBool("Farming Custom Grown", false) || isAllowed(Professions.Profession.Farming)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a farmer.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(Plant), "Grow")] private class SaveCustomGrownPlantState { [CompilerGenerated] private sealed class <Transpiler>d__1 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private MethodInfo <transferInfo>5__2; private MethodInfo <instantiator>5__3; private IEnumerator<CodeInstruction> <>7__wrap3; private CodeInstruction <instruction>5__5; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__1(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <transferInfo>5__2 = null; <instantiator>5__3 = null; <>7__wrap3 = null; <instruction>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <transferInfo>5__2 = AccessTools.DeclaredMethod(typeof(SaveCustomGrownPlantState), "TransferInfo", (Type[])null, (Type[])null); <instantiator>5__3 = typeof(Object).GetMethods().First((MethodInfo m) => m.Name == "Instantiate" && m.IsGenericMethodDefinition && (from p in m.GetParameters().Skip(1) select p.ParameterType).SequenceEqual(new Type[2] { typeof(Vector3), typeof(Quaternion) })).MakeGenericMethod(typeof(GameObject)); <>7__wrap3 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; if (<instruction>5__5.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(<instruction>5__5, (MemberInfo)<instantiator>5__3)) { <>2__current = new CodeInstruction(OpCodes.Call, (object)<transferInfo>5__2); <>1__state = 2; return true; } goto IL_0138; case 2: { <>1__state = -3; goto IL_0138; } IL_0138: <instruction>5__5 = null; break; } if (<>7__wrap3.MoveNext()) { <instruction>5__5 = <>7__wrap3.Current; <>2__current = <instruction>5__5; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap3 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap3 != null) { <>7__wrap3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__1 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__1(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private static GameObject TransferInfo(GameObject pickable) { pickable.GetComponent<ZNetView>().GetZDO().Set("Farming Custom Grown", true); return pickable; } [IteratorStateMachine(typeof(<Transpiler>d__1))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__1(-2) { <>3__instructions = instructions }; } } [HarmonyPatch] public static class BlockLumberjacking { private static IEnumerable<MethodInfo> TargetMethods() { return new MethodInfo[3] { AccessTools.DeclaredMethod(typeof(TreeLog), "Damage", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(TreeBase), "Damage", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Destructible), "Damage", (Type[])null, (Type[])null) }; } private static void Prefix(object __instance, HitData hit) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if (isAllowed(Professions.Profession.Lumberjacking) || !((Object)(object)hit.GetAttacker() == (Object)(object)Player.m_localPlayer)) { return; } Destructible val = (Destructible)((__instance is Destructible) ? __instance : null); if (val == null || (int)val.m_destructibleType == 2) { if (!(__instance is TreeLog) && !(__instance is TreeBase)) { hit.m_damage.m_slash = 0f; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a lumberjack.", 0, (Sprite)null); hit.m_damage.m_chop = 0f; } } } [HarmonyPatch] public static class BlockMining { private static IEnumerable<MethodInfo> TargetMethods() { return new MethodInfo[3] { AccessTools.DeclaredMethod(typeof(MineRock), "Damage", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(MineRock5), "Damage", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Destructible), "Damage", (Type[])null, (Type[])null) }; } private static void Prefix(object __instance, HitData hit) { //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_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_0032: Invalid comparison between Unknown and I4 //IL_0034: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 if (isAllowed(Professions.Profession.Mining) || !((Object)(object)hit.GetAttacker() == (Object)(object)Player.m_localPlayer)) { return; } Destructible val = (Destructible)((__instance is Destructible) ? __instance : null); if (val != null) { DamageModifiers damages = val.m_damages; if ((int)damages.m_pickaxe <= 0 || (int)damages.m_chop != 0 || (int)val.m_destructibleType == 2) { return; } } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a miner.", 0, (Sprite)null); hit.m_damage.m_pickaxe = 0f; } } [HarmonyPatch(typeof(Character), "Damage")] private class BlockRanching { private static bool Prefix(Character __instance, HitData hit) { if (!__instance.IsTamed() || isAllowed(Professions.Profession.Ranching) || (Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a rancher.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(ShipControlls), "Interact")] private class BlockSailing { private static bool Prefix() { if (isAllowed(Professions.Profession.Sailing)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a sailor.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(CraftingStation), "Interact")] private class BlockAlchemyStation { private static bool Prefix(CraftingStation __instance) { if (!((Object)__instance).name.StartsWith("opalchemy", StringComparison.Ordinal) || isAllowed(Professions.Profession.Alchemy)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not an alchemist.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(Incinerator), "OnIncinerate")] private class BlockAlchemyIncinerator { private static bool Prefix(Incinerator __instance) { if (!((Object)__instance).name.StartsWith("opcauldron", StringComparison.Ordinal) || isAllowed(Professions.Profession.Alchemy)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not an alchemist.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(CraftingStation), "Interact")] private class BlockGemcuttersTable { private static bool Prefix(CraftingStation __instance) { if (!((Object)__instance).name.StartsWith("op_transmution_table", StringComparison.Ordinal) || isAllowed(Professions.Profession.Jewelcrafting)) { return true; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a jeweler.", 0, (Sprite)null); return false; } } [HarmonyPatch(typeof(Pickable), "Interact")] private class BlockForaging { private class SkipForagingException : Exception { } [HarmonyPriority(800)] private static void Prefix(Pickable __instance) { if (__instance.m_respawnTimeMinutes == 0f || ((Object)__instance.m_itemPrefab).name == "Wood" || isAllowed(Professions.Profession.Foraging)) { return; } ((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a forager.", 0, (Sprite)null); throw new SkipForagingException(); } private static Exception? Finalizer(Exception __exception) { if (!(__exception is SkipForagingException)) { return __exception; } return null; } } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(Vector3), typeof(float) })] private class BlockExploration { [HarmonyPriority(800)] private static bool Prefix() { return isAllowed(Professions.Profession.Exploration); } } private static bool isAllowed(Professions.Profession profession) { if (Professions.blockOtherProfessions[profession].Value == Professions.ProfessionToggle.BlockUsage) { return Helper.getActiveProfessions().Contains(profession); } return true; } } public static class Helper { private static byte[] ReadEmbeddedFileBytes(string name) { using MemoryStream memoryStream = new MemoryStream(); Assembly.GetExecutingAssembly().GetManifestResourceStream("Professions." + name)?.CopyTo(memoryStream); return memoryStream.ToArray(); } private static Texture2D loadTexture(string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown return new Texture2D(1, 1); } public static Sprite loadSprite(string name, int width, int height) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) return Sprite.Create(loadTexture(name), new Rect(0f, 0f, (float)width, (float)height), Vector2.zero); } public static string getHumanFriendlyTime(int seconds) { TimeSpan timeSpan = TimeSpan.FromSeconds(seconds); if (timeSpan.TotalSeconds < 60.0) { return "less than 1 minute"; } string text = ""; if (timeSpan.TotalDays >= 1.0) { text = text + $"{(int)timeSpan.TotalDays} day" + ((timeSpan.TotalDays >= 2.0) ? "s" : ""); } if (timeSpan.Hours >= 1) { if (timeSpan.TotalDays >= 1.0) { text += " and "; } text = text + $"{timeSpan.Hours} hour" + ((timeSpan.Hours >= 2) ? "s" : ""); } if (timeSpan.Minutes >= 1) { if (timeSpan.TotalDays >= 1.0 || timeSpan.Hours >= 1) { text += " and "; } text = text + $"{timeSpan.Minutes} minute" + ((timeSpan.Minutes >= 2) ? "s" : ""); } return text; } public static HashSet<Professions.Profession> getActiveProfessions() { HashSet<Professions.Profession> hashSet = new HashSet<Professions.Profession>(); if (Player.m_localPlayer.m_customData.TryGetValue("Professions Active", out var value)) { string[] array = value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { if (Enum.TryParse<Professions.Profession>(array[i], out var result)) { hashSet.Add(result); } } } return hashSet; } public static Dictionary<Professions.Profession, float> getInactiveProfessions() { Dictionary<Professions.Profession, float> dictionary = ((Professions.Profession[])Enum.GetValues(typeof(Professions.Profession))).ToDictionary((Professions.Profession p) => p, (Professions.Profession _) => 0f); foreach (Professions.Profession activeProfession in getActiveProfessions()) { dictionary.Remove(activeProfession); } if (Player.m_localPlayer.m_customData.TryGetValue("Professions Inactive", out var value)) { string[] array = value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }); if (Enum.TryParse<Professions.Profession>(array2[0], out var result)) { float result2 = 0f; if (array2.Length > 1) { float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out result2); } dictionary[result] = result2; } } } return dictionary; } public static void storeActiveProfessions(HashSet<Professions.Profession> professions) { if (professions.Count == 0) { Player.m_localPlayer.m_customData.Remove("Professions Active"); return; } Player.m_localPlayer.m_customData["Professions Active"] = string.Join(",", professions.Select((Professions.Profession p) => p.ToString())); } public static void storeInactiveProfessions(Dictionary<Professions.Profession, float> professions) { if (professions.Count((KeyValuePair<Professions.Profession, float> kv) => kv.Value > 0f) == 0) { Player.m_localPlayer.m_customData.Remove("Professions Inactive"); return; } Player.m_localPlayer.m_customData["Professions Inactive"] = string.Join(",", from kv in professions where kv.Value > 0f select $"{kv.Key}:{kv.Value.ToString(CultureInfo.InvariantCulture)}"); } } [BepInPlugin("org.bepinex.plugins.professions", "Professions", "1.4.5")] [BepInIncompatibility("org.bepinex.plugins.valheim_plus")] public class Professions : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } public enum ProfessionToggle { Ignored, BlockExperience, BlockUsage } public enum Profession { Blacksmithing, Building, Cooking, Farming, Lumberjacking, Mining, Ranching, Sailing, Alchemy, Jewelcrafting, Foraging, Exploration } private class ConfigurationManagerAttributes { [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public int? Order; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class AddRPCs { [CompilerGenerated] private static class <>O { public static Method <0>__onServerTimeRequest; public static Action<ZRpc, long> <1>__onServerTimeReceived; } private static void Postfix(ZNet __instance, ZNetPeer peer) { //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_002e: Expected O, but got Unknown if (__instance.IsServer()) { ZRpc rpc = peer.m_rpc; object obj = <>O.<0>__onServerTimeRequest; if (obj == null) { Method val = onServerTimeRequest; <>O.<0>__onServerTimeRequest = val; obj = (object)val; } rpc.Register("Professions GetServerTime", (Method)obj); } else { peer.m_rpc.Register<long>("Professions GetServerTime", (Action<ZRpc, long>)onServerTimeReceived); } } } [HarmonyPatch(typeof(Menu), "Update")] private class PreventMainMenu { public static bool AllowMainMenu = true; private static bool Prefix() { if (!professionPanelInstance.activeSelf) { return AllowMainMenu; } return false; } } [HarmonyPatch(typeof(Hud), "Awake")] public static class InstantiateSelectPanel { private static void Prefix(Hud __instance) { Transform transform = __instance.m_rootObject.transform; professionPanelInstance = Object.Instantiate<GameObject>(professionPanel, transform, false); professionPanelInstance.SetActive(false); professionPanelInstance.transform.SetSiblingIndex(((Component)MessageHud.instance).transform.GetSiblingIndex()); Skill_Element.tooltipPrefab = InventoryGui.instance.m_playerGrid.m_elementPrefab.GetComponent<UITooltip>().m_tooltipPrefab; } } [HarmonyPatch(typeof(Skills), "Awake")] public static class PopulateSelectPanel { private static void Postfix(Skills __instance) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_00f8: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) Skills __instance2 = __instance; if (!Object.op_Implicit((Object)(object)Professions.professionPanelInstance)) { return; } GameObject? professionPanelInstance = Professions.professionPanelInstance; ProfessionPanel professionPanel = ((professionPanelInstance != null) ? professionPanelInstance.GetComponent<ProfessionPanel>() : null); if (professionPanel == null || ((Transform)professionPanel.panelToInstantiateIn).childCount != 0) { return; } professionPanelElements.Clear(); Profession[] array = (Profession[])Enum.GetValues(typeof(Profession)); foreach (Profession profession in array) { SkillType skillType = fromProfession(profession); Skill skill = __instance2.GetSkill(skillType); if (skill.m_info == null) { __instance2.m_skillData.Remove(skillType); continue; } Sprite icon = skill.m_info.m_icon; Localization instance = Localization.instance; SkillType val = fromProfession(profession); GameObject val2 = professionPanel.InstantiateSkill(icon, instance.Localize(("$skill_" + ((object)(SkillType)(ref val)).ToString()).ToLowerInvariant()), professionDescriptions[profession], "Select"); professionPanelElements[profession] = val2; val2.SetActive(blockOtherProfessions[profession].Value != ProfessionToggle.Ignored); Skill_Element component = val2.GetComponent<Skill_Element>(); component.profession = profession; ((UnityEvent)component.Select.onClick).AddListener((UnityAction)delegate { //IL_00b1: 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_033e: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) if (Helper.getActiveProfessions().Contains(profession)) { if (allowUnselect.Value == Toggle.On && professionChangeCooldown.Value > 0f && Player.m_localPlayer.m_customData.TryGetValue("Professions LastProfessionChange", out var value)) { int num = int.Parse(value) + (int)(professionChangeCooldown.Value * 3600f) - (int)((DateTimeOffset)serverTime).ToUnixTimeSeconds(); if (num > 0) { ((Character)Player.m_localPlayer).Message((MessageType)2, "You can change your profession in " + Helper.getHumanFriendlyTime(num) + ".", 0, (Sprite)null); return; } } Dictionary<Profession, float> inactiveProfessions = Helper.getInactiveProfessions(); float level = __instance2.GetSkill(skillType).m_level; float value2 = ((resetLevelOnUnselect.Value == Toggle.On) ? (level * 0.5f) : level); inactiveProfessions[profession] = value2; Helper.storeInactiveProfessions(inactiveProfessions); HashSet<Profession> activeProfessions = Helper.getActiveProfessions(); activeProfessions.Remove(profession); Helper.storeActiveProfessions(activeProfessions); Player.m_localPlayer.m_skills.m_skillData.Remove(skillType); Player.m_localPlayer.m_customData["Professions LastProfessionChange"] = ((DateTimeOffset)serverTime).ToUnixTimeSeconds().ToString(); } else { if (!Player.m_localPlayer.m_knownStations.TryGetValue("Professions extraProfessionsSlots", out var value3)) { Player.m_localPlayer.m_knownStations["Professions extraProfessionsSlots"] = 0; value3 = 0; } HashSet<Profession> hashSet = Helper.getActiveProfessions() ?? new HashSet<Profession>(); int num2 = maximumAllowedProfessions.Value + value3; if (!hashSet.Contains(profession) && hashSet.Count >= num2) { Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory == null) { return; } int num3 = RequiredTrophies(num2); ItemData val3 = FindItemBySharedName(inventory, "craftsman trophy", num3); if (val3 == null) { ((Character)Player.m_localPlayer).Message((MessageType)2, $"You need Craftsman Trophy x {num3:#}.", 0, (Sprite)null); return; } for (int j = 0; j < num3; j++) { ((Humanoid)Player.m_localPlayer).GetInventory().RemoveOneItem(val3); } Player.m_localPlayer.StartEmote("cheer", true); ((Character)Player.m_localPlayer).Message((MessageType)2, $"Consumed Craftsman Trophy x {num3:#}.", 0, (Sprite)null); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)Player.m_localPlayer).transform.position, Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)Player.m_localPlayer).transform.position, Quaternion.identity); Player.m_localPlayer.m_knownStations["Professions extraProfessionsSlots"] = value3 + 1; value3++; num2 = maximumAllowedProfessions.Value + value3; } Dictionary<Profession, float> dictionary = Helper.getInactiveProfessions() ?? new Dictionary<Profession, float>(); if (dictionary.TryGetValue(profession, out var value4)) { Player.m_localPlayer.m_skills.GetSkill(skillType).m_level = value4; dictionary.Remove(profession); Helper.storeInactiveProfessions(dictionary); } else { Player.m_localPlayer.m_skills.GetSkill(skillType).m_level = 1f; } hashSet.Add(profession); Helper.storeActiveProfessions(hashSet); } UpdateSelectPanelSelections(); }); } } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] private class PreventExperience { private static bool Prefix(SkillType skillType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Profession? profession = fromSkill(skillType); if (profession.HasValue) { Profession valueOrDefault = profession.GetValueOrDefault(); if (!Helper.getActiveProfessions().Contains(valueOrDefault)) { return blockOtherProfessions[valueOrDefault].Value == ProfessionToggle.Ignored; } } return true; } } [HarmonyPatch] private class DisablePlayerInputInProfessionMenu { private static IEnumerable<MethodInfo> TargetMethods() { return new MethodInfo[2] { AccessTools.DeclaredMethod(typeof(StoreGui), "IsVisible", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(TextInput), "IsVisible", (Type[])null, (Type[])null) }; } private static void Postfix(ref bool __result) { GameObject? professionPanelInstance = Professions.professionPanelInstance; if (professionPanelInstance != null && professionPanelInstance.activeSelf) { __result = true; } } } private const string ModName = "Professions"; private const string ModVersion = "1.4.5"; private const string ModGUID = "org.bepinex.plugins.professions"; private static readonly ConfigSync configSync = new ConfigSync("org.bepinex.plugins.professions") { DisplayName = "Professions", CurrentVersion = "1.4.5", MinimumRequiredVersion = "1.4.5" }; private static ConfigEntry<Toggle> serverConfigLocked = null; private static ConfigEntry<KeyboardShortcut> professionPanelHotkey = null; private static ConfigEntry<int> maximumAllowedProfessions = null; public static ConfigEntry<Toggle> allowUnselect = null; private static ConfigEntry<Toggle> resetLevelOnUnselect = null; private static ConfigEntry<float> professionChangeCooldown = null; public static readonly Dictionary<Profession, ConfigEntry<ProfessionToggle>> blockOtherProfessions = new Dictionary<Profession, ConfigEntry<ProfessionToggle>>(); private static DateTime serverTime = DateTime.Now; private int configOrder; private static readonly Dictionary<Profession, string> professionDescriptions = new Dictionary<Profession, string> { { Profession.Blacksmithing, "A blacksmith uses the smelter and forge to smelt ore and craft armor and weapons." }, { Profession.Building, "A builder uses the hammer to construct floors, walls and roofs for shelter." }, { Profession.Cooking, "A cook creates lavish meals." }, { Profession.Farming, "A farmer uses the cultivator to cultivate land to plant crops and harvest them." }, { Profession.Lumberjacking, "A lumberjack uses an axe to cut trees to collect all kind of woods." }, { Profession.Mining, "A miner uses a pickaxe to mine stone and ore." }, { Profession.Ranching, "A rancher can tame certain animals and breed them for their meat." }, { Profession.Sailing, "A sailor uses ships to explore the vast ocean and discover new islands." }, { Profession.Alchemy, "An alchemist creates powerful potions, flasks and elixirs." }, { Profession.Jewelcrafting, "A jeweler cuts powerful magic gems and adds sockets to equipment." }, { Profession.Foraging, "A forager collects berries and mushrooms." }, { Profession.Exploration, "An explorer explores the world and searches treasure chests." } }; private static GameObject professionPanel = null; private static GameObject? professionPanelInstance; private static readonly Dictionary<Profession, GameObject> professionPanelElements = new Dictionary<Profession, GameObject>(); private readonly Assembly? bepinexConfigManager = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager"); private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown description = new ConfigDescription(description.Description, description.AcceptableValues, CollectionExtensions.AddItem<object>((IEnumerable<object>)description.Tags, (object)new ConfigurationManagerAttributes { Order = configOrder-- }).ToArray()); ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description); configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting; return val; } private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } private static SkillType fromProfession(Profession profession) { //IL_000c: 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_0011: 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) return (SkillType)(profession switch { Profession.Cooking => 105, Profession.Farming => 106, _ => Math.Abs(StringExtensionMethods.GetStableHashCode(profession.ToString())), }); } private static Profession? fromSkill(SkillType skill) { //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) return ((IEnumerable<Profession>)(Profession[])Enum.GetValues(typeof(Profession))).Select((Func<Profession, Profession?>)((Profession p) => p)).FirstOrDefault((Profession? p) => skill == fromProfession(p.Value)); } public void Awake() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) try { Type configManagerType = bepinexConfigManager?.GetType("ConfigurationManager.ConfigurationManager"); object configManager = ((configManagerType == null) ? null : Chainloader.ManagerObject.GetComponent(configManagerType)); serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked); maximumAllowedProfessions = config("1 - General", "Maximum Number of Professions", 1, new ConfigDescription("Sets the maximum number of professions a player is allowed to have at the same time.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>())); allowUnselect = config("1 - General", "Allow Profession Change", Toggle.Off, "If on, players can unselect professions and select new ones."); ConfigurationManagerAttributes changeCooldownAttributes = new ConfigurationManagerAttributes { Browsable = (allowUnselect.Value == Toggle.On) }; allowUnselect.SettingChanged += delegate { changeCooldownAttributes.Browsable = allowUnselect.Value == Toggle.On; reloadConfigDisplay(); }; resetLevelOnUnselect = config("1 - General", "Reset Level on Unlearn", Toggle.On, new ConfigDescription("If on, the skill level of a profession is reset, if you unlearn it.", (AcceptableValueBase)null, new object[1] { changeCooldownAttributes })); professionChangeCooldown = config("1 - General", "Profession Change Cooldown", 0f, new ConfigDescription("Time between profession changes. Uses real time hours. Use 0 to disable this.", (AcceptableValueBase)null, new object[1] { changeCooldownAttributes })); professionPanelHotkey = config<KeyboardShortcut>("1 - General", "Profession Panel Hotkey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Key or key combination to open the profession panel.", synchronizedSetting: false); Profession[] array = (Profession[])Enum.GetValues(typeof(Profession)); foreach (Profession profession in array) { blockOtherProfessions[profession] = config("2 - Professions", $"{profession} behaviour", ProfessionToggle.BlockExperience, "Ignored: The skill is not considered a profession and can be used by everyone.\nBlock Experience: If you did not pick the skills profession, you will not get any experience for this skill.\nBlock Usage: If you did not pick the skills profession, you will not be able to perform the action that would grant you experience for the skill."); blockOtherProfessions[profession].SettingChanged += delegate { if (professionPanelElements.TryGetValue(profession, out GameObject value)) { value.SetActive(blockOtherProfessions[profession].Value != ProfessionToggle.Ignored); } }; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); new Harmony("org.bepinex.plugins.professions").PatchAll(executingAssembly); professionPanel = LoadAssetBundle("professionSelect").LoadAsset<GameObject>("ProfessionPanel"); Skill_Element.blockExperience = Helper.loadSprite("blockxp.png", 1, 1); Skill_Element.blockUsage = Helper.loadSprite("blockusage.png", 1, 1); void reloadConfigDisplay() { configManagerType?.GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>()); } } catch (Exception arg) { Debug.LogError((object)$"Professions Awake failed. Shutting down, to prevent further issues with the professions. Exception:\n{arg}"); Application.Quit(); } } private static void onServerTimeReceived(ZRpc? rpc, long time) { serverTime = new DateTime(time); } private static void onServerTimeRequest(ZRpc rpc) { rpc.Invoke("Professions GetServerTime", new object[1] { DateTime.Now.Ticks }); } private static void requestServerTime() { if (ZNet.instance.IsServer()) { onServerTimeReceived(null, DateTime.Now.Ticks); } else { ZNet.instance.GetServerPeer().m_rpc.Invoke("Professions GetServerTime", Array.Empty<object>()); } } private void Update() { //IL_0013: 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) PreventMainMenu.AllowMainMenu = true; if (Player.m_localPlayer == null) { return; } KeyboardShortcut value = professionPanelHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && (professionPanelInstance.activeSelf || ((Character)Player.m_localPlayer).TakeInput())) { professionPanelInstance.SetActive(!professionPanelInstance.activeSelf); if (professionPanelInstance.activeSelf) { UpdateSelectPanelSelections(); requestServerTime(); } } if (professionPanelInstance.activeSelf && Input.GetKey((KeyCode)27)) { professionPanelInstance.SetActive(false); PreventMainMenu.AllowMainMenu = false; } } public static SkillType GetSkillTypeFromProfession(Profession profession) { //IL_000c: 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_0011: 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) return (SkillType)(profession switch { Profession.Cooking => 105, Profession.Farming => 106, _ => Math.Abs(StringExtensionMethods.GetStableHashCode(profession.ToString())), }); } private static void UpdateSelectPanelSelections() { HashSet<Profession> activeProfessions = Helper.getActiveProfessions(); if (!Player.m_localPlayer.m_knownStations.TryGetValue("Professions extraProfessionsSlots", out var value)) { Player.m_localPlayer.m_knownStations["Professions extraProfessionsSlots"] = 0; value = 0; } foreach (KeyValuePair<Profession, GameObject> professionPanelElement in professionPanelElements) { Skill_Element component = professionPanelElement.Value.GetComponent<Skill_Element>(); component.Toggle(activeProfessions.Contains(professionPanelElement.Key), activeProfessions.Count >= maximumAllowedProfessions.Value + value); component.UpdateImageDisplay(blockOtherProfessions[professionPanelElement.Key].Value); } int num = RequiredTrophies(maximumAllowedProfessions.Value + value); professionPanelInstance.GetComponent<ProfessionPanel>().description.text = string.Format("You have {0} / {1} professions selected.\nYou need Craftsman Trophy x {2} to unlock another profession.\nYou are{3} allowed to change your professions{4}.", activeProfessions.Count, maximumAllowedProfessions.Value + value, num, (allowUnselect.Value == Toggle.Off) ? " not" : "", (professionChangeCooldown.Value > 0f && allowUnselect.Value == Toggle.On) ? (" every " + Helper.getHumanFriendlyTime((int)(professionChangeCooldown.Value * 3600f))) : ""); string text = ((resetLevelOnUnselect.Value == Toggle.On) ? "Relearn at 50% of your previous level." : "Relearn at 100% of your previous level."); professionPanelInstance.GetComponent<ProfessionPanel>().description.text = $"You have {activeProfessions.Count} / {maximumAllowedProfessions.Value + value} professions selected.\n" + $"You need Craftsman Trophy x {num} to unlock another profession.\n" + "You are" + ((allowUnselect.Value == Toggle.Off) ? " not" : "") + " allowed to change your professions" + ((professionChangeCooldown.Value > 0f && allowUnselect.Value == Toggle.On) ? (" every " + Helper.getHumanFriendlyTime((int)(professionChangeCooldown.Value * 3600f))) : "") + ".\n" + text; } private static AssetBundle LoadAssetBundle(string bundleName) { string bundleName2 = bundleName; string name = typeof(Professions).Assembly.GetManifestResourceNames().Single((string s) => s.EndsWith(bundleName2)); return AssetBundle.LoadFromStream(typeof(Professions).Assembly.GetManifestResourceStream(name)); } private static int RequiredTrophies(int allowed) { if (allowed <= 0) { return 0; } return allowed switch { 1 => 2, 2 => 3, 3 => 5, 4 => 9, 5 => 16, 6 => 30, 7 => 60, 8 => 120, 9 => 240, 10 => 480, 11 => 1000, _ => Mathf.CeilToInt(0.97657f * Mathf.Pow(2f, (float)allowed)), }; } private static ItemData FindItemBySharedName(Inventory inv, string lowerName, int minStack) { for (int i = 0; i < inv.GetHeight(); i++) { for (int j = 0; j < inv.GetWidth(); j++) { ItemData itemAt = inv.GetItemAt(j, i); if (itemAt != null && itemAt.m_shared?.m_name != null && itemAt.m_shared.m_name.ToLower() == lowerName && itemAt.m_stack >= minStack) { return itemAt; } } } return null; } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = (from p in ZNet.instance.GetPeers() where adminList.Contains(p.m_rpc.GetSocket().GetHostName()) select p).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (__instance.IsServer()) { BufferingSocket value = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, value); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, value); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = value; } } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<ConfigSync> configSyncs; private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>(); private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>(); private static bool isServer; private static bool lockExempt; private OwnConfigEntryBase? lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>(); private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; public event Action<bool>? SourceOfTruthChanged; private event Action? lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet<ConfigSync>(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry) { ConfigEntry<T> configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Expected O, but got Unknown //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv) { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value)) { value = new SortedDictionary<int, byte[]>(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteArray()); if (value.Count < num2) { return false; } configValueCache.Remove(text2); package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray()); b = package.ReadByte(); } ProcessingServerUpdate = true; if ((b & 4u) != 0) { byte[] buffer = package.ReadByteArray(); MemoryStream stream = new MemoryStream(buffer); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress)) { deflateStream.CopyTo(memoryStream); } package = new ZPackage(memoryStream.ToArray()); b = package.ReadByte(); } if ((b & 1) == 0) { resetConfigsFromServer(); } ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package); foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues) { if (!isServer && configValue.Key.LocalBaseValue == null) { configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue; } configValue.Key.BaseConfig.BoxedValue = configValue.Value; } foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues) { if (!isServer) { CustomSyncedValueBase key2 = customValue.Key; if (key2.LocalBaseValue == null) { key2.LocalBaseValue = customValue.Key.BoxedValue; } } customValue.Key.BoxedValue = customValue.Value; } Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name)); if (!isServer) { serverLockedSettingChanged(); } return true; } finally { ProcessingServerUpdate = false; } } private ParsedConfigs ReadConfigsFromPackage(ZPackage package) { ParsedConfigs parsedConfigs = new ParsedConfigs(); Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c); Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string text = package.ReadString(); string text2 = package.ReadString(); string text3 = package.ReadString(); Type type = Type.GetType(text3); if (text3 == "" || type != null) { object obj; try { obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type)); } catch (InvalidDeserializationTypeException ex) { Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected)); continue; } OwnConfigEntryBase value2; if (text == "Internal") { CustomSyncedValueBase value; if (text2 == "serverversion") { if (obj?.ToString() != CurrentVersion) { Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown"))); } } else if (text2 == "lockexempt") { if (obj is bool flag) { lockExempt = flag; } } else if (dictionary2.TryGetValue(text2, out value)) { if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3) { parsedConfigs.customValues[value] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName)); } } else if (dictionary.TryGetValue(text + "_" + text2, out value2)) { Type type2 = configType(value2.BaseConfig); if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3) { parsedConfigs.configValues[value2] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName)); } else { Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match.")); } continue; } Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs")); return new ParsedConfigs(); } return parsedConfigs; } private static bool isWritableConfig(OwnConfigEntryBase config) { OwnConfigEntryBase config2 = config; ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2)); if (configSync == null) { return true; } return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt)); } private void serverLockedSettingChanged() { foreach (OwnConfigEntryBase allConfig in allConfigs) { configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig); } } private void resetConfigsFromServer() { foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null)) { item.BaseConfig.BoxedValue = item.LocalBaseValue; item.LocalBaseValue = null; } foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null)) { item2.BoxedValue = item2.LocalBaseValue; item2.LocalBaseValue = null; } lockedConfigChanged -= serverLockedSettingChanged; serverLockedSettingChanged(); } private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package) { ZNetPeer peer2 = peer; ZRoutedRpc rpc = ZRoutedRpc.instance; if (rpc == null) { yield break; } byte[] data = package.GetArray(); if (data != null && data.LongLength > 250000) { int fragments = (int)(1 + (data.LongLength - 1) / 250000); long packageIdentifier = ++packageCounter; int fragment = 0; while (fragment < fragments) { foreach (bool item in waitForQueue()) { yield return item; } if (peer2.m_socket.IsConnected()) { ZPackage fragmentedPackage = new ZPackage(); fragmentedPackage.Write((byte)2); fragmentedPackage.Write(packageIdentifier); fragmentedPackage.Write(fragment); fragmentedPackage.Write(fragments); fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray()); SendPackage(fragmentedPackage); if (fragment != fragments - 1) { yield return true; } int num = fragment + 1; fragment = num; continue; } break; } yield break; } foreach (bool item2 in waitForQueue()) { yield return item2; } SendPackage(package); void SendPackage(ZPackage pkg) { string text = Name + " ConfigSync"; if (isServer) { peer2.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg }); } } IEnumerable<bool> waitForQueue() { float timeout = Time.time + 30f; while (peer2.m_socket.GetSendQueueSize() > 20000) { if (Time.time > timeout) { Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout"); peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 }); ZNet.instance.Disconnect(peer2); break; } yield return false; } } } private IEnumerator sendZPackage(long target, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return Enumerable.Empty<object>().GetEnumerator(); } List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance); if (target != ZRoutedRpc.Everybody) { list = list.Where((ZNetPeer p) => p.m_uid == target).ToList(); } return sendZPackage(list, package); } private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package) { ZPackage package2 = package; if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] rawData = package2.GetArray(); if (rawData != null && rawData.LongLength > 10000) { ZPackage compressedPackage = new ZPackage(); compressedPackage.Write((byte)4); MemoryStream output = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal)) { deflateStream.Write(rawData, 0, rawData.Length); } compressedPackage.Write(output.ToArray()); package2 = compressedPackage; } List<IEnumerator<bool>> writers = (from peer in peers where peer.IsReady() select peer into p select distributeConfigToPeers(p, package2)).ToList(); writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); while (writers.Count > 0) { yield return null; writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); } } private void Broadcast(long target, params ConfigEntryBase[] configs) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(configs); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private void Broadcast(long target, params CustomSyncedValueBase[] customValues) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(null, customValues); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private static OwnConfigEntryBase? configData(ConfigEntryBase config) { return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault(); } public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config) { return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault(); } private static T configAttribute<T>(ConfigEntryBase config) { return config.Description.Tags.OfType<T>().First(); } private static Type configType(ConfigEntryBase config) { return configType(config.SettingType); } private static Type configType(Type type) { return type.IsEnum ? Enum.GetUnderlyingType(type) : type; } private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>(); List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>(); ZPackage val = new ZPackage(); val.Write((byte)(partial ? 1 : 0)); val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0)); foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>()) { AddEntryToPackage(val, item); } foreach (CustomSyncedValueBase item2 in list2) { AddEntryToPackage(val, new PackageEntry { section = "Internal", key = item2.Identifier, type = item2.Type, value = item2.BoxedValue }); } foreach (ConfigEntryBase item3 in list) { AddEntryToPackage(val, new PackageEntry { section = item3.Definition.Section, key = item3.Definition.Key, type = configType(item3), value = item3.BoxedValue }); } return val; } private static void AddEntryToPackage(ZPackage package, PackageEntry entry) { package.Write(entry.section); package.Write(entry.key); package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type)); AddValueToZPackage(package, entry.value); } private static string GetZPackageTypeString(Type type) { return type.AssemblyQualifiedName; } private static void AddValueToZPackage(ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { AddValueToZPackage(package, item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetZPackageTypeString(fieldInfo.FieldType)); AddValueToZPackage(package, fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetZPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetZPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = ReadValueWithTypeFromZPackage(package, type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List<string>) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List<object> source = new List<object>(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.First(); } } [PublicAPI] [HarmonyPatch] internal class VersionCheck { private static readonly HashSet<VersionCheck> versionChecks; private static readonly Dictionary<string, string> notProcessedNames; public string Name; private string? displayName; private string? currentVersion; private string? minimumRequiredVersion; public bool ModRequired = true; private string? ReceivedCurrentVersion; private string? ReceivedMinimumRequiredVersion; private readonly List<ZRpc> ValidatedClients = new List<ZRpc>(); private ConfigSync? ConfigSync; public string DisplayName { get { return displayName ?? Name; } set { displayName = value; } } public string CurrentVersion { get { return currentVersion ?? "0.0.0"; } set { currentVersion = value; } } public string MinimumRequiredVersion { get { return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0"); } set { minimumRequiredVersion = value; } } private static void PatchServerSync() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null)); if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0) { return; } Harmony val = new Harmony("org.bepinex.helpers.ServerSync"); foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) }) where t.IsClass select t) { val.PatchAll(item); } } static VersionCheck() { versionChecks = new HashSet<VersionCheck>(); notProcessedNames = new Dictionary<string, string>(); typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1] { new Action(PatchServerSync) }); } public VersionCheck(string name) { Name = name; ModRequired = true; versionChecks.Add(this); } public VersionCheck(ConfigSync configSync) { ConfigSync = configSync; Name = ConfigSync.Name; versionChecks.Add(this); } public void Initialize() { ReceivedCurrentVersion = null; ReceivedMinimumRequiredVersion = null; if (ConfigSync != null) { Name = ConfigSync.Name; DisplayName = ConfigSync.DisplayName; CurrentVersion = ConfigSync.CurrentVersion; MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion; ModRequired = ConfigSync.ModRequired; } } private bool IsVersionOk() { if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null) { return !ModRequired; } bool flag = new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion); bool flag2 = new Version(ReceivedCurrentVersion) >= new Version(MinimumRequiredVersion); return flag && flag2; } private string ErrorClient() { if (ReceivedMinimumRequiredVersion == null) { return "Mod " + DisplayName + " must not be installed."; } return (new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion)) ? ("Mod " + DisplayName + " requires maximum " + ReceivedCurrentVersion + ". Installed is version " + CurrentVersion + ".") : ("Mod " + DisplayName + " requires minimum " + ReceivedMinimumRequiredVersion + ". Installed is version " + CurrentVersion + "."); } private string ErrorServer(ZRpc rpc) { return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion; } private string Error(ZRpc? rpc = null) { return (rpc == null) ? ErrorClient() : ErrorServer(rpc); } private static VersionCheck[] GetFailedClient() { return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray(); } private static VersionCheck[] GetFailedServer(ZRpc rpc) { ZRpc rpc2 = rpc; return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray(); } private static void Logout() { Game.instance.Logout(true, true); AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3); } private static void DisconnectClient(ZRpc rpc) { rpc.Invoke("Error", new object[1] { 3 }); } private static void CheckVersion(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, null); } private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); string text3 = pkg.ReadString(); bool flag = false; foreach (VersionCheck versionCheck in versionChecks) { if (!(text != versionCheck.Name)) { Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + ".")); versionCheck.ReceivedMinimumRequiredVersion = text2; versionCheck.ReceivedCurrentVersion = text3; if (ZNet.instance.IsServer() && versionCheck.IsVersionOk()) { versionCheck.ValidatedClients.Add(rpc); } flag = true; } } if (flag) { return; } pkg.SetPos(0); if (original != null) { original(rpc, pkg); if (pkg.GetPos() == 0) { notProcessedNames.Add(text, text3); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance) { VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient()); if (array.Length == 0) { return true; } VersionCheck[] array2 = array; foreach (VersionCheck versionCheck in array2) { Debug.LogWarnin
BepInEx/plugins/RepairRequiresCoins.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RepairRequiresCoins")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RepairRequiresCoins")] [assembly: AssemblyTitle("RepairRequiresCoins")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace RepairRequiresMats { [BepInPlugin("aedenthorn.RepairRequiresMats", "Repair Requires Mats", "0.5.0")] public class BepInExPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(InventoryGui), "RepairOneItem")] private static class InventoryGui_RepairOneItem_Patch { private static void Postfix(InventoryGui __instance) { if (modEnabled.Value) { Traverse.Create((object)__instance).Method("UpdateRepair", Array.Empty<object>()).GetValue(); } } } [HarmonyPatch(typeof(UITooltip), "LateUpdate")] private static class UITooltip_LateUpdate_Patch { private static void Postfix(UITooltip __instance, UITooltip ___m_current, GameObject ___m_tooltip) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (modEnabled.Value && !((Object)(object)___m_current != (Object)(object)__instance) && !((Object)(object)___m_tooltip == (Object)null) && IsRepairTooltipOwner(__instance)) { ___m_tooltip.transform.position = Input.mousePosition + new Vector3(-200f, -100f); if (showAllRepairsInToolTip.Value && !string.IsNullOrEmpty(cachedRepairTooltip)) { SetTooltipText(___m_tooltip, cachedRepairTooltip); } } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRepair")] private static class InventoryGui_UpdateRepair_Patch { private static void Postfix(InventoryGui __instance, ref List<ItemData> ___m_tempWornItems) { if (!modEnabled.Value) { return; } if ((Object)(object)Player.m_localPlayer == (Object)null) { cachedRepairTooltip = null; return; } if (___m_tempWornItems == null || !___m_tempWornItems.Any()) { cachedRepairTooltip = null; return; } List<RepairItemData> list = new List<RepairItemData>(); List<RepairItemData> list2 = new List<RepairItemData>(); List<RepairItemData> list3 = new List<RepairItemData>(); List<RepairItemData> list4 = new List<RepairItemData>(); List<string> list5 = new List<string>(); foreach (ItemData ___m_tempWornItem in ___m_tempWornItems) { if (!Traverse.Create((object)__instance).Method("CanRepair", new object[1] { ___m_tempWornItem }).GetValue<bool>()) { list4.Add(new RepairItemData(___m_tempWornItem)); continue; } List<Requirement> list6 = RepairReqs(___m_tempWornItem); if (list6 == null) { list.Add(new RepairItemData(___m_tempWornItem)); continue; } List<string> list7 = new List<string>(); foreach (Requirement item in list6) { if (item?.m_resItem?.m_itemData?.m_shared != null && item.m_amount != 0) { list7.Add($"{item.m_amount}/{((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item.m_resItem.m_itemData.m_shared.m_name, -1, true)} {Localization.instance.Localize(item.m_resItem.m_itemData.m_shared.m_name)}"); } } bool flag = true; foreach (Requirement item2 in list6) { if (item2?.m_resItem?.m_itemData?.m_shared != null) { int amount = item2.m_amount; if (((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item2.m_resItem.m_itemData.m_shared.m_name, -1, true) < amount) { flag = false; break; } } } if (!flag) { list3.Add(new RepairItemData(___m_tempWornItem, list7)); } else { list2.Add(new RepairItemData(___m_tempWornItem, list7)); } } orderedWornItems = new List<ItemData>(); foreach (RepairItemData item3 in list) { list5.Add("<color=#" + hasEnoughTooltipColor.Value + ">" + Localization.instance.Localize(item3.item.m_shared.m_name) + ": Free</color>"); orderedWornItems.Add(item3.item); } foreach (RepairItemData item4 in list2) { list5.Add("<color=#" + hasEnoughTooltipColor.Value + ">" + Localization.instance.Localize(item4.item.m_shared.m_name) + ": " + string.Join(", ", item4.reqstring) + "</color>"); orderedWornItems.Add(item4.item); } foreach (RepairItemData item5 in list3) { list5.Add("<color=#" + notEnoughTooltipColor.Value + ">" + Localization.instance.Localize(item5.item.m_shared.m_name) + ": " + string.Join(", ", item5.reqstring) + "</color>"); orderedWornItems.Add(item5.item); } foreach (RepairItemData item6 in list4) { orderedWornItems.Add(item6.item); } ___m_tempWornItems = new List<ItemData>(orderedWornItems); if (showAllRepairsInToolTip.Value) { if (list5.Count == 0) { cachedRepairTooltip = null; return; } cachedRepairTooltip = "<b><color=#" + titleTooltipColor.Value + ">" + Localization.instance.Localize("$inventory_repairbutton") + "</color></b>\n" + string.Join("\n", list5); } } } [HarmonyPatch(typeof(InventoryGui), "CanRepair")] private static class InventoryGui_CanRepair_Patch { private static void Postfix(ItemData item, ref bool __result) { if (!modEnabled.Value || !Environment.StackTrace.Contains("RepairOneItem") || Environment.StackTrace.Contains("HaveRepairableItems") || !__result || item?.m_shared == null || !((Object)(object)Player.m_localPlayer != (Object)null) || orderedWornItems.Count <= 0) { return; } if (orderedWornItems[0] != item) { __result = false; return; } List<Requirement> list = RepairReqs(item, log: true); if (list == null) { return; } List<string> list2 = new List<string>(); foreach (Requirement item2 in list) { if (item2?.m_resItem?.m_itemData?.m_shared != null) { list2.Add($"{item2.m_amount}/{((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item2.m_resItem.m_itemData.m_shared.m_name, -1, true)} {Localization.instance.Localize(item2.m_resItem.m_itemData.m_shared.m_name)}"); } } bool flag = true; foreach (Requirement item3 in list) { if (item3?.m_resItem?.m_itemData?.m_shared != null) { int amount = item3.m_amount; if (((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item3.m_resItem.m_itemData.m_shared.m_name, -1, true) < amount) { flag = false; break; } } } string text; if (flag) { Player.m_localPlayer.ConsumeResources(list.ToArray(), 1, -1, 1); text = "Used " + string.Join(", ", list2) + " to repair " + Localization.instance.Localize(item.m_shared.m_name); __result = true; } else { text = "Require " + string.Join(", ", list2) + " to repair " + Localization.instance.Localize(item.m_shared.m_name); __result = false; } ((Character)Player.m_localPlayer).Message((MessageType)1, text, 0, (Sprite)null); Dbgl(text); } } [HarmonyPatch(typeof(Terminal), "InputText")] private static class InputText_Patch { private static bool Prefix(Terminal __instance) { if (!modEnabled.Value) { return true; } string text = ""; try { object value = Traverse.Create((object)__instance).Field("m_input").GetValue(); InputField val = (InputField)((value is InputField) ? value : null); if (val != null) { text = val.text ?? ""; } else { TMP_InputField val2 = (TMP_InputField)((value is TMP_InputField) ? value : null); if (val2 != null) { text = val2.text ?? ""; } } } catch { } if (string.IsNullOrWhiteSpace(text)) { return true; } if (text.Trim().ToLower().Equals("repairmod reset")) { ((BaseUnityPlugin)context).Config.Reload(); ((BaseUnityPlugin)context).Config.Save(); Traverse.Create((object)__instance).Method("AddString", new object[1] { text }).GetValue(); Traverse.Create((object)__instance).Method("AddString", new object[1] { "Repair Items config reloaded" }).GetValue(); return false; } return true; } } private static bool isDebug = true; public static ConfigEntry<bool> modEnabled; public static ConfigEntry<bool> showAllRepairsInToolTip; public static ConfigEntry<float> materialRequirementMult; public static ConfigEntry<string> titleTooltipColor; public static ConfigEntry<string> hasEnoughTooltipColor; public static ConfigEntry<string> notEnoughTooltipColor; public static ConfigEntry<int> nexusID; private static List<ItemData> orderedWornItems = new List<ItemData>(); private static BepInExPlugin context; private static string cachedRepairTooltip = null; private static Assembly epicLootAssembly; private static MethodInfo epicLootIsMagic; private static MethodInfo epicLootGetRarity; private static MethodInfo epicLootGetEnchantCosts; public static void Dbgl(string str = "", bool pref = true) { if (isDebug) { Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str)); } } private void Awake() { context = this; modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod"); nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 215, "Nexus mod ID for updates"); showAllRepairsInToolTip = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowAllRepairsInToolTip", true, "Show all repairs in tooltip when hovering over repair button."); titleTooltipColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TitleTooltipColor", "FFFFFFFF", "Color to use in tooltip title."); hasEnoughTooltipColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HasEnoughTooltipColor", "FFFFFFFF", "Color to use in tooltip for items with enough resources to repair."); notEnoughTooltipColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "NotEnoughTooltipColor", "FF0000FF", "Color to use in tooltip for items with NOT enough resources to repair."); materialRequirementMult = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaterialRequirementMult", 0.5f, "Multiplier for amount of each material required."); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } private void Start() { if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot")) { epicLootAssembly = ((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType().Assembly; epicLootIsMagic = epicLootAssembly.GetType("EpicLoot.ItemDataExtensions")?.GetMethod("IsMagic", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); epicLootGetRarity = epicLootAssembly.GetType("EpicLoot.ItemDataExtensions")?.GetMethod("GetRarity", BindingFlags.Static | BindingFlags.Public); epicLootGetEnchantCosts = epicLootAssembly.GetType("EpicLoot.Crafting.EnchantTabController")?.GetMethod("GetEnchantCosts", BindingFlags.Static | BindingFlags.Public); Dbgl($"Loaded Epic Loot assembly; epicLootIsMagic {epicLootIsMagic != null}, epicLootGetRarity {epicLootGetRarity != null}, epicLootGetEnchantCosts {epicLootGetEnchantCosts != null}"); } } private static Button GetRepairButton() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { return null; } try { return Traverse.Create((object)instance).Field("m_repairButton").GetValue<Button>(); } catch { return null; } } private static bool IsRepairTooltipOwner(UITooltip ownerTooltipComponent) { Button repairButton = GetRepairButton(); if ((Object)(object)repairButton == (Object)null || (Object)(object)ownerTooltipComponent == (Object)null) { return false; } return (Object)(object)((Component)ownerTooltipComponent).transform == (Object)(object)((Component)repairButton).transform; } private static void SetTooltipText(GameObject tooltipRoot, string value) { if ((Object)(object)tooltipRoot == (Object)null) { return; } Text componentInChildren = tooltipRoot.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.supportRichText = true; componentInChildren.alignment = (TextAnchor)7; componentInChildren.text = value; return; } TMP_Text componentInChildren2 = tooltipRoot.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.richText = true; componentInChildren2.alignment = (TextAlignmentOptions)1026; componentInChildren2.text = value; } else { Dbgl("[TOOLTIP] No Text/TMP_Text found under tooltip root."); } } private static List<Requirement> RepairReqs(ItemData item, bool log = false) { //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Expected O, but got Unknown //IL_00ff: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown float maxDurability = item.GetMaxDurability(); if (maxDurability <= 0f) { return null; } float num = (maxDurability - item.m_durability) / maxDurability; Recipe recipe = ObjectDB.instance.GetRecipe(item); if ((Object)(object)recipe == (Object)null) { return null; } List<Requirement> list = new List<Requirement>(recipe.m_resources); bool flag = false; if (epicLootAssembly != null && epicLootIsMagic != null) { try { MethodInfo methodInfo = epicLootIsMagic; object[] parameters = (object[])(object)new ItemData[1] { item }; flag = (bool)methodInfo.Invoke(null, parameters); } catch { } } if (flag && epicLootGetRarity != null && epicLootGetEnchantCosts != null) { try { MethodInfo methodInfo2 = epicLootGetRarity; object[] parameters = (object[])(object)new ItemData[1] { item }; int num2 = (int)methodInfo2.Invoke(null, parameters); foreach (KeyValuePair<ItemDrop, int> item2 in (List<KeyValuePair<ItemDrop, int>>)epicLootGetEnchantCosts.Invoke(null, new object[2] { item, num2 })) { list.Add(new Requirement { m_amount = item2.Value, m_resItem = item2.Key }); } } catch { } } List<Requirement> list2 = new List<Requirement>(); for (int i = 0; i < list.Count; i++) { if (list[i]?.m_resItem?.m_itemData?.m_shared == null) { continue; } Requirement val = new Requirement { m_resItem = list[i].m_resItem, m_amount = list[i].m_amount, m_amountPerLevel = list[i].m_amountPerLevel, m_recover = list[i].m_recover }; int num3 = 0; for (int num4 = item.m_quality; num4 > 0; num4--) { if (val.m_resItem.m_itemData.m_shared.m_name.ToLower().Contains("item_coins")) { num3 += val.GetAmount(num4); } } int num5 = Mathf.RoundToInt((float)num3 * num * materialRequirementMult.Value); if (num5 > 0) { val.m_amount = num5; list2.Add(val); } } if (!list2.Any()) { return null; } return list2; } } internal class RepairItemData : ItemData { public List<string> reqstring; public ItemData item; public RepairItemData(ItemData item, List<string> reqstring = null) { this.reqstring = reqstring; this.item = item; } } }
BepInEx/plugins/UsefulTrophiesXP.dll
Decompiled a day agousing System.CodeDom.Compiler; using System.Collections.Generic; using System.Configuration; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using EpicMMOSystem; using HarmonyLib; using UnityEngine; using ValheimLegends; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ClassLibrary1")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ClassLibrary1")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("fba93479-93ac-43d9-8ef2-cfb83bdb7b6d")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.1.1.0")] namespace UsefulTrophiesXP { [HarmonyPatch(typeof(Humanoid), "UseItem")] internal class UseItemPatch { public static bool Prefix(Player __instance, [HarmonyArgument(0)] Inventory inventory, [HarmonyArgument(1)] ItemData item, [HarmonyArgument(2)] bool fromInventoryGui, Inventory ___m_inventory, ZSyncAnimation ___m_zanim) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) string name = item.m_shared.m_name; if (name.Contains("$item_trophy_")) { string text = name.Substring(13); if (inventory == null) { inventory = ___m_inventory; } if (!inventory.ContainsItem(item)) { return false; } GameObject hoverObject = ((Humanoid)__instance).GetHoverObject(); if (!((Object)(object)hoverObject == (Object)null) && !fromInventoryGui) { Interactable componentInParent = hoverObject.GetComponentInParent<Interactable>(); if (componentInParent is ItemStand || componentInParent is OfferingBowl) { return true; } } float num = 10f; if (UsefulTrophiesXP.TrophyXPDict.TryGetValue(text, out var value)) { num = value * UsefulTrophiesXP.ExperienceModifier; } else { Debug.Log((object)("Unknown trophy for " + text + "!")); } inventory.RemoveOneItem(item); Player.m_localPlayer.m_skillLevelupEffects.Create(((Character)Player.m_localPlayer).GetHeadPoint(), Quaternion.identity, (Transform)null, 1f, -1); ValheimLegends.shouldUseGuardianPower = false; ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetSpeed(2f); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetTrigger("gpower"); LevelSystem.Instance.AddExp((int)num, false); ((Character)__instance).Message((MessageType)1, $"Experience received: {num}", 0, (Sprite)null); return false; } return true; } } [BepInPlugin("gg.khairex.usefultrophies.twentyonez.EpicMMOPatch", "Useful Trophies Mod by Khairex, EpicMMO XP Patch by TwentyOneZ", "2.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("valheim.exe")] public class UsefulTrophiesXP : BaseUnityPlugin { public const string Id = "gg.khairex.usefultrophies.twentyonez.EpicMMOPatch"; public static bool EnableSellingTrophies = true; public static float ExperienceModifier = 1f; public static Dictionary<string, float> TrophyXPDict = new Dictionary<string, float> { { "deer", 40f }, { "boar", 133f }, { "neck", 400f }, { "greydwarf", 1200f }, { "greydwarfbrute", 1500f }, { "greydwarfshaman", 1200f }, { "skeleton", 800f }, { "skeletonpoison", 1500f }, { "troll", 1000f }, { "surtling", 2600f }, { "leech", 1800f }, { "draugr", 1500f }, { "draugrelite", 5000f }, { "blob", 1800f }, { "wraith", 5000f }, { "abomination", 200f }, { "wolf", 3500f }, { "fenring", 4000f }, { "hatchling", 3000f }, { "sgolem", 14000f }, { "ulv", 4000f }, { "cultist", 4000f }, { "goblin", 4500f }, { "goblinbrute", 13000f }, { "goblinshaman", 4000f }, { "lox", 7000f }, { "growth", 6000f }, { "deathsquito", 6000f }, { "serpent", 1500f }, { "hare", 400f }, { "gjall", 3600f }, { "tick", 4800f }, { "dvergr", 6000f }, { "seeker", 18000f }, { "seekerbrute", 25000f }, { "eikthyr", 200f }, { "elder", 500f }, { "bonemass", 900f }, { "dragonqueen", 1400f }, { "goblinking", 3000f }, { "seekerqueen", 4500f }, { "ghost", 2500f }, { "bjorn", 3000f }, { "skeleton_hildir", 6000f }, { "cultist_hildir", 8000f }, { "bjorn_undead", 3500f }, { "shamanbro", 9000f }, { "brutebro", 9000f }, { "asksvin", 8000f }, { "bonemaw", 12000f }, { "fallenvalkyrie", 15000f }, { "charredarcher", 9000f }, { "morgen", 12000f }, { "volture", 9000f }, { "charredmage", 12000f }, { "charredmelee", 10000f }, { "fader", 20000f } }; public static Dictionary<string, int> TrophyGoldValueDict = new Dictionary<string, int> { { "deer", 15 }, { "boar", 10 }, { "neck", 10 }, { "greydwarf", 10 }, { "greydwarfbrute", 15 }, { "greydwarfshaman", 15 }, { "skeleton", 10 }, { "skeletonpoison", 15 }, { "troll", 50 }, { "surtling", 15 }, { "leech", 15 }, { "draugr", 15 }, { "draugrelite", 30 }, { "blob", 20 }, { "wraith", 30 }, { "abomination", 100 }, { "wolf", 25 }, { "fenring", 30 }, { "hatchling", 35 }, { "sgolem", 100 }, { "ulv", 50 }, { "cultist", 50 }, { "goblin", 35 }, { "goblinbrute", 50 }, { "goblinshaman", 50 }, { "lox", 150 }, { "growth", 50 }, { "deathsquito", 25 }, { "serpent", 250 }, { "hare", 40 }, { "gjall", 150 }, { "tick", 50 }, { "dvergr", 30 }, { "seeker", 50 }, { "seekerbrute", 100 }, { "eikthyr", 50 }, { "elder", 100 }, { "bonemass", 150 }, { "dragonqueen", 200 }, { "goblinking", 250 }, { "seekerqueen", 300 }, { "ghost", 30 }, { "bjorn", 50 }, { "skeleton_hildir", 50 }, { "cultist_hildir", 50 }, { "bjorn_undead", 50 }, { "shamanbro", 100 }, { "brutebro", 100 }, { "asksvin", 100 }, { "bonemaw", 250 }, { "fallenvalkyrie", 200 }, { "charredarcher", 120 }, { "morgen", 150 }, { "volture", 100 }, { "charredmage", 150 }, { "charredmelee", 120 }, { "fader", 300 } }; public Harmony Harmony { get; } = new Harmony("gg.khairex.usefultrophies.twentyonez.EpicMMOPatch"); private void Awake() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition("GoldValue", "EnableSellingTrophies"); EnableSellingTrophies = ((BaseUnityPlugin)this).Config.Bind<bool>(val, true, (ConfigDescription)null).Value; ConfigDefinition val2 = new ConfigDefinition("XPModifier", "ExperienceModifier"); ExperienceModifier = ((BaseUnityPlugin)this).Config.Bind<float>(val2, 1f, (ConfigDescription)null).Value; List<ConfigDefinition> list = new List<ConfigDefinition>(); foreach (string key in TrophyXPDict.Keys) { list.Add(new ConfigDefinition("ExpScaling", key)); } foreach (ConfigDefinition item in list) { TrophyXPDict[item.Key] = ((BaseUnityPlugin)this).Config.Bind<float>(item, TrophyXPDict[item.Key], (ConfigDescription)null).Value; } List<ConfigDefinition> list2 = new List<ConfigDefinition>(); foreach (string key2 in TrophyGoldValueDict.Keys) { list2.Add(new ConfigDefinition("GoldValue", key2)); } foreach (ConfigDefinition item2 in list2) { TrophyGoldValueDict[item2.Key] = ((BaseUnityPlugin)this).Config.Bind<int>(item2, TrophyGoldValueDict[item2.Key], (ConfigDescription)null).Value; } Harmony.PatchAll(); } } } namespace UsefulTrophiesXP.Properties { [CompilerGenerated] [GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] internal sealed class Settings : ApplicationSettingsBase { private static Settings defaultInstance = (Settings)(object)SettingsBase.Synchronized((SettingsBase)(object)new Settings()); public static Settings Default => defaultInstance; } }
BepInEx/plugins/VLDamageFix.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using EpicMMOSystem; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ValheimLegends")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ValheimLegends")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f0baf009-4135-4368-9987-850698809493")] [assembly: AssemblyFileVersion("0.4.9.3")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.9.3")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimLegends { public class AnimationClipOverrides : List<KeyValuePair<AnimationClip, AnimationClip>> { public AnimationClip this[string name] { get { return Find((KeyValuePair<AnimationClip, AnimationClip> x) => ((Object)x.Key).name == name).Value; } set { int num = FindIndex((KeyValuePair<AnimationClip, AnimationClip> x) => ((Object)x.Key).name == name); if (num != -1) { base[num] = new KeyValuePair<AnimationClip, AnimationClip>(base[num].Key, value); } } } public AnimationClipOverrides(int capacity) : base(capacity) { } } public class Class_Berserker { private static int Script_Layermask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece_nonsolid", "vehicle", "viewblock", "piece" }); private static int Player_Layermask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle" }); private static GameObject GO_CastFX; public static void Execute_Dash(Player player, ref float altitude, ref Rigidbody playerBody) { //IL_0015: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_0645: Unknown result type (might be due to invalid IL or missing references) //IL_0659: Unknown result type (might be due to invalid IL or missing references) //IL_065b: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0621: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: 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_01d9: 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_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_0637: 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_0248: 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) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0313: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Expected O, but got Unknown //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04ed: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_050a: Unknown result type (might be due to invalid IL or missing references) //IL_05bf: Unknown result type (might be due to invalid IL or missing references) //IL_05c4: Unknown result type (might be due to invalid IL or missing references) Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_perfectblock"), ((Component)player).transform.position, Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_stonegolem_attack_hit"), ((Component)player).transform.position, Quaternion.identity); float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f)); float num2 = 0.6f + num * 0.015f * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_berserkerDash; if (((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Berserk")) || ((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Execute"))) { SE_Berserk sE_Berserk = (SE_Berserk)(object)((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Berserk")); if ((Object)(object)sE_Berserk != (Object)null) { num2 *= sE_Berserk.damageModifier; } } Vector3 lookDir = ((Character)player).GetLookDir(); lookDir.y = 0f; ((Component)player).transform.rotation = Quaternion.LookRotation(lookDir); Vector3 val = default(Vector3); Vector3 forward = ((Component)player).transform.forward; Vector3 position = ((Component)player).transform.position; Vector3 val2 = ((Component)player).transform.position; val2.y += 0.1f; List<int> list = new List<int>(); float num3 = 1f; int i; for (i = 0; i <= 10; i++) { RaycastHit val3 = default(RaycastHit); bool flag = false; for (int j = 0; j <= 10; j++) { Vector3 val4 = Vector3.MoveTowards(((Component)player).transform.position, ((Component)player).transform.position + forward * 100f, (float)i + (float)j * 0.1f); val4.y = val2.y; if (val4.y < ZoneSystem.instance.GetGroundHeight(val4)) { val2.y = ZoneSystem.instance.GetGroundHeight(val4) + 1f; val4.y = val2.y; } flag = Physics.SphereCast(val4, 0.05f, forward, ref val3, float.PositiveInfinity, Script_Layermask); if (flag && Object.op_Implicit((Object)(object)((RaycastHit)(ref val3)).collider)) { val = ((RaycastHit)(ref val3)).point; break; } } position = Vector3.MoveTowards(((Component)player).transform.position, ((Component)player).transform.position + forward * 100f, (float)i); position.y = ((ZoneSystem.instance.GetSolidHeight(position) - ZoneSystem.instance.GetGroundHeight(position) <= 1f) ? ZoneSystem.instance.GetSolidHeight(position) : ZoneSystem.instance.GetGroundHeight(position)); if (flag && Vector3.Distance(new Vector3(position.x, val2.y, position.z), val) <= 1f) { val2 = Vector3.MoveTowards(val, val2, 1f); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_beehive_hit"), val2, Quaternion.identity); break; } Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_beehive_hit"), val2, Quaternion.identity); ((Vector3)(ref val2))..ctor(position.x, val2.y, position.z); foreach (Character allCharacter in Character.GetAllCharacters()) { HitData val5 = new HitData(); val5.m_damage = ((Humanoid)player).GetCurrentWeapon().GetDamage(); if (((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_DruidFenringForm")) && Class_Monk.PlayerIsBareHanded && val5.m_damage.m_blunt > 0f) { float num4 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f)); float num5 = (float)LevelSystem.Instance.getLevel() * (1f + num4 / 80f) * 0.25f; val5.m_damage.m_blunt += num5; val5.m_damage.m_slash += num5; } val5.ApplyModifier(Random.Range(0.8f, 1.2f) * num2 / num3); val5.m_point = allCharacter.GetCenterPoint(); val5.m_dir = ((Component)allCharacter).transform.position - position; val5.m_skill = ValheimLegends.DisciplineSkill; float num6 = Vector3.Distance(((Component)allCharacter).transform.position, position); if (!BaseAI.IsEnemy(allCharacter, (Character)(object)player) || !(num6 <= 3f) || list.Contains(((Object)allCharacter).GetInstanceID())) { continue; } SE_Execute sE_Execute = (SE_Execute)(object)((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Execute")); if ((Object)(object)sE_Execute != (Object)null) { val5.ApplyModifier(sE_Execute.damageBonus); sE_Execute.hitCount--; if (sE_Execute.hitCount <= 0) { ((Character)player).GetSEMan().RemoveStatusEffect((StatusEffect)(object)sE_Execute, false); } } num3 += 0.6f; allCharacter.Damage(val5); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_crit"), allCharacter.GetCenterPoint(), Quaternion.identity); list.Add(((Object)allCharacter).GetInstanceID()); } } list.Clear(); if (i > 10 && ZoneSystem.instance.GetSolidHeight(val2) - val2.y <= 2f) { val2.y = ZoneSystem.instance.GetSolidHeight(val2); } playerBody.position = val2; altitude = 0f; ((Component)player).transform.rotation = Quaternion.LookRotation(forward); } public static void Process_Input(Player player, ref float altitude) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) new Random(); if (VL_Utility.Ability3_Input_Down) { if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability3_CD"))) { if (player.GetStamina() > VL_Utility.GetDashCost(player)) { StatusEffect val = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD)); val.m_ttl = VL_Utility.GetDashCooldown(player); ((Character)player).GetSEMan().AddStatusEffect(val, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetDashCost(player)); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("swing_longsword2"); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)player).transform.position, Quaternion.identity); ValheimLegends.isChargingDash = true; ValheimLegends.dashCounter = 0; ((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetDashSkillGain(player)); } else { ((Character)player).Message((MessageType)1, "Not enough stamina for Dash: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetDashCost(player) + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else if (VL_Utility.Ability2_Input_Down) { if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability2_CD"))) { if (player.GetStamina() > VL_Utility.GetBerserkCost(player)) { StatusEffect val2 = (StatusEffect)(object)(SE_Ability2_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability2_CD)); val2.m_ttl = VL_Utility.GetBerserkCooldown(player); ((Character)player).GetSEMan().AddStatusEffect(val2, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetBerserkCost(player)); ValheimLegends.shouldUseGuardianPower = false; player.StartEmote("challenge", true); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_GP_Stone"), ((Character)player).GetCenterPoint(), Quaternion.identity); float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance(0) / 40f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); SE_Berserk sE_Berserk = (SE_Berserk)(object)ScriptableObject.CreateInstance(typeof(SE_Berserk)); ((StatusEffect)sE_Berserk).m_ttl = SE_Berserk.m_baseTTL; sE_Berserk.speedModifier = 1.2f + 0.006f * num; sE_Berserk.damageModifier = 1.2f + 0.006f * num * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_berserkerBerserk; sE_Berserk.healthAbsorbPercent = 0.2f + 0.002f * num; ((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Berserk, false, 0, 0f); ((Character)player).RaiseSkill(ValheimLegends.AlterationSkill, VL_Utility.GetBerserkSkillGain(player)); } else { ((Character)player).Message((MessageType)1, "Not enough stamina for Berserk: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetBerserkCost(player) + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else { if (!VL_Utility.Ability1_Input_Down) { return; } if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability1_CD"))) { if (player.GetStamina() > VL_Utility.GetExecuteCost(player)) { StatusEffect val3 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD)); val3.m_ttl = VL_Utility.GetExecuteCooldown(player); ((Character)player).GetSEMan().AddStatusEffect(val3, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetExecuteCost(player)); player.StartEmote("point", true); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_backstab"), ((Character)player).GetCenterPoint(), Quaternion.identity); float num2 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f)); SE_Execute sE_Execute = (SE_Execute)(object)ScriptableObject.CreateInstance(typeof(SE_Execute)); sE_Execute.hitCount = Mathf.RoundToInt(3f + 0.04f * num2); sE_Execute.damageBonus = 1.4f + 0.005f * num2 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_berserkerExecute; sE_Execute.staggerForce = 1.5f + 0.005f * num2; if (((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Execute"))) { StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Execute")); ((Character)player).GetSEMan().RemoveStatusEffect(statusEffect, false); } ((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Execute, false, 0, 0f); ((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetExecuteSkillGain(player)); } else { ((Character)player).Message((MessageType)1, "Not enough stamina for Execute: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetExecuteCost(player) + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } } } public class Class_Druid { private static int Script_Layermask = LayerMask.GetMask(new string[11] { "Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle", "piece", "viewblock", "character", "character_net", "character_ghost" }); private static GameObject GO_CastFX; private static GameObject GO_Root; private static Projectile P_Root; private static StatusEffect SE_Root; private static GameObject GO_RootDefender; private static int rootCount; private static int rootTotal; private static int rootCountTrigger; public static bool canDoubleJump = true; public static readonly int SE_FENRING_HASH = StringExtensionMethods.GetStableHashCode("SE_VL_DruidFenringForm"); public static readonly int SE_CULTIST_HASH = StringExtensionMethods.GetStableHashCode("SE_VL_DruidCultistForm"); private static readonly MethodInfo MI_GetRightItem = AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null); private static readonly MethodInfo MI_GetLeftItem = AccessTools.Method(typeof(Humanoid), "GetLeftItem", (Type[])null, (Type[])null); private static readonly FieldInfo FI_RightItem = AccessTools.Field(typeof(Humanoid), "m_rightItem"); private static readonly FieldInfo FI_LeftItem = AccessTools.Field(typeof(Humanoid), "m_leftItem"); private static readonly MethodInfo MI_UpdateEquipmentVisuals = AccessTools.Method(typeof(Humanoid), "UpdateEquipmentVisuals", (Type[])null, (Type[])null); public static void Process_FenringForm(Player player, float altitude, ref Rigidbody playerBody) { //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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00bc: Unknown result type (might be due to invalid IL or missing references) if (ZInput.GetButtonDown("Jump") && !((Character)player).IsDead() && !((Character)player).InAttack() && !((Character)player).IsEncumbered() && !((Character)player).InDodge() && !((Character)player).IsKnockedBack()) { if (!((Character)player).IsOnGround() && canDoubleJump) { Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; playerBody.linearVelocity = velocity * 2f + new Vector3(0f, 8f, 0f); canDoubleJump = false; altitude = 0f; ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("jump"); } else if (((Character)player).IsOnGround()) { canDoubleJump = true; } } if (VL_Utility.Ability1_Input_Down) { VL_AbilityBorrow.Ranger_ShadowStalk(player); } else if (VL_Utility.Ability2_Input_Down) { if (((Character)player).IsBlocking()) { TryActivate_HumanForm(player, forced: false); } else { VL_AbilityBorrow.Valkyrie_Stagger(player); } } else if (VL_Utility.Ability3_Input_Down) { VL_AbilityBorrow.Berserker_Dash(player); } } public static void Process_Input(Player player, float altitude, ref Rigidbody playerBody) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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) //IL_0790: Unknown result type (might be due to invalid IL or missing references) //IL_079c: Unknown result type (might be due to invalid IL or missing references) //IL_07a1: Unknown result type (might be due to invalid IL or missing references) //IL_07a4: Unknown result type (might be due to invalid IL or missing references) //IL_07aa: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: 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_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: 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_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_07d9: Unknown result type (might be due to invalid IL or missing references) //IL_07dc: Unknown result type (might be due to invalid IL or missing references) //IL_07e6: Unknown result type (might be due to invalid IL or missing references) //IL_07eb: Unknown result type (might be due to invalid IL or missing references) //IL_05c5: Unknown result type (might be due to invalid IL or missing references) //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_05d4: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: 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_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_08f0: Unknown result type (might be due to invalid IL or missing references) //IL_08f5: Unknown result type (might be due to invalid IL or missing references) //IL_0909: Unknown result type (might be due to invalid IL or missing references) //IL_090b: Unknown result type (might be due to invalid IL or missing references) //IL_07f0: Unknown result type (might be due to invalid IL or missing references) //IL_07f2: Unknown result type (might be due to invalid IL or missing references) //IL_07f9: Expected O, but got Unknown //IL_0828: Unknown result type (might be due to invalid IL or missing references) //IL_082d: Unknown result type (might be due to invalid IL or missing references) //IL_0834: Unknown result type (might be due to invalid IL or missing references) //IL_0839: Unknown result type (might be due to invalid IL or missing references) //IL_0841: Unknown result type (might be due to invalid IL or missing references) //IL_084d: Unknown result type (might be due to invalid IL or missing references) //IL_0852: Unknown result type (might be due to invalid IL or missing references) //IL_085c: Unknown result type (might be due to invalid IL or missing references) //IL_0883: Unknown result type (might be due to invalid IL or missing references) //IL_07d2: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Unknown result type (might be due to invalid IL or missing references) //IL_060b: Unknown result type (might be due to invalid IL or missing references) //IL_0615: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0620: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_0636: Unknown result type (might be due to invalid IL or missing references) //IL_063b: Unknown result type (might be due to invalid IL or missing references) //IL_064b: Unknown result type (might be due to invalid IL or missing references) //IL_0651: Unknown result type (might be due to invalid IL or missing references) //IL_0657: Unknown result type (might be due to invalid IL or missing references) //IL_065d: Unknown result type (might be due to invalid IL or missing references) //IL_0662: Unknown result type (might be due to invalid IL or missing references) //IL_06e9: Unknown result type (might be due to invalid IL or missing references) //IL_06fa: Unknown result type (might be due to invalid IL or missing references) //IL_06ff: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_05f8: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_09ec: Unknown result type (might be due to invalid IL or missing references) //IL_0a10: Unknown result type (might be due to invalid IL or missing references) //IL_0a15: Unknown result type (might be due to invalid IL or missing references) //IL_0733: Unknown result type (might be due to invalid IL or missing references) //IL_073d: Unknown result type (might be due to invalid IL or missing references) //IL_071a: Unknown result type (might be due to invalid IL or missing references) //IL_071f: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_12d4: Unknown result type (might be due to invalid IL or missing references) //IL_12d9: Unknown result type (might be due to invalid IL or missing references) //IL_12fd: Unknown result type (might be due to invalid IL or missing references) //IL_1302: Unknown result type (might be due to invalid IL or missing references) //IL_1390: Unknown result type (might be due to invalid IL or missing references) //IL_0a8b: Unknown result type (might be due to invalid IL or missing references) //IL_0a91: Unknown result type (might be due to invalid IL or missing references) //IL_0a9b: Unknown result type (might be due to invalid IL or missing references) //IL_0aa0: Unknown result type (might be due to invalid IL or missing references) //IL_0aab: Unknown result type (might be due to invalid IL or missing references) //IL_0ab5: Unknown result type (might be due to invalid IL or missing references) //IL_0aba: Unknown result type (might be due to invalid IL or missing references) //IL_0abf: Unknown result type (might be due to invalid IL or missing references) //IL_0ac2: Unknown result type (might be due to invalid IL or missing references) //IL_0ace: Unknown result type (might be due to invalid IL or missing references) //IL_0ad4: Unknown result type (might be due to invalid IL or missing references) //IL_0ade: Unknown result type (might be due to invalid IL or missing references) //IL_0ae3: Unknown result type (might be due to invalid IL or missing references) //IL_0aee: Unknown result type (might be due to invalid IL or missing references) //IL_0af8: Unknown result type (might be due to invalid IL or missing references) //IL_0b02: Unknown result type (might be due to invalid IL or missing references) //IL_0b07: Unknown result type (might be due to invalid IL or missing references) //IL_0b0c: Unknown result type (might be due to invalid IL or missing references) //IL_0b0f: Unknown result type (might be due to invalid IL or missing references) //IL_0b1b: Unknown result type (might be due to invalid IL or missing references) //IL_0b21: Unknown result type (might be due to invalid IL or missing references) //IL_0b2b: Unknown result type (might be due to invalid IL or missing references) //IL_0b35: Unknown result type (might be due to invalid IL or missing references) //IL_0b3a: Unknown result type (might be due to invalid IL or missing references) //IL_0b3f: Unknown result type (might be due to invalid IL or missing references) //IL_0b42: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04d0: Expected O, but got Unknown //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_0fd1: Unknown result type (might be due to invalid IL or missing references) //IL_0b56: Unknown result type (might be due to invalid IL or missing references) //IL_0b5b: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_0573: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_05a9: Unknown result type (might be due to invalid IL or missing references) //IL_0c6a: Unknown result type (might be due to invalid IL or missing references) //IL_0c6f: Unknown result type (might be due to invalid IL or missing references) //IL_0beb: Unknown result type (might be due to invalid IL or missing references) //IL_0bf0: Unknown result type (might be due to invalid IL or missing references) //IL_0c35: Unknown result type (might be due to invalid IL or missing references) //IL_0c3a: Unknown result type (might be due to invalid IL or missing references) //IL_0c47: Unknown result type (might be due to invalid IL or missing references) //IL_144c: Unknown result type (might be due to invalid IL or missing references) //IL_0d04: Unknown result type (might be due to invalid IL or missing references) //IL_0d0f: Unknown result type (might be due to invalid IL or missing references) //IL_0d19: Unknown result type (might be due to invalid IL or missing references) //IL_0d1e: Unknown result type (might be due to invalid IL or missing references) //IL_0d24: Unknown result type (might be due to invalid IL or missing references) //IL_0d50: Unknown result type (might be due to invalid IL or missing references) //IL_0d5b: Unknown result type (might be due to invalid IL or missing references) //IL_0d87: Unknown result type (might be due to invalid IL or missing references) //IL_0d8c: Unknown result type (might be due to invalid IL or missing references) //IL_0d91: Unknown result type (might be due to invalid IL or missing references) //IL_0d96: Unknown result type (might be due to invalid IL or missing references) //IL_0d99: Unknown result type (might be due to invalid IL or missing references) //IL_0d9a: Unknown result type (might be due to invalid IL or missing references) //IL_0e8f: Unknown result type (might be due to invalid IL or missing references) //IL_112e: Unknown result type (might be due to invalid IL or missing references) //IL_1139: Unknown result type (might be due to invalid IL or missing references) //IL_113e: Unknown result type (might be due to invalid IL or missing references) //IL_1143: Unknown result type (might be due to invalid IL or missing references) //IL_0e6f: Unknown result type (might be due to invalid IL or missing references) //IL_0e74: Unknown result type (might be due to invalid IL or missing references) //IL_0e3a: Unknown result type (might be due to invalid IL or missing references) //IL_0e3f: Unknown result type (might be due to invalid IL or missing references) //IL_0e4c: Unknown result type (might be due to invalid IL or missing references) //IL_11c0: Unknown result type (might be due to invalid IL or missing references) //IL_11c5: Unknown result type (might be due to invalid IL or missing references) //IL_11e5: Unknown result type (might be due to invalid IL or missing references) //IL_11ea: Unknown result type (might be due to invalid IL or missing references) if (((Character)player).GetSEMan().HaveStatusEffect(SE_FENRING_HASH)) { Process_FenringForm(player, altitude, ref playerBody); return; } new Random(); Vector3 val = default(Vector3); if (VL_Utility.Ability3_Input_Down) { if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability3_CD"))) { ValheimLegends.shouldUseGuardianPower = false; if (player.GetStamina() >= VL_Utility.GetRootCost && !ValheimLegends.isChanneling) { ValheimLegends.isChanneling = true; ValheimLegends.channelingBlocksMovement = false; StatusEffect val2 = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD)); val2.m_ttl = VL_Utility.GetRootCooldownTime; ((Character)player).GetSEMan().AddStatusEffect(val2, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetRootCost); player.StartEmote("point", true); float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.ConjurationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddStamina(0) / 200f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); rootCount = 0; rootCountTrigger = 16 - Mathf.RoundToInt(0.05f * num - 7.5f * (LevelSystem.Instance.getAddMagicDamage(0) / 80f)); rootTotal = 0; Vector3 val3 = ((Component)player).transform.right * 2.5f; if (Random.Range(0f, 1f) < 0.5f) { val3 *= -1f; } val = ((Component)player).transform.position + ((Component)player).transform.up * 3f + ((Character)player).GetLookDir() * 2f + val3; GO_Root = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("gdking_root_projectile"), new Vector3(val.x, val.y, val.z), Quaternion.identity); P_Root = GO_Root.GetComponent<Projectile>(); ((Object)P_Root).name = "VL_DruidRoot"; P_Root.m_respawnItemOnHit = false; P_Root.m_spawnOnHit = null; P_Root.m_ttl = 35f; P_Root.m_gravity = 0f; P_Root.m_rayRadius = 0.1f; Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill); Vector3 lookDir = ((Character)player).GetLookDir(); if (((Vector3)(ref lookDir)).sqrMagnitude > 1E-06f) { ((Component)P_Root).transform.localRotation = Quaternion.LookRotation(((Character)player).GetLookDir()); } GO_Root.transform.localScale = Vector3.one * 1.5f; ((Character)player).RaiseSkill(ValheimLegends.ConjurationSkill, VL_Utility.GetRootSkillGain); } else { ((Character)player).Message((MessageType)1, "Not enough stamina to channel Root: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRootCost + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else if (VL_Utility.Ability3_Input_Pressed && player.GetStamina() > VL_Utility.GetRootCostPerUpdate && ValheimLegends.isChanneling) { rootCount++; VL_Utility.SetTimer(); ((Character)player).UseStamina(VL_Utility.GetRootCostPerUpdate * (float)rootTotal); ValheimLegends.isChanneling = true; if (rootCount < rootCountTrigger) { return; } ((Character)player).RaiseSkill(ValheimLegends.ConjurationSkill, 0.06f); float num2 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.ConjurationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddStamina(0) / 200f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); rootCount = 0; if ((Object)(object)GO_Root != (Object)null && (Object)(object)GO_Root.transform != (Object)null) { RaycastHit val4 = default(RaycastHit); Vector3 position = ((Component)player).transform.position; Vector3 val5 = ((!Physics.Raycast(((Character)player).GetEyePoint(), ((Character)player).GetLookDir(), ref val4, float.PositiveInfinity, Script_Layermask) || !Object.op_Implicit((Object)(object)((RaycastHit)(ref val4)).collider)) ? (position + ((Character)player).GetLookDir() * 1000f) : ((RaycastHit)(ref val4)).point); HitData val6 = new HitData(); val6.m_damage.m_pierce = Random.Range(10f + 0.6f * num2, 15f + 1.2f * num2) * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidVines; val6.m_pushForce = 2f; rootTotal++; Vector3 val7 = Vector3.MoveTowards(GO_Root.transform.position, val5, 1f); if ((Object)(object)P_Root != (Object)null && ((Object)P_Root).name == "VL_DruidRoot") { P_Root.Setup((Character)(object)player, (val7 - GO_Root.transform.position) * 75f, -1f, val6, (ItemData)null, (ItemData)null); Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill); } } GO_Root = null; Vector3 val8 = ((Component)player).transform.right * 2.5f; if (Random.Range(0f, 1f) < 0.5f) { val8 *= -1f; } val = ((Component)player).transform.position + ((Component)player).transform.up * 3f + ((Character)player).GetLookDir() * 2f + val8; GO_Root = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("gdking_root_projectile"), new Vector3(val.x, val.y, val.z), Quaternion.identity); P_Root = GO_Root.GetComponent<Projectile>(); ((Object)P_Root).name = "VL_DruidRoot"; P_Root.m_respawnItemOnHit = false; P_Root.m_spawnOnHit = null; P_Root.m_ttl = rootCountTrigger + 1; P_Root.m_gravity = 0f; P_Root.m_rayRadius = 0.1f; Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill); Vector3 lookDir2 = ((Character)player).GetLookDir(); if (((Vector3)(ref lookDir2)).sqrMagnitude > 1E-06f) { ((Component)P_Root).transform.localRotation = Quaternion.LookRotation(((Character)player).GetLookDir()); } GO_Root.transform.localScale = Vector3.one * 1.5f; } else if ((VL_Utility.Ability3_Input_Up || player.GetStamina() <= VL_Utility.GetRootCostPerUpdate) && ValheimLegends.isChanneling) { if ((Object)(object)GO_Root != (Object)null && (Object)(object)GO_Root.transform != (Object)null) { RaycastHit val9 = default(RaycastHit); Vector3 position2 = ((Component)player).transform.position; Vector3 val10 = ((!Physics.Raycast(((Character)player).GetEyePoint(), ((Character)player).GetLookDir(), ref val9, float.PositiveInfinity, Script_Layermask) || !Object.op_Implicit((Object)(object)((RaycastHit)(ref val9)).collider)) ? (position2 + ((Character)player).GetLookDir() * 1000f) : ((RaycastHit)(ref val9)).point); HitData val11 = new HitData(); val11.m_damage.m_pierce = 10f; val11.m_pushForce = 10f; val11.SetAttacker((Character)(object)player); Vector3 val12 = Vector3.MoveTowards(GO_Root.transform.position, val10, 1f); P_Root.Setup((Character)(object)player, (val12 - GO_Root.transform.position) * 65f, -1f, val11, (ItemData)null, (ItemData)null); Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill); } rootTotal = 0; GO_Root = null; ValheimLegends.isChanneling = false; ValheimLegends.channelingBlocksMovement = true; } else if (VL_Utility.Ability2_Input_Down) { if (((Character)player).IsBlocking()) { TryActivate_FenringForm(player); } else if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability2_CD"))) { if (player.GetStamina() >= VL_Utility.GetDefenderCost) { Vector3 lookDir3 = ((Character)player).GetLookDir(); lookDir3.y = 0f; ((Component)player).transform.rotation = Quaternion.LookRotation(lookDir3); ValheimLegends.shouldUseGuardianPower = false; StatusEffect val13 = (StatusEffect)(object)(SE_Ability2_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability2_CD)); val13.m_ttl = VL_Utility.GetDefenderCooldownTime; ((Character)player).GetSEMan().AddStatusEffect(val13, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetDefenderCost); float num3 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.ConjurationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddStamina(0) / 200f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetTrigger("gpower"); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)player).transform.position, Quaternion.identity); GameObject prefab = ZNetScene.instance.GetPrefab("TentaRoot"); CharacterTimedDestruction component = prefab.GetComponent<CharacterTimedDestruction>(); if ((Object)(object)component != (Object)null) { component.m_timeoutMin = 24f + 0.3f * num3; component.m_timeoutMax = component.m_timeoutMin; component.m_triggerOnAwake = true; ((Behaviour)component).enabled = true; } List<Vector3> list = new List<Vector3>(); list.Clear(); val = ((Component)player).transform.position + ((Character)player).GetLookDir() * 5f + ((Component)player).transform.right * 5f; list.Add(val); val = ((Component)player).transform.position + ((Character)player).GetLookDir() * 5f + ((Component)player).transform.right * 5f * -1f; list.Add(val); val = ((Component)player).transform.position + ((Character)player).GetLookDir() * 5f * -1f; list.Add(val); for (int i = 0; i < list.Count; i++) { GO_RootDefender = Object.Instantiate<GameObject>(prefab, list[i], Quaternion.identity); Character component2 = GO_RootDefender.GetComponent<Character>(); if ((Object)(object)component2 != (Object)null) { SE_RootsBuff sE_RootsBuff = (SE_RootsBuff)(object)ScriptableObject.CreateInstance(typeof(SE_RootsBuff)); ((StatusEffect)sE_RootsBuff).m_ttl = SE_RootsBuff.m_baseTTL; sE_RootsBuff.damageModifier = 0.5f + 0.015f * num3 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidDefenders; sE_RootsBuff.staminaRegen = 0.5f + 0.05f * num3; sE_RootsBuff.summoner = player; sE_RootsBuff.centerPoint = ((Component)player).transform.position; component2.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_RootsBuff, false, 0, 0f); component2.SetMaxHealth(30f + 6f * num3); ((Component)component2).transform.localScale = (0.75f + 0.005f * num3) * Vector3.one; component2.m_faction = (Faction)0; component2.SetTamed(true); } Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)component2).transform.position, Quaternion.identity); } GameObject prefab2 = ZNetScene.instance.GetPrefab("VL_Deathsquit"); CharacterTimedDestruction component3 = prefab2.GetComponent<CharacterTimedDestruction>(); if ((Object)(object)component3 != (Object)null) { component3.m_timeoutMin = 24f + 0.3f * num3; component3.m_timeoutMax = component3.m_timeoutMin; component3.m_triggerOnAwake = true; ((Behaviour)component3).enabled = true; } int num4 = 2 + Mathf.RoundToInt(0.05f * num3); for (int j = 0; j < num4; j++) { val = ((Component)player).transform.position + ((Component)player).transform.up * 4f + (((Character)player).GetLookDir() * Random.Range(0f - (5f + 0.1f * num3), 5f + 0.1f * num3) + ((Component)player).transform.right * Random.Range(0f - (5f + 0.1f * num3), 5f + 0.1f * num3)); Character component4 = Object.Instantiate<GameObject>(prefab2, val, Quaternion.identity).GetComponent<Character>(); component4.m_name = "Drusquito"; if ((Object)(object)component4 != (Object)null) { SE_Companion sE_Companion = (SE_Companion)(object)ScriptableObject.CreateInstance(typeof(SE_Companion)); ((StatusEffect)sE_Companion).m_ttl = 60f; sE_Companion.damageModifier = 0.05f + 0.0075f * num3 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidDefenders; sE_Companion.summoner = player; component4.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Companion, false, 0, 0f); ((Component)component4).transform.localScale = (0.4f + 0.005f * num3) * Vector3.one; component4.m_faction = (Faction)0; component4.SetTamed(true); } Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_float_hitwater"), ((Component)component4).transform.position, Quaternion.identity); } ((Character)player).RaiseSkill(ValheimLegends.ConjurationSkill, VL_Utility.GetDefenderSkillGain); } else { ((Character)player).Message((MessageType)1, "Not enough stamina to summon root defenders: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetDefenderCost + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else if (VL_Utility.Ability1_Input_Down) { if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability1_CD"))) { if (((Character)player).IsBlocking()) { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } int requiredAmount = 1; string text = "AncientSeed"; ItemData val14 = VL_Utility.FindItemByPrefabName(inventory, text, requiredAmount); if (val14 == null) { ((Character)player).Message((MessageType)2, "You need an Ancient Seed to create a Spirit Binding Vial.", 0, (Sprite)null); return; } if (player.GetStamina() < VL_Utility.GetRegenerationCost) { ((Character)player).Message((MessageType)1, "Not enough stamina to Create Spirit Binding Vial: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRegenerationCost.ToString("#.#") + ")", 0, (Sprite)null); return; } ((Character)player).RaiseSkill(ValheimLegends.AlterationSkill, VL_Utility.GetRegenerationSkillGain); StatusEffect val15 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD)); float num5 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance(0) / 40f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); val15.m_ttl = VL_Utility.GetHealCooldownTime * 20f / (1f + num5 / 150f); ((Character)player).GetSEMan().AddStatusEffect(val15, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetRegenerationCost); inventory.RemoveOneItem(val14); if ((Object)(object)ZNetScene.instance == (Object)null) { Debug.Log((object)"ZNetScene not ready."); return; } GameObject prefab3 = ZNetScene.instance.GetPrefab("questitem_wraiths_breath"); if ((Object)(object)prefab3 == (Object)null) { Debug.Log((object)"Prefab not found: questitem_wraiths_breath"); return; } ItemDrop component5 = prefab3.GetComponent<ItemDrop>(); if ((Object)(object)component5 == (Object)null) { Debug.Log((object)"Prefab has no ItemDrop: questitem_wraiths_breath"); return; } ItemData val16 = component5.m_itemData.Clone(); if (!inventory.AddItem(val16)) { ItemDrop.DropItem(val16, 1, ((Component)player).transform.position + ((Component)player).transform.forward, Quaternion.identity); ((Character)player).Message((MessageType)1, "Inventory full. Dropped Spirit Binding Vial on the ground.", 0, (Sprite)null); } else { ((Character)player).Message((MessageType)1, "Consumed 1 " + text + " to create a " + val16.m_shared.m_name + ".", 0, (Sprite)null); } player.StartEmote("cheer", true); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)player).transform.position, Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)player).transform.position, Quaternion.identity); } else if (player.GetStamina() >= VL_Utility.GetRegenerationCost) { StatusEffect val17 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD)); val17.m_ttl = VL_Utility.GetRegenerationCooldownTime; ((Character)player).GetSEMan().AddStatusEffect(val17, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetRegenerationCost); float num6 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance(0) / 40f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); player.StartEmote("cheer", true); GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_guardstone_permitted_add"), ((Character)player).GetCenterPoint(), Quaternion.identity); GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)player).transform.position, Quaternion.identity); SE_Regeneration sE_Regeneration = (SE_Regeneration)(object)ScriptableObject.CreateInstance(typeof(SE_Regeneration)); ((StatusEffect)sE_Regeneration).m_ttl = SE_Regeneration.m_baseTTL; ((StatusEffect)sE_Regeneration).m_icon = ZNetScene.instance.GetPrefab("TrophyGreydwarfShaman").GetComponent<ItemDrop>().m_itemData.GetIcon(); sE_Regeneration.m_HealAmount = 0.5f + 0.4f * num6 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidRegen; sE_Regeneration.doOnce = false; List<Character> list2 = new List<Character>(); list2.Clear(); Character.GetCharactersInRange(((Character)player).GetCenterPoint(), 30f + 0.2f * num6, list2); foreach (Character item in list2) { if (!BaseAI.IsEnemy((Character)(object)player, item)) { if ((Object)(object)item == (Object)(object)Player.m_localPlayer) { item.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Regeneration, true, 0, 0f); } else if (item.IsPlayer()) { item.GetSEMan().AddStatusEffect(StringExtensionMethods.GetStableHashCode(((Object)sE_Regeneration).name), true, 0, 0f); } else { item.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Regeneration, true, 0, 0f); } } } ((Character)player).RaiseSkill(ValheimLegends.AlterationSkill, VL_Utility.GetRegenerationSkillGain); } else { ((Character)player).Message((MessageType)1, "Not enough stamina to for Regeneration: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRegenerationCost + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else { ValheimLegends.isChanneling = false; ValheimLegends.channelingBlocksMovement = true; } } public static void TryActivate_HumanForm(Player player, bool forced) { //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan == null) { return; } bool flag = sEMan.HaveStatusEffect(SE_FENRING_HASH); bool flag2 = sEMan.HaveStatusEffect(SE_CULTIST_HASH); if (!flag && !flag2) { ((Character)player).Message((MessageType)1, "Already human.", 0, (Sprite)null); return; } float getDefenderCost = VL_Utility.GetDefenderCost; if (!forced) { if (player.GetStamina() < getDefenderCost) { ((Character)player).Message((MessageType)1, $"Not enough stamina: ({player.GetStamina():#.#}/{getDefenderCost:#.#})", 0, (Sprite)null); return; } if (sEMan.HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Shapeshift_CD"))) { ((Character)player).Message((MessageType)1, "Can't shapeshift again yet.", 0, (Sprite)null); return; } } else { ((Character)player).Message((MessageType)1, "Ran out of Eitr to sustain the shapeshifting.", 0, (Sprite)null); } StatusEffect val = (StatusEffect)(object)(SE_Shapeshift_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Shapeshift_CD)); float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance(0) / 40f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); val.m_ttl = 180f - 60f * (num / 150f) - 60f * (LevelSystem.Instance.getAddMagicDamage(0) / 80f); if (!forced) { val.m_ttl = 30f - 14.25f * (num / 150f) - 14.25f * (LevelSystem.Instance.getAddMagicDamage(0) / 80f); ((Character)player).UseStamina(getDefenderCost); } sEMan.AddStatusEffect(val, false, 0, 0f); if (flag) { sEMan.RemoveStatusEffect(SE_FENRING_HASH, false); } if (flag2) { sEMan.RemoveStatusEffect(SE_CULTIST_HASH, false); } ForceWeaponRefresh(player); ValheimLegends.NameCooldowns(); if (ValheimLegends.abilitiesStatus != null) { foreach (RectTransform item in ValheimLegends.abilitiesStatus) { if ((Object)(object)((Component)item).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)item).gameObject); } } ValheimLegends.abilitiesStatus.Clear(); } ValheimLegends.shouldUseGuardianPower = false; ZSyncAnimation val2 = (ZSyncAnimation)(typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(player)); if ((int)val2 != 0) { val2.SetTrigger("gpower"); } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab("vfx_odin_despawn"); if (Object.op_Implicit((Object)(object)prefab)) { Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity); } prefab = ZNetScene.instance.GetPrefab("sfx_wraith_death"); if (Object.op_Implicit((Object)(object)prefab)) { Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity); } } } private static void TryActivate_FenringForm(Player player) { //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: 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_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan == null) { return; } if (sEMan.HaveStatusEffect(SE_FENRING_HASH)) { TryActivate_HumanForm(player, forced: false); return; } if (sEMan.HaveStatusEffect(SE_CULTIST_HASH)) { ((Character)player).Message((MessageType)1, "Already transformed (Cultist).", 0, (Sprite)null); return; } float getDefenderCost = VL_Utility.GetDefenderCost; if (player.GetStamina() < getDefenderCost) { ((Character)player).Message((MessageType)1, $"Not enough stamina: ({player.GetStamina():#.#}/{getDefenderCost:#.#})", 0, (Sprite)null); return; } if (sEMan.HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Shapeshift_CD"))) { ((Character)player).Message((MessageType)1, "Can't shapeshift again yet.", 0, (Sprite)null); return; } StatusEffect val = (StatusEffect)(object)(SE_Shapeshift_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Shapeshift_CD)); float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance(0) / 40f + LevelSystem.Instance.getAddMagicDamage(0) / 80f, 0f, 0.5f)); val.m_ttl = 30f - 14.25f * (num / 150f) - 14.25f * (LevelSystem.Instance.getAddMagicDamage(0) / 80f); sEMan.AddStatusEffect(val, false, 0, 0f); ((Character)player).UseStamina(getDefenderCost); SE_DruidFenringForm sE_DruidFenringForm = (SE_DruidFenringForm)(object)ScriptableObject.CreateInstance(typeof(SE_DruidFenringForm)); sEMan.AddStatusEffect((StatusEffect)(object)sE_DruidFenringForm, false, 0, 0f); ValheimLegends.NameCooldowns(); if (ValheimLegends.abilitiesStatus != null) { foreach (RectTransform item in ValheimLegends.abilitiesStatus) { if ((Object)(object)((Component)item).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)item).gameObject); } } ValheimLegends.abilitiesStatus.Clear(); } ValheimLegends.shouldUseGuardianPower = false; ZSyncAnimation val2 = (ZSyncAnimation)(typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(player)); if ((int)val2 != 0) { val2.SetTrigger("gpower"); } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab("vfx_odin_despawn"); if (Object.op_Implicit((Object)(object)prefab)) { Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity); } prefab = ZNetScene.instance.GetPrefab("sfx_wraith_death"); if (Object.op_Implicit((Object)(object)prefab)) { Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity); } } } private static void TryActivate_CultistForm(Player player) { //IL_00aa: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan == null) { return; } if (sEMan.HaveStatusEffect(SE_FENRING_HASH) || sEMan.HaveStatusEffect(SE_CULTIST_HASH)) { ((Character)player).Message((MessageType)1, "Already transformed.", 0, (Sprite)null); return; } float getDefenderCost = VL_Utility.GetDefenderCost; if (player.GetStamina() < getDefenderCost) { ((Character)player).Message((MessageType)1, $"Not enough stamina: ({player.GetStamina():#.#}/{getDefenderCost})", 0, (Sprite)null); return; } ((Character)player).UseStamina(getDefenderCost); SE_DruidCultistForm sE_DruidCultistForm = (SE_DruidCultistForm)(object)ScriptableObject.CreateInstance(typeof(SE_DruidCultistForm)); ((StatusEffect)sE_DruidCultistForm).m_ttl = SE_DruidCultistForm.BaseTTL; ValheimLegends.shouldUseGuardianPower = false; Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_odin_despawn"), ((Component)player).transform.position, Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_wraith_death"), ((Component)player).transform.position, Quaternion.identity); sEMan.AddStatusEffect((StatusEffect)(object)sE_DruidCultistForm, true, 0, 0f); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("gpower"); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetSpeed(2f); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_odin_despawn"), ((Component)player).transform.position, Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_wraith_death"), ((Component)player).transform.position, Quaternion.identity); ((Character)player).Message((MessageType)1, "Transformed: Cultist Form", 0, (Sprite)null); } public static ItemData GetRightItemSafe(Player player) { if ((Object)(object)player == (Object)null) { return null; } try { if (MI_GetRightItem != null) { object? obj = MI_GetRightItem.Invoke(player, null); return (ItemData)((obj is ItemData) ? obj : null); } } catch { } try { if (FI_RightItem != null) { object? value = FI_RightItem.GetValue(player); return (ItemData)((value is ItemData) ? value : null); } } catch { } try { return ((Humanoid)player).GetCurrentWeapon(); } catch { return null; } } private static ItemData GetLeftItemSafe(Player player) { if ((Object)(object)player == (Object)null) { return null; } try { if (MI_GetLeftItem != null) { object? obj = MI_GetLeftItem.Invoke(player, null); return (ItemData)((obj is ItemData) ? obj : null); } } catch { } try { if (FI_LeftItem != null) { object? value = FI_LeftItem.GetValue(player); return (ItemData)((value is ItemData) ? value : null); } } catch { } return null; } private static void ForceWeaponRefresh(Player player) { if ((Object)(object)player == (Object)null) { return; } ZNetView component = ((Component)player).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsOwner()) { return; } ItemData rightItemSafe = GetRightItemSafe(player); ItemData leftItemSafe = GetLeftItemSafe(player); if (rightItemSafe != null) { ((Humanoid)player).UnequipItem(rightItemSafe, true); ((Humanoid)player).EquipItem(rightItemSafe, true); return; } if (leftItemSafe != null) { ((Humanoid)player).UnequipItem(leftItemSafe, true); ((Humanoid)player).EquipItem(leftItemSafe, true); return; } try { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } ItemData val = null; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null && allItem.IsEquipable()) { val = allItem; if (((Humanoid)player).EquipItem(val, true)) { ((Humanoid)player).UnequipItem(val, true); break; } val = null; } } } catch (Exception ex) { Debug.LogWarning((object)("[VL] ForceWeaponRefresh inventory fallback failed: " + ex)); } } } public class Class_Duelist { private static int ScriptChar_Layermask = LayerMask.GetMask(new string[11] { "Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle", "piece", "viewblock", "character", "character_net", "character_ghost" }); private static GameObject GO_CastFX; private static GameObject GO_QuickShot; private static Projectile P_QuickShot; public static ItemDrop coinsItem; public static List<int> challengedDeath = new List<int>(); public static List<int> challengedMastery = new List<int>(); public static void Execute_Slash(Player player) { //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_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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_017c: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //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_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: 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_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_BlinkStrike"), ((Character)player).GetCenterPoint() + ((Character)player).GetLookDir() * 3f, Quaternion.LookRotation(((Character)player).GetLookDir())); float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f)); float num2 = (1.25f + num / 300f) * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_duelistSeismicSlash; Vector3 forward = ((Component)player).transform.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); float num3 = 7f; float num4 = Mathf.Cos(90f * 0.5f * (MathF.PI / 180f)); List<Character> list = new List<Character>(); Character.GetCharactersInRange(((Component)player).transform.position, num3, list); foreach (Character item in list) { if (!BaseAI.IsEnemy((Character)(object)player, item)) { continue; } Vector3 val = ((Component)item).transform.position - ((Component)player).transform.position; val.y = 0f; if (((Vector3)(ref val)).magnitude > num3) { continue; } ((Vector3)(ref val)).Normalize(); if (Vector3.Dot(forward, val) < num4 || !VL_Utility.LOS_IsValid(item, item.GetEyePoint(), ((Character)player).GetEyePoint())) { continue; } HitData val2 = new HitData(); val2.m_damage = ((Humanoid)player).GetCurrentWeapon().GetDamage(); val2.ApplyModifier(Random.Range(1.8f, 2.2f) * num2); val2.m_pushForce = 25f + 0.1f * num; val2.m_point = item.GetEyePoint(); val2.m_dir = forward; val2.m_skill = ValheimLegends.DisciplineSkill; item.Damage(val2); if (challengedMastery.Contains(((Object)item).GetInstanceID())) { challengedMastery.Remove(((Object)item).GetInstanceID()); int num5 = Mathf.CeilToInt(Mathf.Sqrt(item.GetMaxHealth()) + (1f + LevelSystem.Instance.getAddCriticalChance(0) / 40f) * Mathf.Sqrt(item.GetMaxHealth())); if (((Humanoid)player).GetInventory().CanAddItem(ValheimLegends.coinsItem.m_itemData.m_dropPrefab, num5)) { ((Humanoid)player).GetInventory().AddItem(ValheimLegends.coinsItem.m_itemData.m_dropPrefab, num5); } else { ItemDrop.DropItem(ValheimLegends.coinsItem.m_itemData, num5, ((Component)player).transform.position, Quaternion.identity); } ((Character)player).Message((MessageType)1, $"Spoiled {num5:#} coins from {item.GetHoverName()}!", 0, (Sprite)null); } } } public static void Process_Input(Player player, ref Rigidbody playerBody) { //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05c0: Unknown result type (might be due to invalid IL or missing references) //IL_05c5: Unknown result type (might be due to invalid IL or missing references) //IL_0609: 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_00d2: Invalid comparison between Unknown and I4 //IL_0729: Unknown result type (might be due to invalid IL or missing references) //IL_0735: Unknown result type (might be due to invalid IL or missing references) //IL_073c: Unknown result type (might be due to invalid IL or missing references) //IL_0747: 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_00e8: Invalid comparison between Unknown and I4 //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Invalid comparison between Unknown and I4 //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Invalid comparison between Unknown and I4 //IL_07ee: Unknown result type (might be due to invalid IL or missing references) //IL_07f5: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Invalid comparison between Unknown and I4 //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0e4e: Unknown result type (might be due to invalid IL or missing references) //IL_0e72: Unknown result type (might be due to invalid IL or missing references) //IL_0e77: Unknown result type (might be due to invalid IL or missing references) //IL_0e8c: Unknown result type (might be due to invalid IL or missing references) //IL_0e97: Unknown result type (might be due to invalid IL or missing references) //IL_0ea1: Unknown result type (might be due to invalid IL or missing references) //IL_0ea6: Unknown result type (might be due to invalid IL or missing references) //IL_0eac: Unknown result type (might be due to invalid IL or missing references) //IL_0eb6: Unknown result type (might be due to invalid IL or missing references) //IL_0ebb: Unknown result type (might be due to invalid IL or missing references) //IL_0ec0: Unknown result type (might be due to invalid IL or missing references) //IL_0ed2: Unknown result type (might be due to invalid IL or missing references) //IL_0ed7: Unknown result type (might be due to invalid IL or missing references) //IL_0ef1: Unknown result type (might be due to invalid IL or missing references) //IL_0ef4: Unknown result type (might be due to invalid IL or missing references) //IL_0ef9: Unknown result type (might be due to invalid IL or missing references) //IL_0f17: Unknown result type (might be due to invalid IL or missing references) //IL_0f19: Unknown result type (might be due to invalid IL or missing references) //IL_0fa3: Unknown result type (might be due to invalid IL or missing references) //IL_0fa5: Unknown result type (might be due to invalid IL or missing references) //IL_0faa: Unknown result type (might be due to invalid IL or missing references) //IL_0fcd: Unknown result type (might be due to invalid IL or missing references) //IL_0fd9: Unknown result type (might be due to invalid IL or missing references) //IL_0fe0: Unknown result type (might be due to invalid IL or missing references) //IL_0fe6: Unknown result type (might be due to invalid IL or missing references) //IL_088e: Unknown result type (might be due to invalid IL or missing references) //IL_089a: Unknown result type (might be due to invalid IL or missing references) //IL_1016: Unknown result type (might be due to invalid IL or missing references) //IL_101c: Unknown result type (might be due to invalid IL or missing references) //IL_1026: Unknown result type (might be due to invalid IL or missing references) //IL_102b: Unknown result type (might be due to invalid IL or missing references) //IL_1030: Unknown result type (might be due to invalid IL or missing references) //IL_1032: Unknown result type (might be due to invalid IL or missing references) //IL_1039: Expected O, but got Unknown //IL_1098: Unknown result type (might be due to invalid IL or missing references) //IL_109d: Unknown result type (might be due to invalid IL or missing references) //IL_10a2: Unknown result type (might be due to invalid IL or missing references) //IL_10a4: Unknown result type (might be due to invalid IL or missing references) //IL_10ab: Unknown result type (might be due to invalid IL or missing references) //IL_10b0: Unknown result type (might be due to invalid IL or missing references) //IL_10b8: Unknown result type (might be due to invalid IL or missing references) //IL_10c4: Unknown result type (might be due to invalid IL or missing references) //IL_10c9: Unknown result type (might be due to invalid IL or missing references) //IL_10d3: Unknown result type (might be due to invalid IL or missing references) //IL_10fa: Unknown result type (might be due to invalid IL or missing references) //IL_1117: Unknown result type (might be due to invalid IL or missing references) //IL_100e: Unknown result type (might be due to invalid IL or missing references) //IL_0a3c: Unknown result type (might be due to invalid IL or missing references) //IL_0a41: Unknown result type (might be due to invalid IL or missing references) //IL_0a5d: Unknown result type (might be due to invalid IL or missing references) //IL_0a62: Unknown result type (might be due to invalid IL or missing references) //IL_09f8: Unknown result type (might be due to invalid IL or missing references) //IL_09fd: Unknown result type (might be due to invalid IL or missing references) //IL_0a19: Unknown result type (might be due to invalid IL or missing references) //IL_0a1e: Unknown result type (might be due to invalid IL or missing references) //IL_0b5b: Unknown result type (might be due to invalid IL or missing references) new Random(); if (VL_Utility.Ability3_Input_Down) { if (challengedDeath == null) { challengedDeath = new List<int>(); challengedDeath.Clear(); } if (challengedDeath.Count > 50) { challengedDeath.Clear(); } if (challengedMastery == null) { challengedMastery = new List<int>(); challengedMastery.Clear(); } if (challengedMastery.Count > 50) { challengedMastery.Clear(); } if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability3_CD"))) { if (((Character)player).IsBlocking()) { if (Traverse.Create((object)player).Field("m_leftItem").GetValue<ItemData>() == null && ((Humanoid)player).GetCurrentWeapon() != null && (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_itemType != 14 && ((int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 1 || (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 2 || (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 7 || (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 5)) { float num = ((Humanoid)player).GetCurrentWeapon().GetMaxDurability() * (1f - ((Humanoid)player).GetCurrentWeapon().GetDurabilityPercentage()); if (num > 0f) { float num2 = num * 4f * (1f - LevelSystem.Instance.getStaminaReduction(0) / 100f); float num3 = num; if (player.GetStamina() < num2) { num3 = player.GetStamina() / (4f * (1f - LevelSystem.Instance.getStaminaReduction(0) / 100f)); } float num4 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f)); StatusEffect val = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD)); val.m_ttl = 60f + num3 * 2f * (1f - LevelSystem.Instance.getAddCriticalChance(0) / 40f); ((Character)player).GetSEMan().AddStatusEffect(val, false, 0, 0f); ((Character)player).UseStamina(num3 * 10f * (1f - LevelSystem.Instance.getAddCriticalChance(0) / 40f) * (1f - num4 / 300f)); ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); currentWeapon.m_durability += num3; Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_BlinkStrike"), ((Character)player).GetCenterPoint() + ((Character)player).GetLookDir() * 3f, Quaternion.LookRotation(((Character)player).GetLookDir())); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("knife_stab1"); ((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetBlinkStrikeSkillGain); } else { ((Character)player).Message((MessageType)1, "You don't need to Sharpen you weapon.", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "You can only Sharpen an equipped bladed single one-handed weapon (swords, knives, axes or spears).", 0, (Sprite)null); } } else if (player.GetStamina() >= VL_Utility.GetBlinkStrikeCost) { StatusEffect val2 = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD)); val2.m_ttl = VL_Utility.GetBlinkStrikeCooldownTime; ((Character)player).GetSEMan().AddStatusEffect(val2, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetBlinkStrikeCost); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("knife_stab1"); ValheimLegends.isChanneling = true; ValheimLegends.isChargingDash = true; ValheimLegends.dashCounter = 0; ((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetBlinkStrikeSkillGain); } else { ((Character)player).Message((MessageType)1, "Not enough stamina for S. Slash : (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetBlinkStrikeCost + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else if (VL_Utility.Ability2_Input_Down) { if (challengedDeath == null) { challengedDeath = new List<int>(); challengedDeath.Clear(); } if (challengedDeath.Count > 50) { challengedDeath.Clear(); } if (challengedMastery == null) { challengedMastery = new List<int>(); challengedMastery.Clear(); } if (challengedMastery.Count > 50) { challengedMastery.Clear(); } if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability2_CD"))) { if (player.GetStamina() >= VL_Utility.GetRiposteCost) { StatusEffect val3 = (StatusEffect)(object)(SE_Ability2_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability2_CD)); val3.m_ttl = VL_Utility.GetRiposteCooldownTime; ((Character)player).GetSEMan().AddStatusEffect(val3, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetRiposteCost); _ = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level; Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f); GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_perfectblock"), ((Component)player).transform.position, Quaternion.identity); GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_backstab"), ((Character)player).GetCenterPoint(), Quaternion.identity); SE_Riposte sE_Riposte = (SE_Riposte)(object)ScriptableObject.CreateInstance(typeof(SE_Riposte)); sE_Riposte.playerBody = playerBody; ((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Riposte, false, 0, 0f); ((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetRiposteSkillGain); } else { ((Character)player).Message((MessageType)1, "Not enough stamina for Riposte: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRiposteCost + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null); } } else if (VL_Utility.Ability1_Input_Down) { if (challengedDeath == null) { challengedDeath = new List<int>(); challengedDeath.Clear(); } if (challengedDeath.Count > 50) { challengedDeath.Clear(); } if (challengedMastery == null) { challengedMastery = new List<int>(); challengedMastery.Clear(); } if (challengedMastery.Count > 50) { challengedMastery.Clear(); } if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability1_CD"))) { ValheimLegends.DefineCoins(); if (!((Object)(object)ValheimLegends.coinsItem != (Object)null)) { return; } if (((Character)player).IsBlocking()) { RaycastHit val4 = default(RaycastHit); _ = ((Component)player).transform.position; Physics.SphereCast(((Character)player).GetEyePoint(), 0.2f, ((Character)player).GetLookDir(), ref val4, 200f, ScriptChar_Layermask); VL_Utility.SetTimer(); if ((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null && (Object)(object)((Component)((RaycastHit)(ref val4)).collider).gameObject != (Object)null) { Character val5 = null; ((Component)((RaycastHit)(ref val4)).collider).gameObject.TryGetComponent<Character>(ref val5); bool flag = (Object)(object)val5 != (Object)null; List<Component> list = new List<Component>(); list.Clear(); ((Component)((RaycastHit)(ref val4)).collider).gameObject.GetComponents<Component>(list); if ((Object)(object)val5 == (Object)null) { val5 = (Character)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(typeof(Character)); flag = (Object)(object)val5 != (Object)null; if ((Object)(object)val5 == (Object)null) { val5 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInChildren<Character>(); flag = (Object)(object)val5 != (Object)null; } } if (flag && !val5.IsPlayer()) { int instanceID = ((Object)val5).GetInstanceID(); if ((challengedDeath != null && challengedDeath.Contains(instanceID)) || (challengedMastery != null && challengedMastery.Contains(instanceID))) { ((Character)player).Message((MessageType)1, val5.GetHoverName() + " was already challenged!", 0, (Sprite)null); } else if (Vector3.Distance(((Component)player).transform.position, ((Component)val5).transform.position) <= 70f) { if (player.GetStamina() >= VL_Utility.GetQuickShotCost) { int num5 = Mathf.CeilToInt(Mathf.Sqrt(val5.GetMaxHealth())); if (((Humanoid)player).GetInventory() != null && ((Humanoid)player).GetInventory().HaveItem(ValheimLegends.coinsItem.m_itemData.m_shared.m_name, true) && ((Humanoid)player).GetInventory().CountItems("$item_coins", -1, true) >= num5) { ItemData val6 = null; ItemData val7 = null; for (int i = 0; i < ((Humanoid)player).GetInventory().GetHeight(); i++) { if (val7 != null) { break; } for (int j = 0; j < ((Humanoid)player).GetInventory().GetWidth(); j++) { val6 = ((Humanoid)player).GetInventory().GetItemAt(j, i); if (val6 != null) { if (val6.m_shared.m_name == "$item_coins" && ((Humanoid)player).GetInventory().GetItemAt(j, i).m_stack >= num5) { val7 = val6; } if (val7 != null) { break; } } } } for (int k = 0; k < num5; k++) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Humanoid)localPlayer).GetInventory().RemoveOneItem(val7); } } ((Character)player).UseStamina(VL_Utility.GetQuickShotCost); if (num5 < LevelSystem.Instance.getLevel()) { Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_destroyed"), val5.GetCenterPoint(), Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_coin_stack_destroyed"), val5.GetCenterPoint(), Quaternion.identity); } else { Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_pile_destroyed"), val5.GetCenterPoint(), Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_coin_pile_destroyed"), val5.GetCenterPoint(), Quaternion.identity); } player.StartEmote("point", true); ((Character)player).Message((MessageType)1, "Challenged " + val5.GetHoverName() + " to a duel worth of " + num5.ToString("#") + " coins!", 0, (Sprite)null); if (val5.IsOwner()) { if (Random.value < 0.33f) { ((Character)player).Message((MessageType)2, "Duel of Mastery!", 1, ValheimLegends.RiposteIcon); challengedMastery.Add(((Object)val5).GetInstanceID()); } else { ((Character)player).Message((MessageType)2, "Duel to the Death!", 1, ZNetScene.instance.GetPrefab("TrophySkeleton").GetComponent<ItemDrop>().m_itemData.GetIcon()); challengedDeath.Add(((Object)val5).GetInstanceID()); } } else { ((Character)player).Message((MessageType)2, "Duel of Mastery!", 1, ValheimLegends.RiposteIcon); challengedMastery.Add(((Object)val5).GetInstanceID()); } ((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetQuickShotSkillGain); StatusEffect val8 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD)); val8.m_ttl = VL_Utility.GetQuickShotCooldownTime * 3f; ((Character)player).GetSEMan().AddStatusEffect(val8, false, 0, 0f); } else { ((Character)player).Message((MessageType)1, "You need " + num5.ToString("#") + " coins to challenge " + val5.GetHoverName() + ".", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Not enough stamina for Challenge: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetBackstabCost + ")", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, val5.GetHoverName() + " is too far away to challenge!", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "Invalid target", 0, (Sprite)null); } } else { ((Character)player).Message((MessageType)1, "No target", 0, (Sprite)null); } } else if (!((Character)player).GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Ability1_CD"))) { if (player.GetStamina() >= VL_Utility.GetQuickShotCost) { if (((Humanoid)player).GetInventory() != null && ((Humanoid)player).GetInventory().HaveItem(ValheimLegends.coinsItem.m_itemData.m_shared.m_name, true)) { ItemData val9 = null; ItemData val10 = null; for (int l = 0; l < ((Humanoid)player).GetInventory().GetHeight(); l++) { if (val10 != null) { break; } for (int m = 0; m < ((Humanoid)player).GetInventory().GetWidth(); m++) { val9 = ((Humanoid)player).GetInventory().GetItemAt(m, l); if (val9 != null) { if (val9.m_shared.m_name == "$item_coins" && ((Humanoid)player).GetInventory().GetItemAt(m, l).m_stack >= 0) { val10 = val9; } if (val10 != null) { break; } } } } Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Humanoid)localPlayer2).GetInventory().RemoveOneItem(val10); } float num6 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage(0) / 40f + LevelSystem.Instance.getAddAttackSpeed(0) / 40f, 0f, 0.5f)); StatusEffect val11 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD)); val11.m_ttl = VL_Utility.GetQuickShotCooldownTime; ((Character)player).GetSEMan().AddStatusEffect(val11, false, 0, 0f); ((Character)player).UseStamina(VL_Utility.GetQuickShotCost + 0.5f * num6); ((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("interact"); GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_smelter_add"), ((Component)player).transform.position, Quaternion.identity); Vector3 val12 = ((Component)player).transform.position + ((Component)player).transform.up * 1.2f + ((Character)player).GetLookDir() * 0.5f; Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_destroyed"), ((Character)player).GetCenterPoint(), Quaternion.identity); GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_Q