Decompiled source of Enhanced Monsters v1.0.4

BepInEx/plugins/EnhancedMonsters/EnhancedMonsters.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EnhancedMonsters.Config;
using EnhancedMonsters.Patches;
using EnhancedMonsters.Utils;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using StaticNetcodeLib;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EnhancedMonsters")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1")]
[assembly: AssemblyInformationalVersion("1.0.0+26995972b31114a400ca1263f51513676d169c7d")]
[assembly: AssemblyProduct("EnhancedMonsters")]
[assembly: AssemblyTitle("EnhancedMonsters")]
[assembly: NeutralResourcesLanguage("en-GB")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EnhancedMonsters
{
	[BepInPlugin("com.velddev.enhancedmonsters", "Enhanced Monsters", "1.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("Entity378.sellbodies")]
	public class Plugin : BaseUnityPlugin
	{
		private static readonly Harmony harmony = new Harmony("com.velddev.enhancedmonsters");

		public static ManualLogSource? logger;

		internal static Plugin Singleton { get; private set; }

		public static GameObject EnemyToPropPrefab { get; private set; }

		private void Awake()
		{
			Singleton = this;
			logger = ((BaseUnityPlugin)this).Logger;
			new LocalConfig(((BaseUnityPlugin)this).Config);
		}

		private void Start()
		{
			if (logger == null)
			{
				logger = ((BaseUnityPlugin)this).Logger;
			}
			logger.LogInfo((object)"This is (maybe) NOT an RPG mod. And hi btw.");
			EnemiesDataManager.LoadEnemiesData();
			new SyncedConfig(((BaseUnityPlugin)this).Config);
			logger.LogInfo((object)"Enemies data loaded and ready to be synchronized.");
			ApplyAllPatches();
			logger.LogDebug((object)"All harmony patches have been applied (energistics).");
			CreateThePrefab();
			logger.LogDebug((object)"The Prefab have been created correctly");
		}

		private static void ApplyAllPatches()
		{
			if (logger == null)
			{
				throw new NullReferenceException("logger is null. Cannot process further because it means that the mod was not initialized yet.");
			}
			logger.LogDebug((object)"Applying patches...");
			harmony.PatchAll(typeof(EnemyAI_Patches));
			logger.LogDebug((object)"Enemy patches applied.");
			logger.LogDebug((object)"MaskedEnemy patches applied.");
			harmony.PatchAll(typeof(MenuManager_Patches));
			logger.LogDebug((object)"MenuManager patches applied.");
			harmony.PatchAll(typeof(PlayerControllerB_Patches));
			logger.LogDebug((object)"PlayerController patches applied.");
			harmony.PatchAll(typeof(GameNetworkManager_Patches));
			logger.LogDebug((object)"GameNetworkManager patches applied.");
		}

		private static void CreateThePrefab()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NetworkPrefabs.CreateNetworkPrefab("EnemyAsProp");
			val.tag = "PhysicsProp";
			val.layer = 6;
			BoxCollider val2 = val.AddComponent<BoxCollider>();
			((Collider)val2).enabled = true;
			((Collider)val2).isTrigger = true;
			val2.size = new Vector3(1.5f, 1.5f, 1.5f);
			val.AddComponent<PhysicsProp>();
			EnemyToPropPrefab = val;
		}
	}
	public static class PluginInfo
	{
		public const string Version = "1.0.4";

		public const string GUID = "com.velddev.enhancedmonsters";

		public const string DisplayName = "Enhanced Monsters";
	}
}
namespace EnhancedMonsters.Utils
{
	public static class EnemiesDataManager
	{
		public static readonly Dictionary<string, EnemyData> EnemiesData = new Dictionary<string, EnemyData>();

		public static readonly Dictionary<string, EnemyData> DefaultEnemiesData = new Dictionary<string, EnemyData>
		{
			["Manticoil"] = new EnemyData(Pickupable: true, 100, 160, 10f, "F"),
			["Tulip Snake"] = new EnemyData(Pickupable: true, 10, 70, 24f, "F"),
			["Baboon hawk"] = new EnemyData(Pickupable: true, 40, 70, 61f),
			["Hoarding bug"] = new EnemyData(Pickupable: true, 30, 60, 38f),
			["Puffer"] = new EnemyData(Pickupable: true, 50, 95, 78f, "D"),
			["Centipede"] = new EnemyData(Pickupable: true, 55, 95, 23f, "D"),
			["Bunker Spider"] = new EnemyData(Pickupable: true, 140, 180, 75f, "C"),
			["MouthDog"] = new EnemyData(Pickupable: true, 170, 210, 88f, "C"),
			["Crawler"] = new EnemyData(Pickupable: true, 210, 270, 66f, "B"),
			["Flowerman"] = new EnemyData(Pickupable: true, 225, 299, 45f, "B"),
			["Butler"] = new EnemyData(Pickupable: true, 250, 305, 99f, "B"),
			["Nutcracker"] = new EnemyData(Pickupable: true, 300, 340, 44f, "A"),
			["Maneater"] = new EnemyData(Pickupable: true, 310, 340, 80f, "A"),
			["Docile Locust Bees"] = new EnemyData(Pickupable: false, 0, 0, 0f, "F"),
			["Red pill"] = new EnemyData(Pickupable: false, 0, 0, 0f, "F"),
			["Blob"] = new EnemyData(Pickupable: false, 0, 0, 0f, "D"),
			["Red Locust Bees"] = new EnemyData(Pickupable: false, 0, 0, 0f, "C"),
			["Butler Bees"] = new EnemyData(Pickupable: false, 0, 0, 0f, "C"),
			["Earth Leviathan"] = new EnemyData(Pickupable: false, 0, 0, 0f, "B"),
			["Masked"] = new EnemyData(Pickupable: false, 0, 0, 0f, "B"),
			["Clay Surgeon"] = new EnemyData(Pickupable: false, 0, 0, 0f, "B"),
			["Spring"] = new EnemyData(Pickupable: false, 0, 0, 0f, "A"),
			["Jester"] = new EnemyData(Pickupable: false, 0, 0, 0f, "S+"),
			["RadMech"] = new EnemyData(Pickupable: false, 0, 0, 0f, "S+"),
			["Girl"] = new EnemyData(Pickupable: false, 0, 0, 0f, "?"),
			["Lasso"] = new EnemyData(Pickupable: false, 0, 0, 0f, "dont exist haha"),
			["ForestGiant"] = new EnemyData(Pickupable: false, 0, 0, 0f, "S"),
			["PinkGiant"] = new EnemyData(Pickupable: false, 0, 0, 0f, "F"),
			["Football"] = new EnemyData(Pickupable: false, 0, 0, 0f, "B"),
			["Locker"] = new EnemyData(Pickupable: false, 0, 0, 0f, "A"),
			["Bush Wolf"] = new EnemyData(Pickupable: true, 250, 320, 72f, "A"),
			["PjonkGoose"] = new EnemyData(Pickupable: true, 279, 340, 60f, "A")
		};

		public static string EnemiesDataFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "EnemiesData.json");

		public static readonly Dictionary<string, GameObject> Enemies2Props = new Dictionary<string, GameObject>();

		public static void LoadEnemiesData()
		{
			if (!File.Exists(EnemiesDataFile))
			{
				Plugin.logger.LogWarning((object)"Enemy Data File did not exist!");
				EnemiesData.ProperConcat(DefaultEnemiesData);
				SaveEnemiesData();
				return;
			}
			string text = File.ReadAllText(EnemiesDataFile);
			Plugin.logger.LogDebug((object)text);
			Dictionary<string, EnemyData> dictionary = JsonConvert.DeserializeObject<Dictionary<string, EnemyData>>(text);
			if (dictionary == null)
			{
				Plugin.logger.LogWarning((object)"Enemy Data File seems to be empty or invalid.");
				EnemiesData.ProperConcat(DefaultEnemiesData);
				SaveEnemiesData();
			}
			else
			{
				EnemiesData.ProperConcat(dictionary);
				Plugin.logger.LogDebug((object)$"{dictionary} => {EnemiesData.Count}");
				EnemiesData.ProperConcat(DefaultEnemiesData);
				Plugin.logger.LogDebug((object)$"{DefaultEnemiesData.Count} => {EnemiesData.Count}");
				SaveEnemiesData();
			}
		}

		public static void RegisterEnemy(string enemyName, bool sellable, int minPrice, int maxPrice, float mass, string rank)
		{
			EnemiesData.Add(enemyName, new EnemyData(sellable, minPrice, maxPrice, mass, rank));
			if (Synchronizable<SyncedConfig>.IsHost || !NetworkManager.Singleton.IsListening)
			{
				SyncedConfig.BroadcastSync();
			}
		}

		internal static void RegisterEnemy(string enemyName, EnemyData enemyData)
		{
			if (Synchronizable<SyncedConfig>.IsHost || !NetworkManager.Singleton.IsListening)
			{
				if (EnemiesData != Synchronizable<SyncedConfig>.Instance.EnemiesData)
				{
					Plugin.logger.LogError((object)"Cannot update the mob configs. Somehow, the EnemiesData from the EnemiesDataManager and the one from the SyncedConfigs are not the same, even though they both are yours.");
				}
				else if (!EnemiesData.TryAdd(enemyName, enemyData))
				{
					Plugin.logger.LogDebug((object)("EnemyData '" + enemyName + "' already exists!"));
				}
				else
				{
					SyncedConfig.BroadcastSync();
				}
			}
		}

		public static void SaveEnemiesData()
		{
			if (!Synchronizable<SyncedConfig>.IsHost)
			{
				NetworkManager singleton = NetworkManager.Singleton;
				if (singleton != null && singleton.IsListening)
				{
					return;
				}
			}
			string contents = JsonConvert.SerializeObject((object)EnemiesData, (Formatting)1);
			File.WriteAllText(EnemiesDataFile, contents);
			Plugin.logger.LogInfo((object)"Saved enemies data.");
		}

		public static void EnsureEnemy2PropPrefabs()
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>();
			EnemyAI[] array2 = array;
			foreach (EnemyAI val in array2)
			{
				Plugin.logger.LogInfo((object)("Registering NetworkPrefab '" + val.enemyType.enemyName + "'"));
				ref string enemyName = ref val.enemyType.enemyName;
				if (Enemies2Props.TryGetValue(val.enemyType.enemyName, out GameObject value))
				{
					if (!Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].Pickupable)
					{
						Enemies2Props.Remove(enemyName);
						continue;
					}
					PhysicsProp component = value.GetComponent<PhysicsProp>();
					((GrabbableObject)component).itemProperties.minValue = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].MinValue;
					((GrabbableObject)component).itemProperties.maxValue = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].MaxValue;
					((GrabbableObject)component).itemProperties.weight = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].LCMass;
				}
				else
				{
					if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.TryGetValue(val.enemyType.enemyName, out var value2) || !value2.Pickupable)
					{
						continue;
					}
					GameObject val2 = new GameObject(((Object)val).name + " neutralized");
					foreach (Transform item in ((Component)val).transform)
					{
						Transform val3 = item;
						Transform val4 = Object.Instantiate<Transform>(val3);
						((Object)val4).name = ((Object)val3).name;
						((Component)val4).transform.parent = val2.transform;
					}
					val2.transform.localScale = ((Component)val).transform.localScale;
					GameObject val5 = NetworkPrefabs.CloneNetworkPrefab(Plugin.EnemyToPropPrefab, ((Object)val).name + " propized");
					val2.transform.parent = val5.transform;
					Plugin.logger.LogInfo((object)("Attached " + ((Object)val2).name + " to " + ((Object)val2.transform.parent).name));
					PhysicsProp component2 = val5.GetComponent<PhysicsProp>();
					((GrabbableObject)component2).grabbable = true;
					((GrabbableObject)component2).grabbableToEnemies = false;
					Transform val6 = val2.transform.Find("MapDot");
					if (Object.op_Implicit((Object)(object)val6))
					{
						Object.Destroy((Object)(object)val6);
					}
					Transform val7 = val2.transform.Find("ScanNode");
					if (Object.op_Implicit((Object)(object)val7))
					{
						((Component)val7).transform.parent = val5.transform;
						ScanNodeProperties component3 = ((Component)val7).GetComponent<ScanNodeProperties>();
						component3.maxRange = 13;
						component3.minRange = 1;
						component3.nodeType = 2;
						component3.requiresLineOfSight = true;
						component3.headerText = "Dead " + component3.headerText;
						Item val8 = (((GrabbableObject)component2).itemProperties = ScriptableObject.CreateInstance<Item>());
						val8.itemName = component3.headerText;
						val8.minValue = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].MinValue;
						val8.maxValue = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].MaxValue;
						val8.allowDroppingAheadOfPlayer = true;
						val8.canBeGrabbedBeforeGameStart = true;
						val8.isScrap = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].Pickupable;
						val8.itemSpawnsOnGround = false;
						val8.twoHanded = true;
						val8.requiresBattery = false;
						val8.twoHandedAnimation = true;
						val8.weight = Synchronizable<SyncedConfig>.Instance.EnemiesData[enemyName].LCMass;
						val8.spawnPrefab = val5;
						Items.RegisterItem(val8);
						Enemies2Props.Add(enemyName, val5);
						Plugin.logger.LogInfo((object)("Registered NetworkPrefab '" + ((Object)val5).name + "'/'" + ((Object)val2).name + "' (" + val8.itemName + ")"));
					}
				}
			}
		}
	}
	[Serializable]
	[JsonObject(Description = "The value of a moby once killed, if it can be killed.")]
	public record struct EnemyData(bool Pickupable = true, int MinValue = 80, int MaxValue = 250, float Mass = 50f, string Rank = "E")
	{
		[JsonIgnore]
		public readonly float LCMass => Mass / 105f + 1f;
	}
	public static class Utility
	{
		public const float KgToLb = 2.2046227f;

		public static string ToStringObj(this object obj, string prefix = "")
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(prefix + obj.GetType().FullName + ": {");
			FieldInfo[] fields = obj.GetType().GetFields();
			foreach (FieldInfo fieldInfo in fields)
			{
				object arg = fieldInfo.GetValue(obj) ?? null;
				stringBuilder.AppendLine(prefix + $"\t{fieldInfo.FieldType.Name} {fieldInfo.Name}: {arg}");
			}
			stringBuilder.AppendLine(prefix + "}");
			return stringBuilder.ToString();
		}

		public static T EnsureComponent<T>(this GameObject go) where T : Component
		{
			if (go == null)
			{
				throw new NullReferenceException("The gameObject is a null reference.");
			}
			T result = default(T);
			if (!go.TryGetComponent<T>(ref result))
			{
				return go.AddComponent<T>();
			}
			return result;
		}

		public static void AddRange<K, T, TI>(this IDictionary<K, T> target, IEnumerable<TI> source, Func<TI, K> key, Func<TI, T> selector, bool set = true)
		{
			foreach (TI item in source)
			{
				K key2 = key(item);
				T value = selector(item);
				if (set)
				{
					target[key2] = value;
				}
				else
				{
					target.TryAdd(key(item), selector(item));
				}
			}
		}

		public static void ProperConcat<K, T>(this IDictionary<K, T> target, IDictionary<K, T> source)
		{
			foreach (KeyValuePair<K, T> item in source)
			{
				if (!target.ContainsKey(item.Key))
				{
					target.Add(item.Key, item.Value);
				}
			}
		}
	}
}
namespace EnhancedMonsters.Patches
{
	[StaticNetcode]
	[HarmonyPatch(typeof(EnemyAI))]
	public class EnemyAI_Patches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(EnemyAI), "Start")]
		private static void Start(EnemyAI __instance)
		{
			string text = Synchronizable<SyncedConfig>.Instance.EnemiesData[__instance.enemyType.enemyName].Rank ?? "?";
			ScanNodeProperties val = ((Component)((Component)__instance).gameObject.transform.Find("ScanNode")).gameObject.EnsureComponent<ScanNodeProperties>();
			val.subText = "Rank " + text;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAI), "KillEnemy")]
		private static void KillEnemy(EnemyAI __instance, bool destroy)
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			Plugin.logger.LogDebug((object)("Mob " + __instance.enemyType.enemyName + " died."));
			if (!destroy)
			{
				if (!__instance.isEnemyDead)
				{
					__instance.isEnemyDead = true;
				}
				if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(__instance.enemyType.enemyName))
				{
					EnemiesDataManager.RegisterEnemy(__instance.enemyType.enemyName, new EnemyData(Pickupable: true, 80, 250, 50f, "E"));
					Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + __instance.enemyType.enemyName + "'"));
				}
				if (NetworkManager.Singleton.IsHost)
				{
					EnemyData enemyData = Synchronizable<SyncedConfig>.Instance.EnemiesData[__instance.enemyType.enemyName];
					int mobValue = new Random().Next(enemyData.MinValue, enemyData.MaxValue);
					NetworkBehaviourReference netref = default(NetworkBehaviourReference);
					((NetworkBehaviourReference)(ref netref))..ctor((NetworkBehaviour)(object)__instance);
					Plugin.logger.LogInfo((object)"Synchronizing the mob data and scrap value with clients...");
					InstantiatePhysicPrefabServerRpc(netref, mobValue);
				}
				Plugin.logger.LogDebug((object)"Mob should now be grabbable for all users.");
			}
		}

		[ServerRpc]
		public static void InstantiatePhysicPrefabServerRpc(NetworkBehaviourReference netref, int mobValue)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI val = default(EnemyAI);
			if (!((NetworkBehaviourReference)(ref netref)).TryGet<EnemyAI>(ref val, (NetworkManager)null))
			{
				Plugin.logger.LogError((object)"Coudln't instantiate physic prop prefab: Invalid EnemyAI net behaviour reference");
				return;
			}
			if (!EnemiesDataManager.Enemies2Props.TryGetValue(val.enemyType.enemyName, out GameObject value))
			{
				Plugin.logger.LogWarning((object)("Mob " + val.enemyType.enemyName + " has no enemy2prop prefab."));
			}
			GameObject val2 = Object.Instantiate<GameObject>(value);
			val2.GetComponent<NetworkObject>().Spawn(false);
			NetworkObjectReference enemy2PropNetRef = default(NetworkObjectReference);
			((NetworkObjectReference)(ref enemy2PropNetRef))..ctor(val2);
			SynchronizeMobClientRpc(netref, enemy2PropNetRef, mobValue);
		}

		[ClientRpc]
		public static void SynchronizeMobClientRpc(NetworkBehaviourReference enemyNetRef, NetworkObjectReference enemy2PropNetRef, int mobValue)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI val = default(EnemyAI);
			if (!((NetworkBehaviourReference)(ref enemyNetRef)).TryGet<EnemyAI>(ref val, NetworkManager.Singleton))
			{
				Plugin.logger.LogError((object)"Couldn't synchronize the enemy among network: The network reference was invalid. Critical synchronization error. Can you even see that dead enemy ?");
				return;
			}
			NetworkObject val2 = default(NetworkObject);
			if (!((NetworkObjectReference)(ref enemy2PropNetRef)).TryGet(ref val2, (NetworkManager)null))
			{
				Plugin.logger.LogError((object)"Couldn't synchronize the enemy among network: The network object reference for Physic Props was invalid. Maybe it wasn't spawned correctly at first.");
				return;
			}
			GameObject gameObject = ((Component)val2).gameObject;
			gameObject.transform.position = ((Component)val).transform.position;
			EnemyData enemyData = Synchronizable<SyncedConfig>.Instance.EnemiesData[val.enemyType.enemyName];
			PhysicsProp val3 = default(PhysicsProp);
			if (!gameObject.TryGetComponent<PhysicsProp>(ref val3))
			{
				Plugin.logger.LogError((object)"Physic Prop Object did not have the PhysicsProp component. Make sure the component was correctly initialized before the game start.");
				return;
			}
			((GrabbableObject)val3).grabbable = enemyData.Pickupable;
			((GrabbableObject)val3).scrapValue = mobValue;
			GameObject gameObject2 = ((Component)gameObject.transform.Find("ScanNode")).gameObject;
			ScanNodeProperties component = gameObject2.GetComponent<ScanNodeProperties>();
			component.scrapValue = ((GrabbableObject)val3).scrapValue;
			component.subText = $"Rank:{enemyData.Rank}\nValue: ${component.scrapValue}";
			Animator componentInChildren = gameObject.GetComponentInChildren<Animator>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				try
				{
					componentInChildren.SetBool("Stunned", false);
					componentInChildren.SetBool("stunned", false);
					componentInChildren.SetBool("stun", false);
					componentInChildren.SetTrigger("KillEnemy");
					componentInChildren.SetBool("Dead", true);
				}
				catch (Exception arg)
				{
					Plugin.logger.LogWarning((object)$"Tried to set animation to 'Dead' state on enemy '{val.enemyType.enemyName}' but failed. Enemy has no dead state ? Probably a modded enemy. Error: {arg}");
				}
			}
			((Component)val).gameObject.GetComponent<NetworkObject>().Despawn(true);
			Plugin.logger.LogDebug((object)"Mob successfully synchronized among all clients ! It is now grabbable and sellable !");
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManager_Patches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void Start(GameNetworkManager __instance)
		{
			EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>();
			EnemyAI[] array2 = array;
			foreach (EnemyAI val in array2)
			{
				if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName))
				{
					EnemiesDataManager.RegisterEnemy(val.enemyType.enemyName, default(EnemyData));
					Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + val.enemyType.enemyName + "'"));
				}
			}
			EnemiesDataManager.SaveEnemiesData();
			EnemiesDataManager.EnsureEnemy2PropPrefabs();
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartDisconnect")]
		public static void StartDisconnect()
		{
			Synchronizable<SyncedConfig>.RevertSync();
		}
	}
	[HarmonyPatch(typeof(MaskedPlayerEnemy))]
	public class MaskedPlayerEnemy_Patches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(MaskedPlayerEnemy), "KillEnemyServerRpc")]
		private static void KillEnemyServerRpc(MaskedPlayerEnemy __instance, bool destroy)
		{
			Plugin.logger.LogInfo((object)"Hey. Spawn a mimic mask. now.");
		}
	}
	[HarmonyPatch(typeof(MenuManager))]
	public class MenuManager_Patches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(MenuManager), "Start")]
		private static void Start(MenuManager __instance)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (__instance == null)
			{
				Plugin.logger.LogError((object)"MenuManager instance is null. Something might have booted too early.");
				return;
			}
			TextMeshProUGUI versionNumberText = __instance.versionNumberText;
			((TMP_Text)versionNumberText).text = ((TMP_Text)versionNumberText).text + "\n<size=75%>Enhanced Monsters v1.0.4</size>";
			((Component)__instance.versionNumberText).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(500f, 50f);
			EnemyAI[] array = Resources.FindObjectsOfTypeAll<EnemyAI>();
			Plugin.logger.LogInfo((object)$"{array.Length} enemies to patch.");
			EnemyAI[] array2 = array;
			foreach (EnemyAI val in array2)
			{
				if (!Synchronizable<SyncedConfig>.Instance.EnemiesData.ContainsKey(val.enemyType.enemyName))
				{
					EnemiesDataManager.RegisterEnemy(val.enemyType.enemyName, default(EnemyData));
					Plugin.logger.LogInfo((object)("Mob was not registered. Registered it with name '" + val.enemyType.enemyName + "'"));
				}
			}
			EnemiesDataManager.SaveEnemiesData();
			EnemiesDataManager.EnsureEnemy2PropPrefabs();
			Plugin.logger.LogInfo((object)"All enemies have been patched correctly.");
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerB_Patches
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnRequestSync;

			public static HandleNamedMessageDelegate <1>__OnReceiveSync;
		}

		[HarmonyPostfix]
		[HarmonyPatch("ConnectClientToPlayerObject")]
		public static void InitializeLocalPlayer()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (Synchronizable<SyncedConfig>.IsHost)
			{
				CustomMessagingManager messagingManager = Synchronizable<SyncedConfig>.MessagingManager;
				object obj = <>O.<0>__OnRequestSync;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = SyncedConfig.OnRequestSync;
					<>O.<0>__OnRequestSync = val;
					obj = (object)val;
				}
				messagingManager.RegisterNamedMessageHandler("EnhancedMonsters_OnRequestConfigSync", (HandleNamedMessageDelegate)obj);
				Synchronizable<SyncedConfig>.Synced = true;
				return;
			}
			Synchronizable<SyncedConfig>.Synced = false;
			CustomMessagingManager messagingManager2 = Synchronizable<SyncedConfig>.MessagingManager;
			object obj2 = <>O.<1>__OnReceiveSync;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = SyncedConfig.OnReceiveSync;
				<>O.<1>__OnReceiveSync = val2;
				obj2 = (object)val2;
			}
			messagingManager2.RegisterNamedMessageHandler("EnhancedMonsters_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2);
			SyncedConfig.RequestSync();
		}
	}
}
namespace EnhancedMonsters.Monobehaviours
{
	public class EnemyScrap : GrabbableObject
	{
	}
}
namespace EnhancedMonsters.Config
{
	public class LocalConfig
	{
		private readonly bool SeamlessDungeonExists;

		public readonly ConfigEntry<bool> dungeonPreview;

		public readonly ConfigEntry<int> dungeonPreviewResolution;

		public readonly ConfigEntry<bool> dungeonSoundExchange;

		public readonly ConfigEntry<int> dungeonSoundExchangeVolume;

		public static LocalConfig Singleton { get; private set; }

		public LocalConfig(ConfigFile cfg)
		{
			//IL_00b5: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00e6: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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_012d: Expected O, but got Unknown
			//IL_0133: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_013a: 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)
			//IL_0158: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Expected O, but got Unknown
			//IL_01a1: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			Singleton = this;
			SeamlessDungeonExists = Chainloader.PluginInfos.ContainsKey("tsundrella.seamlessdungeon");
			dungeonPreview = cfg.Bind<bool>("Dungeon Preview", "EM_DungeonPreviewBoolText", (!SeamlessDungeonExists) ? true : false, "Wether or not to enable interior/exterior preview through Dungeon's doors windows. [NOTE: This may not work on some modded moons and interiors.]");
			dungeonPreviewResolution = cfg.Bind<int>("Dungeon Preview Resolution", "EM_DungeonPreviewResIntText", 512, "The dungeon preview uses cameras to render the exterior/interior. Reducing this will reduce preview quality but increase performance. [NOTE: Must be a multiple of 2.]");
			dungeonSoundExchange = cfg.Bind<bool>("Dungeon Sound Exchange", "EM_DungeonSoundExchangeBoolText", true, "Wether to enable or not sound exchange between interior and exterior of the dungeon, next to entrance and fire exits. Disabling it can enhance performance on weakest configurations.");
			dungeonSoundExchangeVolume = cfg.Bind<int>("Dungeon Sound Exchange Volume", "EM_DungeonSoundExchangeVolumeIntText", 70, "Volume level of sounds emitted from the interior/exterior when player is on the other side of the door.");
			LethalConfigManager.SetModDescription("Enhanced Monsters aims at enhancing experience towards monsters, but also has various QOL improvements.");
			BoolCheckBoxConfigItem val = new BoolCheckBoxConfigItem(dungeonPreview, new BoolCheckBoxOptions
			{
				Section = "Entrance Improvements",
				RequiresRestart = false,
				CanModifyCallback = (CanModifyDelegate)(() => CanModifyResult.op_Implicit(!SeamlessDungeonExists))
			});
			ConfigEntry<int> obj = dungeonPreviewResolution;
			IntSliderOptions val2 = new IntSliderOptions
			{
				Section = "Entrance Improvements"
			};
			((BaseRangeOptions<int>)val2).Min = 16;
			((BaseRangeOptions<int>)val2).Max = 1024;
			((BaseOptions)val2).RequiresRestart = true;
			((BaseOptions)val2).CanModifyCallback = (CanModifyDelegate)(() => CanModifyResult.op_Implicit(dungeonPreview.Value));
			IntSliderConfigItem val3 = new IntSliderConfigItem(obj, val2);
			BoolCheckBoxConfigItem val4 = new BoolCheckBoxConfigItem(dungeonSoundExchange, new BoolCheckBoxOptions
			{
				Section = "Entrance Improvements",
				RequiresRestart = false
			});
			ConfigEntry<int> obj2 = dungeonSoundExchangeVolume;
			IntSliderOptions val5 = new IntSliderOptions
			{
				Section = "Entrance Improvements"
			};
			((BaseRangeOptions<int>)val5).Min = 0;
			((BaseRangeOptions<int>)val5).Max = 100;
			((BaseOptions)val5).RequiresRestart = false;
			((BaseOptions)val5).CanModifyCallback = (CanModifyDelegate)(() => CanModifyResult.op_Implicit(dungeonSoundExchange.Value));
			IntSliderConfigItem val6 = new IntSliderConfigItem(obj2, val5);
			LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val);
			LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val3);
			LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val4);
			LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val6);
		}
	}
	[Serializable]
	public class SyncedConfig : Synchronizable<SyncedConfig>
	{
		public Dictionary<string, EnemyData> EnemiesData;

		[NonSerialized]
		public ConfigFile BepInConfigs;

		public SyncedConfig(ConfigFile cfg)
		{
			InitInstance(this);
			BepInConfigs = cfg;
			EnemiesData = EnemiesDataManager.EnemiesData;
		}

		public static void BroadcastSync()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (!Synchronizable<SyncedConfig>.IsHost)
			{
				return;
			}
			Plugin.logger.LogDebug((object)"Host is broadcasting its config.");
			byte[] array = Synchronizable<SyncedConfig>.Serialize(Synchronizable<SyncedConfig>.Instance);
			int num = array.Length;
			int num2 = checked(FastBufferWriter.GetWriteSize<byte>(array, -1, 0) + Synchronizable<SyncedConfig>.IntSize);
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(num2, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
				Synchronizable<SyncedConfig>.MessagingManager.SendNamedMessageToAll("EnhancedMonster_OnReceiveConfigSync", val, (NetworkDelivery)4);
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"The config sync broadcast lamentably failed lmao; here's the error: {arg}");
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public static void RequestSync()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!Synchronizable<SyncedConfig>.IsClient)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(Synchronizable<SyncedConfig>.IntSize, (Allocator)2, -1);
			try
			{
				Synchronizable<SyncedConfig>.MessagingManager.SendNamedMessage("EnhancedMonsters_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
				Plugin.logger.LogInfo((object)"Asking host for their EnemyData config");
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public static void OnRequestSync(ulong clientId, FastBufferReader _)
		{
			//IL_005e: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!Synchronizable<SyncedConfig>.IsHost)
			{
				return;
			}
			Plugin.logger.LogDebug((object)$"Config sync request received from client {clientId}");
			byte[] array = Synchronizable<SyncedConfig>.Serialize(Synchronizable<SyncedConfig>.Instance);
			int num = array.Length;
			int writeSize = FastBufferWriter.GetWriteSize<byte>(array, -1, 0);
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(checked(writeSize + Synchronizable<SyncedConfig>.IntSize), (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
				Synchronizable<SyncedConfig>.MessagingManager.SendNamedMessage("EnhancedMonsters_OnReceiveConfigSync", clientId, val, (NetworkDelivery)4);
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Coudln't sync configs between clients. Error: {arg}");
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public static void OnReceiveSync(ulong _, FastBufferReader reader)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (!((FastBufferReader)(ref reader)).TryBeginRead(Synchronizable<SyncedConfig>.IntSize))
			{
				Plugin.logger.LogError((object)"Config sync error: could not begin reading buffer.");
				return;
			}
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
			{
				Plugin.logger.LogError((object)$"Config sync error: Host could not sync. Error: The chunk of the buffer to read is larger than the remaining bytes chunk. {num} bytes to read, {checked(((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position)} remaining bytes");
				return;
			}
			byte[] data = new byte[num];
			((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
			Synchronizable<SyncedConfig>.SyncInstance(data);
			Plugin.logger.LogInfo((object)"Successfully synced config with host");
		}
	}
	[Serializable]
	public class Synchronizable<T>
	{
		[NonSerialized]
		protected static int IntSize = 4;

		internal static CustomMessagingManager MessagingManager => NetworkManager.Singleton.CustomMessagingManager;

		internal static bool IsClient
		{
			get
			{
				NetworkManager singleton = NetworkManager.Singleton;
				return singleton != null && singleton.IsClient;
			}
		}

		internal static bool IsHost
		{
			get
			{
				NetworkManager singleton = NetworkManager.Singleton;
				return singleton != null && singleton.IsHost;
			}
		}

		public static T Default { get; set; }

		public static T Instance { get; set; }

		public static bool Synced { get; internal set; }

		protected void InitInstance(T instance)
		{
			Default = instance;
			Instance = instance;
			IntSize = 4;
		}

		internal static void SyncInstance(byte[] data)
		{
			Instance = Deserialize(data);
			Synced = true;
		}

		internal static void RevertSync()
		{
			Instance = Default;
			Synced = false;
		}

		public static byte[] Serialize(T val)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			using MemoryStream memoryStream = new MemoryStream();
			try
			{
				binaryFormatter.Serialize(memoryStream, val);
				return memoryStream.ToArray();
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Error while serializing Config instance: {arg}");
				return null;
			}
		}

		public static T Deserialize(byte[] data)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			using MemoryStream serializationStream = new MemoryStream(data);
			try
			{
				return (T)binaryFormatter.Deserialize(serializationStream);
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Couldn't deserialize Config instance: {arg}");
				return default(T);
			}
		}
	}
}