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);
}
}
}
}