Decompiled source of PaulMillerBug v1.1.1

PaulMillerBug/PaulMillerBug.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PaulMillerBug")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("PaulMillerBug")]
[assembly: AssemblyTitle("PaulMillerBug")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 PaulMillerBug
{
	[BepInPlugin("com.kale.paulmillerbug", "Paul Miller Bug", "1.1.0")]
	[BepInProcess("Lethal Company.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.kale.paulmillerbug";

		public const string PluginName = "Paul Miller Bug";

		public const string PluginVersion = "1.1.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> Volume;

		internal static readonly List<AudioClip> Clips = new List<AudioClip>();

		internal static bool ClipsLoaded;

		private static readonly HashSet<int> AppliedBugs = new HashSet<int>();

		private static Random rng = new Random();

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Paul Miller Bug sound replacement.");
			Volume = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Volume", 1f, new ConfigDescription("Volume multiplier applied to the hoarding bug's voice AudioSources when clips are applied.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			new Harmony("com.kale.paulmillerbug").PatchAll(Assembly.GetExecutingAssembly());
			Log.LogInfo((object)string.Format("{0} v{1} loaded. Enabled={2} Volume={3}", "Paul Miller Bug", "1.1.0", Enabled.Value, Volume.Value));
			GameObject val = new GameObject("PaulMillerBug_Loader");
			Object.DontDestroyOnLoad((Object)val);
			((MonoBehaviour)val.AddComponent<ClipLoader>()).StartCoroutine(LoadClips());
		}

		internal static string PluginFolder()
		{
			try
			{
				string location = Assembly.GetExecutingAssembly().Location;
				if (!string.IsNullOrEmpty(location))
				{
					return Path.GetDirectoryName(location);
				}
			}
			catch
			{
			}
			return Path.Combine(Paths.PluginPath, "PaulMillerBug");
		}

		private IEnumerator LoadClips()
		{
			string text = PluginFolder();
			Log.LogInfo((object)("Loading bug sounds from: " + text));
			string[] array = new string[0];
			try
			{
				array = Directory.GetFiles(text, "bug*.*");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not list plugin folder: " + ex.Message));
			}
			Array.Sort(array, (IComparer<string>?)StringComparer.OrdinalIgnoreCase);
			int attempted = 0;
			string[] array2 = array;
			foreach (string file in array2)
			{
				AudioType val;
				switch (Path.GetExtension(file).ToLowerInvariant())
				{
				case ".wav":
					val = (AudioType)20;
					break;
				case ".mp3":
					val = (AudioType)13;
					break;
				case ".ogg":
					val = (AudioType)14;
					break;
				default:
					continue;
				}
				attempted++;
				string text2 = "file://" + file.Replace("\\", "/");
				UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(text2, val);
				try
				{
					yield return req.SendWebRequest();
					if (!string.IsNullOrEmpty(req.error))
					{
						Log.LogError((object)("Failed to load " + Path.GetFileName(file) + ": " + req.error));
						continue;
					}
					AudioClip content = DownloadHandlerAudioClip.GetContent(req);
					if ((Object)(object)content == (Object)null)
					{
						Log.LogError((object)("Loaded clip was null: " + file));
						continue;
					}
					((Object)content).name = Path.GetFileNameWithoutExtension(file);
					Clips.Add(content);
					Log.LogInfo((object)$"Loaded {((Object)content).name} ({content.length:F2}s, {content.frequency}Hz, ch={content.channels})");
				}
				finally
				{
					((IDisposable)req)?.Dispose();
				}
			}
			ClipsLoaded = true;
			Log.LogInfo((object)$"Loaded {Clips.Count}/{attempted} bug clips.");
			LogGameVersion("after clip load");
			if (Enabled.Value && Clips.Count > 0)
			{
				ApplyToAllBugs("clip-loading-complete");
			}
		}

		internal static void ApplyToAllBugs(string reason)
		{
			int num = 0;
			try
			{
				HoarderBugAI[] array = Object.FindObjectsOfType<HoarderBugAI>();
				for (int i = 0; i < array.Length; i++)
				{
					if (ApplyToBug(array[i]))
					{
						num++;
					}
				}
				array = Resources.FindObjectsOfTypeAll<HoarderBugAI>();
				for (int i = 0; i < array.Length; i++)
				{
					if (ApplyToBug(array[i]))
					{
						num++;
					}
				}
			}
			catch (Exception arg)
			{
				Log.LogWarning((object)$"ApplyToAllBugs ({reason}) error: {arg}");
			}
			Log.LogInfo((object)$"Applied Paul Miller Bug clips to {num} HoarderBugAI instance(s) ({reason}). Total clips={Clips.Count}");
		}

		private static void SetField(object obj, string name, object value, List<string> ok)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name);
				if (fieldInfo == null)
				{
					Log.LogWarning((object)("HoarderBugAI." + name + " not found (game update?) - skipped"));
					return;
				}
				if (fieldInfo.FieldType.IsArray && !(value is Array))
				{
					value = new AudioClip[1] { (AudioClip)value };
				}
				else if (!fieldInfo.FieldType.IsArray && value is AudioClip[] array)
				{
					value = ((array.Length != 0) ? array[rng.Next(array.Length)] : null);
				}
				if (!fieldInfo.FieldType.IsAssignableFrom(value.GetType()))
				{
					Log.LogWarning((object)$"HoarderBugAI.{name} has type {fieldInfo.FieldType} - skipped");
					return;
				}
				fieldInfo.SetValue(obj, value);
				ok.Add(name);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Setting " + name + " failed: " + ex.Message));
			}
		}

		internal static void LogGameVersion(string when)
		{
			try
			{
				GameNetworkManager instance = GameNetworkManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					Log.LogInfo((object)$"Game version ({when}): v{instance.gameVersionNum}");
				}
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Game version not readable yet: " + ex.Message));
			}
		}

		internal static bool ApplyToBug(HoarderBugAI bug)
		{
			if ((Object)(object)bug == (Object)null || !Enabled.Value || Clips.Count == 0)
			{
				return false;
			}
			int instanceID;
			try
			{
				instanceID = ((Object)bug).GetInstanceID();
			}
			catch
			{
				return false;
			}
			if (AppliedBugs.Contains(instanceID))
			{
				return false;
			}
			try
			{
				AudioClip[] array = Clips.ToArray();
				List<string> list = new List<string>();
				SetField(bug, "chitterSFX", (AudioClip[])array.Clone(), list);
				SetField(bug, "angryScreechSFX", (AudioClip[])array.Clone(), list);
				SetField(bug, "angryVoiceSFX", Clips[rng.Next(Clips.Count)], list);
				SetField(bug, "hitPlayerSFX", Clips[rng.Next(Clips.Count)], list);
				try
				{
					if ((Object)(object)((EnemyAI)bug).creatureVoice != (Object)null)
					{
						((EnemyAI)bug).creatureVoice.volume = Mathf.Clamp(((EnemyAI)bug).creatureVoice.volume * Volume.Value, 0f, 1f);
					}
				}
				catch
				{
				}
				try
				{
					if ((Object)(object)((EnemyAI)bug).creatureSFX != (Object)null)
					{
						((EnemyAI)bug).creatureSFX.volume = Mathf.Clamp(((EnemyAI)bug).creatureSFX.volume * Volume.Value, 0f, 1f);
					}
				}
				catch
				{
				}
				AppliedBugs.Add(instanceID);
				Log.LogInfo((object)string.Format("Bug id={0}: replaced [{1}] with {2} clips. bugFlySFX left unchanged.", instanceID, string.Join(", ", list), array.Length));
				return true;
			}
			catch (Exception arg)
			{
				Log.LogWarning((object)$"ApplyToBug failed for id={instanceID}: {arg}");
				return false;
			}
		}
	}
	internal class ClipLoader : MonoBehaviour
	{
	}
	[HarmonyPatch(typeof(HoarderBugAI), "Start")]
	internal static class HoarderBugStartPatch
	{
		private static bool versionLogged;

		private static void Postfix(HoarderBugAI __instance)
		{
			if (!versionLogged)
			{
				versionLogged = true;
				Plugin.LogGameVersion("first bug spawn");
			}
			if (Plugin.ClipsLoaded)
			{
				Plugin.ApplyToBug(__instance);
			}
		}
	}
}