Decompiled source of Husky v1.0.7
Husky.dll
Decompiled 2 months 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using FetchAndRecall; using HarmonyLib; using Husky.Functions; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: AssemblyConfiguration("")] [assembly: Guid("A4E02C2C-E9F1-483B-A789-04A978B1DAF1")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("1.0.7")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/blacks7ar/Husky/")] [assembly: AssemblyProduct("Husky")] [assembly: AssemblyCompany("blacks7ar")] [assembly: AssemblyTitle("Husky")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.7.0")] [module: UnverifiableCode] [module: <5bab85c3-af5a-4891-ac7f-d09532d0492f>RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [<f30a2b2f-2d8c-462b-8d79-1bf63bec8304>Embedded] [CompilerGenerated] internal sealed class <f30a2b2f-2d8c-462b-8d79-1bf63bec8304>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [<f30a2b2f-2d8c-462b-8d79-1bf63bec8304>Embedded] [CompilerGenerated] internal sealed class <5bab85c3-af5a-4891-ac7f-d09532d0492f>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <5bab85c3-af5a-4891-ac7f-d09532d0492f>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FetchAndRecall { public class Recall : StatusEffect { public float m_maxDistance = 100f; public List<Character> m_companions = new List<Character>(); private readonly float[] _offSets = new float[6] { -80f, 80f, -60f, 60f, -30f, 30f }; public override void Setup(Character character) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) ((StatusEffect)this).Setup(character); m_companions.Clear(); List<Character> list = new List<Character>(); Character.GetCharactersInRange(((Component)character).transform.position, m_maxDistance, list); int num = 0; foreach (Character item in list.Where((Character pet) => pet.IsTamed() && ((Object)pet).name.Replace("(Clone)", "") == "BHP_Husky")) { num++; MonsterAI component = ((Component)item).GetComponent<MonsterAI>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.GetFollowTarget()) && (Object)(object)component.GetFollowTarget() == (Object)(object)((Component)character).gameObject) { m_companions.Add(item); } } } public override void UpdateStatusEffect(float dt) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) ((StatusEffect)this).UpdateStatusEffect(dt); int num = 0; foreach (Character companion in m_companions) { Vector3 val = Quaternion.AngleAxis(_offSets[num], Vector3.up) * ((Component)companion).transform.forward * 0.75f; Vector3 val2 = ((Component)base.m_character).transform.rotation * Vector3.forward; ((Component)companion).transform.position = ((Component)base.m_character).transform.position + val; ((Component)companion).transform.rotation = ((Component)base.m_character).transform.rotation; companion.SetLookDir(val2, 0f); num++; } } } } namespace Husky { [BepInPlugin("blacks7ar.Husky", "Husky", "1.0.7")] public class Plugin : BaseUnityPlugin { private const string modGUID = "blacks7ar.Husky"; public const string modName = "Husky"; public const string modAuthor = "blacks7ar"; public const string modVersion = "1.0.7"; public const string modLink = "https://valheim.thunderstore.io/package/blacks7ar/Husky/"; private static readonly Harmony _harmony = new Harmony("blacks7ar.Husky"); private static readonly ConfigSync _configSync = new ConfigSync("blacks7ar.Husky") { DisplayName = "Husky", CurrentVersion = "1.0.7", MinimumRequiredVersion = "1.0.7", ModRequired = true }; private static ConfigEntry<Toggle> _serverConfigLocked; public static ConfigEntry<bool> _boneToyEnable; public static ConfigEntry<string> _boneToyMat; public static ConfigEntry<bool> _pillEnable; public static ConfigEntry<string> _pillMat1; public static ConfigEntry<string> _pillMat2; public static ConfigEntry<string> _pillMat3; public static ConfigEntry<bool> _giftEnable; public static ConfigEntry<string> _giftMat1; public static ConfigEntry<string> _giftMat2; public static ConfigEntry<string> _giftMat3; public static ConfigEntry<string> _giftMat4; public static ConfigEntry<bool> _hornEnable; public static ConfigEntry<string> _hornMat1; public static ConfigEntry<string> _hornMat2; public static ConfigEntry<string> _hornMat3; public static AssetBundle _huskyBundle; public static GameObject _husky; public static GameObject _boneToy; public static GameObject _odinsGift; public static GameObject _healingPill; public static GameObject _horn; public static GameObject _vfxHit; public static GameObject _vfxDeath; public static GameObject _vfxWaterSurface; public static GameObject _fxFootstepWater; private static Localization english; private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedConfig = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedConfig ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); _configSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedConfig; return val2; } public void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Expected O, but got Unknown //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Expected O, but got Unknown //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Expected O, but got Unknown //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Expected O, but got Unknown Localizer.Load(); english = new Localization(); english.SetupLanguage("English"); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; _huskyBundle = GetAssetBundleFromResources("huskybundle"); _husky = _huskyBundle.LoadAsset<GameObject>("BHP_Husky"); ShaderReplacer.Replace(_husky); _boneToy = _huskyBundle.LoadAsset<GameObject>("BHP_BoneToy"); _odinsGift = _huskyBundle.LoadAsset<GameObject>("BHP_OdinsGift"); _healingPill = _huskyBundle.LoadAsset<GameObject>("BHP_HealingPill"); _horn = _huskyBundle.LoadAsset<GameObject>("BHP_Horn"); _vfxHit = _huskyBundle.LoadAsset<GameObject>("bhp_vfx_wolf_hit"); ShaderReplacer.Replace(_vfxHit); _vfxDeath = _huskyBundle.LoadAsset<GameObject>("bhp_vfx_wolf_death"); ShaderReplacer.Replace(_vfxDeath); _vfxWaterSurface = _huskyBundle.LoadAsset<GameObject>("bhp_vfx_water_surface"); ShaderReplacer.Replace(_vfxWaterSurface); _fxFootstepWater = _huskyBundle.LoadAsset<GameObject>("bhp_fx_footstep_water"); ShaderReplacer.Replace(_fxFootstepWater); _serverConfigLocked = config("1- ServerSync", "Lock Configuration", Toggle.On, new ConfigDescription("If On, the configuration is locked and can be changed by server admins only.", (AcceptableValueBase)null, Array.Empty<object>())); _configSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked); string group = english.Localize("$bhp_bonetoy"); _boneToyEnable = config(group, "Recipe", value: true, new ConfigDescription("Enable/Disables recipe. (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _boneToyMat = config(group, "Required Material", "BoneFragments:4:2", new ConfigDescription("Item name : amount : amount per level (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); string group2 = english.Localize("$bhp_odinsgift"); _giftEnable = config(group2, "Recipe", value: true, new ConfigDescription("Enable/Disables recipe. (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _giftMat1 = config(group2, "Required Material 1", "Coins:100", new ConfigDescription("Item name : amount (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _giftMat2 = config(group2, "Required Material 2", "Amber:2", new ConfigDescription("Item name : amount (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _giftMat3 = config(group2, "Required Material 3", "AmberPearl:2", new ConfigDescription("Item name : amount (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _giftMat4 = config(group2, "Required Material 4", "Ruby:2", new ConfigDescription("Item name : amount (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); string group3 = english.Localize("$bhp_horn"); _hornEnable = config(group3, "Recipe", value: true, new ConfigDescription("Enable/Disables recipe. (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _hornMat1 = config(group3, "Required Material 1", "Bronze:4:1", new ConfigDescription("Item name : amount : amount per level (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _hornMat2 = config(group3, "Required Material 2", "Flint:3:1", new ConfigDescription("Item name : amount : amount per level (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); _hornMat3 = config(group3, "Required Material 3", "SurtlingCore:1:0", new ConfigDescription("Item name : amount : amount per level (Needs Logout)", (AcceptableValueBase)null, Array.Empty<object>())); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private static AssetBundle GetAssetBundleFromResources(string filename) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single((string x) => x.EndsWith(filename)); using Stream stream = executingAssembly.GetManifestResourceStream(name); return AssetBundle.LoadFromStream(stream); } public static void NewTame(GameObject pet) { if (!Object.op_Implicit((Object)(object)pet.GetComponent<FetchAI>())) { ((Behaviour)pet.GetComponent<MonsterAI>()).enabled = false; pet.AddComponent<FetchAI>(); } if (!Object.op_Implicit((Object)(object)pet.GetComponent<AlertedFixed>())) { pet.AddComponent<AlertedFixed>(); } } } } namespace Husky.Patches { [HarmonyPatch(typeof(Humanoid), "UseItem")] public class HumanoidPatch { public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui) { //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Invalid comparison between Unknown and I4 //IL_010c: 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) if (inventory == null) { inventory = __instance.m_inventory; } if (!inventory.ContainsItem(item)) { return true; } GameObject hoverObject = __instance.GetHoverObject(); if ((Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<Hoverable>() : null) != null && !fromInventoryGui) { MonsterAI component = hoverObject.GetComponent<MonsterAI>(); if ((Object)(object)component != (Object)null && ((Object)((Component)component).gameObject).name.Replace("(Clone)", "") == "BHP_Husky" && component.CanConsume(item)) { Tameable component2 = hoverObject.GetComponent<Tameable>(); string text = ((((component2 != null) ? component2.GetText() : null) == "") ? component2.m_character.m_name : component2.GetText()); if ((int)item.m_shared.m_itemType == 2) { if ((Object)(object)component2 != (Object)null && component2.IsHungry()) { __instance.DoInteractAnimation(hoverObject); component.m_onConsumedItem(item.m_dropPrefab.GetComponent<ItemDrop>()); Humanoid component3 = hoverObject.GetComponent<Humanoid>(); component3.m_consumeItemEffects.Create(((Component)component3).transform.position, Quaternion.identity, (Transform)null, 1f, -1); hoverObject.GetComponentInChildren<Animator>().SetTrigger("consume"); inventory.RemoveOneItem(item); ((Character)__instance).Message((MessageType)2, text + " is very happy.", 0, (Sprite)null); return false; } if (!component2.IsHungry()) { ((Character)__instance).Message((MessageType)2, text + " is not yet hungry.", 0, (Sprite)null); return false; } return false; } } } if (!fromInventoryGui) { return true; } if (!item.m_shared.m_name.ToLower().Contains("odinsgift")) { return true; } Object.Instantiate<GameObject>(Plugin._husky, ((Component)__instance).transform.position + ((Component)__instance).transform.forward + ((Component)__instance).transform.forward, Quaternion.identity); Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("bhp_fx_wolf_pet"), ((Component)__instance).transform.position, Quaternion.identity); inventory.RemoveOneItem(item); ((Character)__instance).Message((MessageType)2, "You unwrapped the gift and a big healthy dog jumps out.", 0, (Sprite)null); return false; } } [HarmonyPatch] public class ObjectDBPatch { [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPostfix] [HarmonyPriority(700)] public static void Awake_Postfix(ObjectDB __instance) { RegisterPrefab.ToObjectDB(); RegisterPrefab.Recipes(); __instance.UpdateRegisters(); } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyPostfix] [HarmonyPriority(700)] public static void CopyOtherDB_Postfix(ObjectDB __instance) { RegisterPrefab.ToObjectDB(); RegisterPrefab.Recipes(); __instance.UpdateRegisters(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public class ZNetScenePatch { public static void Postfix(ZNetScene __instance) { RegisterPrefab.ToZNetScene(); } } } namespace Husky.Functions { public class AlertedFixed : MonoBehaviour { private MonsterAI m_monsterAI; public void OnEnable() { m_monsterAI = ((Component)this).GetComponent<MonsterAI>(); } public void FixedUpdate() { Character val = ((BaseAI)m_monsterAI).FindEnemy(); if (Object.op_Implicit((Object)(object)val) && ((BaseAI)m_monsterAI).CanSenseTarget(val)) { ((BaseAI)m_monsterAI).Alert(); } } } public class FetchAI : MonoBehaviour { public enum AIStates { BaseAI, Idle, GettingToy, ReturningToy, Wait, DropToy } public static readonly List<FetchAI> _fetchAiList = new List<FetchAI>(); public AIStates m_AiState; public Animator m_animator; public MonsterAI m_monsterAI; public float m_updateTimer; public float m_distanceFromPlayer = 2.25f; public float m_distanceFromToy = 1f; public bool m_pausing; public Rigidbody m_targetToy; public float m_stateTime; public bool m_hasToy; private readonly Vector3 m_ToyOffset = new Vector3(0f, 0f, 0f); private readonly Vector3 m_mouthOffset = new Vector3(0.18f, 0.56f, 0f); private bool ValidToyToGet { get { if ((Object)(object)m_targetToy != (Object)null) { return m_targetToy.useGravity; } return false; } } private bool ValidToy { get { if ((Object)(object)m_targetToy != (Object)null) { return !m_targetToy.useGravity; } return false; } } public void Awake() { m_monsterAI = ((Component)this).GetComponent<MonsterAI>(); ((Behaviour)m_monsterAI).enabled = false; _fetchAiList.Add(this); m_animator = ((Component)this).GetComponentInChildren<Animator>(); } public void Start() { m_monsterAI.Start(); } private void OnDestroy() { _fetchAiList.Remove(this); } private Rigidbody GetToy(float range) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) m_targetToy = FetchSystem.FindToy(((Component)this).transform.position, range); if (Object.op_Implicit((Object)(object)m_targetToy)) { return m_targetToy; } return null; } public void GetToy(ItemDrop toy) { m_targetToy = ((Component)toy).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)m_targetToy)) { m_AiState = AIStates.GettingToy; m_stateTime = 10f; } } public void FixedUpdate() { try { if (((BaseAI)m_monsterAI).m_nview.IsValid()) { m_updateTimer += Time.fixedDeltaTime; if (!(m_updateTimer < 0.05f)) { UpdateAI(0.05f); m_updateTimer -= 0.05f; } } } catch { } } public void UpdateAI(float dt) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_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_01f4: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) m_stateTime -= dt; if (((BaseAI)m_monsterAI).IsAlerted()) { m_stateTime = 3f; m_AiState = AIStates.BaseAI; DropToy(); } if (m_stateTime <= 0f && m_pausing) { m_pausing = false; } else if (m_stateTime <= 0f && m_AiState != 0) { NewAction(); } else if (m_pausing) { return; } switch (m_AiState) { case AIStates.BaseAI: ((BaseAI)m_monsterAI).UpdateAI(dt); if (m_stateTime <= 0f) { if (((BaseAI)m_monsterAI).m_randomMoveUpdateTimer <= 0f) { NewAction(); } else { m_stateTime = 3f; } } break; case AIStates.GettingToy: { if (!ValidToyToGet) { m_stateTime = 0f; break; } Vector3 position = ((Component)m_targetToy).transform.position; if (((BaseAI)m_monsterAI).MoveTo(dt, position, m_distanceFromToy, true) && Utils.DistanceXZ(((Component)this).transform.position, position) <= m_distanceFromToy) { ((BaseAI)m_monsterAI).LookAt(position); if (((BaseAI)m_monsterAI).IsLookingAt(position, 20f, false) && ValidToyToGet) { m_animator.Play("consume"); ((MonoBehaviour)this).StartCoroutine(PickupToy()); m_AiState = AIStates.Wait; m_stateTime = 5f; } } break; } case AIStates.ReturningToy: { if (!ValidToy) { m_hasToy = false; m_stateTime = 0f; break; } Transform transform = ((Component)Player.m_localPlayer).transform; if (((BaseAI)m_monsterAI).MoveTo(dt, transform.position + transform.forward * m_distanceFromPlayer, 0f, true)) { ((BaseAI)m_monsterAI).LookAt(transform.position); if (((BaseAI)m_monsterAI).IsLookingAt(transform.position, 15f, false)) { m_pausing = true; m_AiState = AIStates.DropToy; m_stateTime = Random.Range(0.4f, 1.3f); } } break; } case AIStates.DropToy: DropToy(); m_AiState = AIStates.Wait; m_stateTime = Random.Range(2f, 4f); break; case AIStates.Idle: case AIStates.Wait: break; } } private void DropToy() { if (m_hasToy) { m_hasToy = false; if (ValidToy) { ((Renderer)((Component)m_targetToy).gameObject.GetComponentInChildren<MeshRenderer>()).enabled = true; m_targetToy.isKinematic = false; m_targetToy.collisionDetectionMode = (CollisionDetectionMode)1; Traverse.Create((object)((Component)m_targetToy).GetComponent<ZSyncTransform>()).Field("m_useGravity").SetValue((object)true); ((Component)m_targetToy).transform.SetParent((Transform)null, true); } } } private IEnumerator PickupToy() { yield return (object)new WaitForSeconds(0.48f); if (!ValidToyToGet || ((BaseAI)m_monsterAI).IsAlerted()) { m_animator.CrossFadeInFixedTime("New State 0", 0.4f, 0); m_AiState = AIStates.Idle; m_stateTime = 0f; yield break; } Traverse.Create((object)((Component)m_targetToy).GetComponent<ZSyncTransform>()).Field("m_useGravity").SetValue((object)false); m_targetToy.collisionDetectionMode = (CollisionDetectionMode)3; m_targetToy.isKinematic = true; ((Component)m_targetToy).GetComponent<ItemDrop>().m_autoPickup = false; Transform val = Utils.FindChild(((Component)this).transform, "Bip01 Head", (IterativeSearchType)0); Vector3 val2 = ((Component)m_targetToy).transform.rotation * m_ToyOffset; ((Component)m_targetToy).transform.SetParent(val, true); ((Component)m_targetToy).transform.position = val.position + val2 + val.rotation * m_mouthOffset; m_hasToy = true; ((Renderer)((Component)m_targetToy).gameObject.GetComponentInChildren<MeshRenderer>()).enabled = false; yield return (object)new WaitForSeconds(0.22f); m_animator.CrossFadeInFixedTime("New State 7", 0.6f, 0); yield return (object)new WaitForSeconds(Random.Range(0.2f, 1.5f)); m_AiState = AIStates.ReturningToy; m_stateTime = 10f; } private void NewAction() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (Random.Range(0, 3) == 0) { if (!m_hasToy) { Vector3 val = ((Component)this).transform.position - ((Component)Player.m_localPlayer).transform.position; if (((Vector3)(ref val)).sqrMagnitude <= 64f && !((Object)(object)GetToy(64f) == (Object)null)) { m_AiState = AIStates.GettingToy; m_stateTime = 10f; } } } else { m_AiState = AIStates.BaseAI; m_stateTime = Random.Range(2f, 4f); } } } [HarmonyPatch] public class FetchSystem { private static readonly Collider[] _sphereResults = (Collider[])(object)new Collider[32]; private static ItemDrop _lastDroppedItem; [HarmonyPatch(typeof(ItemDrop), "OnPlayerDrop")] [HarmonyPostfix] public static void OnPlayerDrop_Postfix(ItemDrop __instance) { _lastDroppedItem = __instance; } [HarmonyPatch(typeof(ItemDrop), "DropItem")] [HarmonyPostfix] public static void DropItem_Postfix(ItemDrop __result) { _lastDroppedItem = __result; } [HarmonyPostfix] [HarmonyPatch(typeof(Projectile), "SpawnOnHit")] public static void SpawnOnHit_Postfix(Projectile __instance, ref ItemData ___m_spawnItem) { if (__instance.m_spawnItem == null || !__instance.m_respawnItemOnHit || !Object.op_Implicit((Object)(object)_lastDroppedItem) || ___m_spawnItem.m_shared.m_name != "$bhp_bonetoy") { return; } foreach (FetchAI item in from pet in FetchAI._fetchAiList.Where(delegate(FetchAI pet) { //IL_000b: 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_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) Vector3 val = ((Component)pet).gameObject.transform.position - ((Component)Player.m_localPlayer).transform.position; return !(((Vector3)(ref val)).sqrMagnitude > 100f); }) let component = ((Component)pet).GetComponent<Character>() where Object.op_Implicit((Object)(object)component) && component.IsTamed() && !Object.op_Implicit((Object)(object)((Component)pet).GetComponent<Growup>()) && !((BaseAI)pet.m_monsterAI).IsAlerted() && pet.m_AiState == FetchAI.AIStates.BaseAI select pet) { item.GetToy(_lastDroppedItem); } } [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "DropItem")] public static void DropItem_Postfix(Inventory inventory, ItemData item, int amount, Humanoid __instance, bool __result) { if (!__result || !((Character)__instance).IsPlayer() || !Object.op_Implicit((Object)(object)_lastDroppedItem) || item.m_shared.m_name != "$bhp_bonetoy") { return; } foreach (FetchAI item2 in from pet in FetchAI._fetchAiList.Where(delegate(FetchAI pet) { //IL_000b: 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_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) Vector3 val = ((Component)pet).gameObject.transform.position - ((Component)Player.m_localPlayer).transform.position; return !(((Vector3)(ref val)).sqrMagnitude > 100f); }) let component = ((Component)pet).GetComponent<Character>() where Object.op_Implicit((Object)(object)component) && component.IsTamed() && !Object.op_Implicit((Object)(object)((Component)pet).GetComponent<Growup>()) && !((BaseAI)pet.m_monsterAI).IsAlerted() && pet.m_AiState == FetchAI.AIStates.BaseAI select pet) { item2.GetToy(_lastDroppedItem); } } [HarmonyPostfix] [HarmonyPatch(typeof(MonsterAI), "MakeTame")] public static void MakeTame_Postfix(MonsterAI __instance) { if (!(((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "") != "BHP_Husky")) { Character component = ((Component)__instance).GetComponent<Character>(); if (component != null && component.IsTamed()) { Plugin.NewTame(((Component)__instance).gameObject); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Procreation), "Awake")] public static void Awake_Postfix(Procreation __instance) { if (!(((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "") != "BHP_Husky")) { Character component = ((Component)__instance).GetComponent<Character>(); if (component != null && component.IsTamed()) { Plugin.NewTame(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(Character), "Awake")] [HarmonyPostfix] public static void Awake_Prefix(Character __instance) { if (!((Object)(object)__instance == (Object)null) && !__instance.IsPlayer() && !__instance.IsBoss() && __instance.m_nview.IsValid() && __instance.IsTamed() && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Growup>()) && !(((Object)__instance).name.Replace("(Clone)", "") != "BHP_Husky")) { Plugin.NewTame(((Component)__instance).gameObject); } } public static Rigidbody FindToy(Vector3 pos, float range) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(pos, range, _sphereResults, LayerMask.GetMask(new string[1] { "item" })); Rigidbody result = null; float num2 = 999999f; for (int i = 0; i < num; i++) { Collider val = _sphereResults[i]; if (!Object.op_Implicit((Object)(object)val.attachedRigidbody)) { continue; } ItemDrop component = ((Component)val.attachedRigidbody).GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || !((Component)component).GetComponent<ZNetView>().IsValid() || component.m_itemData.m_shared.m_name != "$bhp_bonetoy") { continue; } Rigidbody component2 = ((Component)component).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component2) && component2.useGravity) { Vector3 val2 = ((Component)component).transform.position - pos; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num2) { result = component2; num2 = sqrMagnitude; } } } return result; } } public static class Helper { public static void AddClonedObject(this ZNetScene zNetScene, GameObject gameObject, bool overWrite = true) { GameObject prefab; if ((Object)(object)(prefab = zNetScene.GetPrefab(((Object)gameObject).name)) != (Object)null) { if (!overWrite) { return; } zNetScene.m_prefabs.Remove(prefab); zNetScene.m_namedPrefabs.Remove(StringExtensionMethods.GetStableHashCode(((Object)gameObject).name)); } zNetScene.m_prefabs.Add(gameObject); zNetScene.m_namedPrefabs.Add(StringExtensionMethods.GetStableHashCode(((Object)gameObject).name), gameObject); } public static void AddClonedObject(this ObjectDB objectDB, GameObject gameObject, bool overWrite = true) { GameObject itemPrefab; if ((Object)(object)(itemPrefab = objectDB.GetItemPrefab(((Object)gameObject).name)) != (Object)null) { if (!overWrite) { return; } objectDB.m_items.Remove(itemPrefab); objectDB.m_itemByHash.Remove(StringExtensionMethods.GetStableHashCode(((Object)gameObject).name)); } objectDB.m_items.Add(gameObject); objectDB.m_itemByHash.Add(StringExtensionMethods.GetStableHashCode(((Object)gameObject).name), gameObject); } public static void AddRecipe(this ObjectDB objectDB, Recipe recipe, bool overWrite = true) { if (objectDB.m_recipes.Contains(recipe)) { if (!overWrite) { return; } objectDB.m_recipes.Remove(recipe); } objectDB.m_recipes.Add(recipe); } public static bool ObjectDBAwake() { if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0) { return (Object)(object)ObjectDB.instance.GetItemPrefab("Wood") != (Object)null; } return false; } public static bool ZNetSceneAwake() { if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs.Count != 0) { return (Object)(object)ZNetScene.instance.GetPrefab("piece_workbench") != (Object)null; } return false; } } public static class RegisterPrefab { private static ZNetScene _zNetScene => ZNetScene.instance; private static ObjectDB _objectDB => ObjectDB.instance; public static void ToZNetScene() { if (Helper.ZNetSceneAwake()) { _zNetScene.AddClonedObject(Plugin._husky); Plugin.NewTame(Plugin._husky); Plugin._husky.GetComponent<MonsterAI>().m_consumeItems = new List<ItemDrop>(7) { _zNetScene.GetPrefab("CookedDeerMeat").GetComponent<ItemDrop>(), _zNetScene.GetPrefab("CookedMeat").GetComponent<ItemDrop>(), _zNetScene.GetPrefab("CookedBugMeat").GetComponent<ItemDrop>(), _zNetScene.GetPrefab("CookedChickenMeat").GetComponent<ItemDrop>(), _zNetScene.GetPrefab("CookedHareMeat").GetComponent<ItemDrop>(), _zNetScene.GetPrefab("CookedLoxMeat").GetComponent<ItemDrop>(), _zNetScene.GetPrefab("CookedWolfMeat").GetComponent<ItemDrop>() }; _zNetScene.AddClonedObject(Plugin._boneToy); _zNetScene.AddClonedObject(Plugin._horn); _zNetScene.AddClonedObject(Plugin._odinsGift); _zNetScene.AddClonedObject(Plugin._vfxHit); _zNetScene.AddClonedObject(Plugin._vfxDeath); _zNetScene.AddClonedObject(Plugin._vfxWaterSurface); _zNetScene.AddClonedObject(Plugin._fxFootstepWater); GameObject gameObject = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_bone_projectile"); _zNetScene.AddClonedObject(gameObject); GameObject gameObject2 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_fx_backstab"); _zNetScene.AddClonedObject(gameObject2); GameObject gameObject3 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_fx_creature_tamed"); _zNetScene.AddClonedObject(gameObject3); GameObject gameObject4 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_fx_crit"); _zNetScene.AddClonedObject(gameObject4); GameObject gameObject5 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_fx_footstep_jog"); _zNetScene.AddClonedObject(gameObject5); GameObject gameObject6 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_fx_wolf_pet"); _zNetScene.AddClonedObject(gameObject6); GameObject gameObject7 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_sfx_creature_consume"); _zNetScene.AddClonedObject(gameObject7); GameObject gameObject8 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_sfx_footstep_swim"); _zNetScene.AddClonedObject(gameObject8); GameObject gameObject9 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_sfx_wolf_alerted"); _zNetScene.AddClonedObject(gameObject9); GameObject gameObject10 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_sfx_wolf_hit"); _zNetScene.AddClonedObject(gameObject10); GameObject gameObject11 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_vfx_corpse_destruction_small"); _zNetScene.AddClonedObject(gameObject11); GameObject gameObject12 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_vfx_creature_soothed"); _zNetScene.AddClonedObject(gameObject12); GameObject gameObject13 = Plugin._huskyBundle.LoadAsset<GameObject>("BHP_HuskyRagdoll"); _zNetScene.AddClonedObject(gameObject13); GameObject gameObject14 = Plugin._huskyBundle.LoadAsset<GameObject>("bhp_sfx_warhorn"); _zNetScene.AddClonedObject(gameObject14); } } public static void ToObjectDB() { if (Helper.ObjectDBAwake()) { _objectDB.AddClonedObject(Plugin._boneToy); _objectDB.AddClonedObject(Plugin._odinsGift); _objectDB.AddClonedObject(Plugin._horn); SharedData shared = Plugin._horn.GetComponent<ItemDrop>().m_itemData.m_shared; Recall recall = ScriptableObject.CreateInstance<Recall>(); ((StatusEffect)recall).m_ttl = 0.25f; shared.m_consumeStatusEffect = (StatusEffect)(object)recall; RegisterStatusEffects(shared.m_consumeStatusEffect); } } public static void Recipes() { if (Helper.ObjectDBAwake() && Helper.ZNetSceneAwake()) { BoneToy(); OdinsGift(); VikingHorn(); } } private static void BoneToy() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = "Recipe_BoneToy"; val.m_item = Plugin._boneToy.GetComponent<ItemDrop>(); val.m_amount = 1; val.m_enabled = Plugin._boneToyEnable.Value; val.m_qualityResultAmountMultiplier = 1f; val.m_craftingStation = _zNetScene.GetPrefab("piece_workbench").GetComponent<CraftingStation>(); val.m_repairStation = val.m_craftingStation; val.m_minStationLevel = 1; val.m_requireOnlyOneIngredient = false; string[] array = Plugin._boneToyMat.Value.Split(':', ' '); val.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = _objectDB.GetItemPrefab(array[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = int.Parse(array[2]), m_recover = true } }; _objectDB.AddRecipe(val); } private static void OdinsGift() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0144: 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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: 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_01fe: 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_020d: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = "Recipe_OdinsGift"; val.m_item = Plugin._odinsGift.GetComponent<ItemDrop>(); val.m_amount = 1; val.m_enabled = Plugin._giftEnable.Value; val.m_qualityResultAmountMultiplier = 1f; val.m_craftingStation = _zNetScene.GetPrefab("piece_workbench").GetComponent<CraftingStation>(); val.m_repairStation = val.m_craftingStation; val.m_minStationLevel = 1; val.m_requireOnlyOneIngredient = false; string[] array = Plugin._giftMat1.Value.Split(':', ' '); string[] array2 = Plugin._giftMat2.Value.Split(':', ' '); string[] array3 = Plugin._giftMat3.Value.Split(':', ' '); string[] array4 = Plugin._giftMat4.Value.Split(':', ' '); val.m_resources = (Requirement[])(object)new Requirement[4] { new Requirement { m_resItem = _objectDB.GetItemPrefab(array[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = 0, m_recover = true }, new Requirement { m_resItem = _objectDB.GetItemPrefab(array2[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array2[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = 0, m_recover = true }, new Requirement { m_resItem = _objectDB.GetItemPrefab(array3[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array3[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = 0, m_recover = true }, new Requirement { m_resItem = _objectDB.GetItemPrefab(array4[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array4[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = 0, m_recover = true } }; _objectDB.AddRecipe(val); } private static void VikingHorn() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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_01bc: Expected O, but got Unknown Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = "Recipe_BHP_GoldenHorn"; val.m_item = Plugin._horn.GetComponent<ItemDrop>(); val.m_amount = 1; val.m_enabled = Plugin._hornEnable.Value; val.m_qualityResultAmountMultiplier = 1f; val.m_craftingStation = _zNetScene.GetPrefab("piece_workbench").GetComponent<CraftingStation>(); val.m_repairStation = val.m_craftingStation; val.m_minStationLevel = 1; val.m_requireOnlyOneIngredient = false; string[] array = Plugin._hornMat1.Value.Split(':', ' '); string[] array2 = Plugin._hornMat2.Value.Split(':', ' '); string[] array3 = Plugin._hornMat3.Value.Split(':', ' '); val.m_resources = (Requirement[])(object)new Requirement[3] { new Requirement { m_resItem = _objectDB.GetItemPrefab(array[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = int.Parse(array[2]), m_recover = true }, new Requirement { m_resItem = _objectDB.GetItemPrefab(array2[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array2[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = int.Parse(array2[2]), m_recover = true }, new Requirement { m_resItem = _objectDB.GetItemPrefab(array3[0]).GetComponent<ItemDrop>(), m_amount = int.Parse(array3[1]), m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = int.Parse(array3[2]), m_recover = true } }; _objectDB.AddRecipe(val); } private static void RegisterStatusEffects(StatusEffect statusEffect) { if (statusEffect != null && !Object.op_Implicit((Object)(object)_objectDB.GetStatusEffect(StringExtensionMethods.GetStableHashCode(((Object)statusEffect).name)))) { _objectDB.m_StatusEffects.Add(statusEffect); } } } public static class ShaderReplacer { private static readonly List<GameObject> GOToSwap; static ShaderReplacer() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown GOToSwap = new List<GameObject>(); new Harmony("blacks7ar.utilities.ShaderReplacer").Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ShaderReplacer), "ReplaceShaderPatch", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static void Replace(GameObject gameObject) { GOToSwap.Add(gameObject); } [HarmonyPriority(700)] private static void ReplaceShaderPatch() { foreach (Material item in from gameObject in GOToSwap select gameObject.GetComponentsInChildren<Renderer>(true) into renderers from renderer in renderers where (Object)(object)renderer != (Object)null from material in renderer.sharedMaterials where (Object)(object)material != (Object)null select material) { Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); foreach (Shader val in array) { if (((Object)item.shader).name == ((Object)val).name) { item.shader = val; } } } } } public enum Toggle { On = 1, Off = 0 } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<1a6f0ff5-51bd-43ca-a986-3aa1fa3ef60d>Embedded] internal sealed class <1a6f0ff5-51bd-43ca-a986-3aa1fa3ef60d>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [<1a6f0ff5-51bd-43ca-a986-3aa1fa3ef60d>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [CompilerGenerated] internal sealed class <1fbceb63-b257-4c72-83a5-57598e7a4b37>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <1fbceb63-b257-4c72-83a5-57598e7a4b37>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <1fbceb63-b257-4c72-83a5-57598e7a4b37>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [<1a6f0ff5-51bd-43ca-a986-3aa1fa3ef60d>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContextAttribute : Attribute { public readonly byte Flag; public <e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [<1a6f0ff5-51bd-43ca-a986-3aa1fa3ef60d>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 ServerSync { [PublicAPI] [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] internal abstract class OwnConfigEntryBase { [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] public object LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] [PublicAPI] internal class SyncedConfigEntry<[<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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; } } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(2)] [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] internal abstract class CustomSyncedValueBase { public object LocalBaseValue; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(1)] public readonly string Identifier; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(1)] 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; [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] 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] [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] internal sealed class CustomSyncedValue<[<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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; } [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] [PublicAPI] [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] private static class SnatchCurrentlyHandlingRPC { [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] public static ZRpc currentRpc; [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] 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()); } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] 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)); } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] 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); } } } } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] 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); } } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] private class ParsedConfigs { [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 1, 1, 2 })] public readonly Dictionary<OwnConfigEntryBase, object> configValues = new Dictionary<OwnConfigEntryBase, object>(); [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 1, 1, 2 })] public readonly Dictionary<CustomSyncedValueBase, object> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] [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")] [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] private class SendConfigsAfterLogin { [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] 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); } } } [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix([<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 2, 1, 1 })] 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) { ZNetPeer peer; if (__instance.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state[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(rpc.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] private class PackageEntry { public string section = null; public string key = null; public Type type = null; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] public object value; } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] [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; } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] [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; } } [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] public string DisplayName; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] public string CurrentVersion; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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[]>>(); [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 1, 0, 1 })] 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; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] [method: <e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(2)] [field: <1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] public event Action<bool> SourceOfTruthChanged; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] [method: <e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(2)] [field: <1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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<[<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] T>(ConfigEntry<T> configEntry) { OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry.SettingChanged += [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (object _, EventArgs _) => { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<[<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (object _, EventArgs _) => { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { if (allCustomValues.Select([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (CustomSyncedValueBase v) => v.Priority)); customValue.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue); } }; } 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(([<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 0, 1 })] 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 var 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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (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; } 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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (OwnConfigEntryBase c) => c); Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (CustomSyncedValueBase c) => c.Identifier, [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (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) { ConfigSync configSync = configSyncs.FirstOrDefault([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (ConfigSync cs) => cs.allConfigs.Contains(config)); if (configSync == null) { return true; } return configSync.IsSourceOfTruth || !config.SynchronizedConfig || config.LocalBaseValue == null || (!configSync.IsLocked && (config != 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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (CustomSyncedValueBase config) => config.LocalBaseValue != null)) { item2.BoxedValue = item2.LocalBaseValue; item2.LocalBaseValue = null; } lockedConfigChanged -= serverLockedSettingChanged; serverLockedSettingChanged(); } private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package) { 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 (peer.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) { peer.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer.m_server ? 0 : peer.m_uid, text, new object[1] { pkg }); } } IEnumerable<bool> waitForQueue() { float timeout = Time.time + 30f; while (peer.m_socket.GetSendQueueSize() > 20000) { if (Time.time > timeout) { Debug.Log((object)$"Disconnecting {peer.m_uid} after 30 seconds config sending timeout"); peer.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 }); ZNet.instance.Disconnect(peer); 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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (ZNetPeer p) => p.m_uid == target).ToList(); } return sendZPackage(list, package); } private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] rawData = package.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()); package = compressedPackage; } List<IEnumerator<bool>> writers = (from peer in peers where peer.IsReady() select peer into p select distributeConfigToPeers(p, package)).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)); } } } [return: <1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] private static OwnConfigEntryBase configData(ConfigEntryBase config) { return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault(); } [return: <1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 2, 1 })] public static SyncedConfigEntry<T> ConfigData<[<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] T>(ConfigEntry<T> config) { return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault(); } private static T configAttribute<[<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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([<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 2, 1 })] IEnumerable<ConfigEntryBase> configs = null, [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 2, 1 })] IEnumerable<CustomSyncedValueBase> customValues = null, [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 2, 1 })] 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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (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, [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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(); } } [<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(1)] [HarmonyPatch] [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(0)] [PublicAPI] internal class VersionCheck { private static readonly HashSet<VersionCheck> versionChecks; private static readonly Dictionary<string, string> notProcessedNames; public string Name; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] private string displayName; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] private string currentVersion; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] private string minimumRequiredVersion; public bool ModRequired = true; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] private string ReceivedCurrentVersion; [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] private string ReceivedMinimumRequiredVersion; private readonly List<ZRpc> ValidatedClients = new List<ZRpc>(); [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] 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([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (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 System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion); bool flag2 = new System.Version(ReceivedCurrentVersion) >= new System.Version(MinimumRequiredVersion); return flag && flag2; } private string ErrorClient() { if (ReceivedMinimumRequiredVersion == null) { return DisplayName + " is not installed on the server."; } return (new System.Version(CurrentVersion) >= new System.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([<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(2)] ZRpc rpc = null) { return (rpc == null) ? ErrorClient() : ErrorServer(rpc); } private static VersionCheck[] GetFailedClient() { return versionChecks.Where([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (VersionCheck check) => !check.IsVersionOk()).ToArray(); } private static VersionCheck[] GetFailedServer(ZRpc rpc) { return versionChecks.Where([<e1ce0dd2-b519-4ddb-ba64-1d88209dd977>NullableContext(0)] (VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc)).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, [<1fbceb63-b257-4c72-83a5-57598e7a4b37>Nullable(new byte[] { 2, 1, 1 })] 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); } } } [HarmonyPrefix] [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance) { VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient()); if (array.Length == 0) { return true;