Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RedactedLootBug v1.0.2
BepInEx/plugins/RedactedLootBug/RedactedLootBug.dll
Decompiled 4 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; 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: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyVersion("1.0.2.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 RedactedLootBug { internal sealed class PcmWaveData { public readonly float[] Samples; public readonly int Channels; public readonly int SampleRate; public readonly int Frames; internal PcmWaveData(float[] samples, int channels, int sampleRate, int frames) { Samples = samples; Channels = channels; SampleRate = sampleRate; Frames = frames; } } internal static class PcmWaveReader { internal static PcmWaveData Read(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (bytes.Length < 12 || !HasId(bytes, 0, "RIFF") || !HasId(bytes, 8, "WAVE")) { throw Invalid("Expected a RIFF/WAVE file."); } long num = 8L + (long)U32(bytes, 4); if (num < 12 || num > bytes.Length) { throw Invalid("The RIFF length exceeds the available file data."); } int num2 = 0; int sampleRate = 0; int num3 = 0; int num4 = -1; int num5 = 0; bool flag = false; long num6 = 12L; while (num6 < num) { if (num - num6 < 8) { throw Invalid("A WAV chunk header is truncated."); } int num7 = (int)num6; uint num8 = U32(bytes, num7 + 4); long num9 = num6 + 8; long num10 = num9 + num8; long num11 = num10 + (num8 & 1); if (num10 > num || num11 > num) { throw Invalid("A WAV chunk or its padding exceeds the RIFF bounds."); } if (HasId(bytes, num7, "fmt ")) { if (flag) { throw Invalid("Multiple WAV format chunks are not supported."); } if (num8 < 16) { throw Invalid("The WAV format chunk is truncated."); } int num12 = (int)num9; int num13 = U16(bytes, num12); num2 = U16(bytes, num12 + 2); uint num14 = U32(bytes, num12 + 4); uint num15 = U32(bytes, num12 + 8); num3 = U16(bytes, num12 + 12); int num16 = U16(bytes, num12 + 14); if (num13 != 1 || num16 != 16) { throw Invalid("Only uncompressed signed 16-bit PCM WAV audio is supported."); } if (num2 == 0 || num14 == 0 || num14 > int.MaxValue) { throw Invalid("The WAV channel count or sample rate is invalid."); } if (num3 != num2 * 2 || num14 * num3 != num15) { throw Invalid("The WAV block alignment or byte rate is invalid."); } sampleRate = (int)num14; flag = true; } else if (HasId(bytes, num7, "data")) { if (num4 >= 0) { throw Invalid("Multiple WAV data chunks are not supported."); } num4 = (int)num9; num5 = (int)num8; } num6 = num11; } if (!flag || num4 < 0) { throw Invalid("The WAV requires format and data chunks."); } if (num5 == 0 || num5 % num3 != 0) { throw Invalid("The WAV data is empty or does not contain complete sample frames."); } float[] array = new float[num5 / 2]; int num17 = 0; int num18 = num4; while (num17 < array.Length) { short num19 = (short)U16(bytes, num18); array[num17] = (float)num19 / 32768f; num17++; num18 += 2; } return new PcmWaveData(array, num2, sampleRate, num5 / num3); } private static bool HasId(byte[] bytes, int offset, string id) { if (bytes[offset] == id[0] && bytes[offset + 1] == id[1] && bytes[offset + 2] == id[2]) { return bytes[offset + 3] == id[3]; } return false; } private static int U16(byte[] bytes, int offset) { return bytes[offset] | (bytes[offset + 1] << 8); } private static uint U32(byte[] bytes, int offset) { return (uint)(bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)); } private static InvalidDataException Invalid(string message) { return new InvalidDataException(message); } } [BepInPlugin("madjack.redactedlootbug", "Redacted Loot Bug", "1.0.2")] public sealed class RedactedLootBugPlugin : BaseUnityPlugin { public const string PluginGuid = "madjack.redactedlootbug"; private static ManualLogSource _log; private readonly List<AudioClip> _ownedClips = new List<AudioClip>(); private Harmony _harmony; private Type _bugType; private static FieldInfo _chitterField; private MethodInfo _startMethod; private MethodInfo _detectMethod; private static AudioClip[] _chatterClips = Array.Empty<AudioClip>(); private static bool _reportedApplyError; private static bool _reportedApplySuccess; public void Awake() { _log = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Initializing Redacted Loot Bug 1.0.2."); try { _bugType = AccessTools.TypeByName("HoarderBugAI"); _chitterField = ((_bugType == null) ? null : AccessTools.Field(_bugType, "chitterSFX")); _startMethod = ((_bugType == null) ? null : AccessTools.DeclaredMethod(_bugType, "Start", Type.EmptyTypes, (Type[])null)); _detectMethod = ((_bugType == null) ? null : AccessTools.DeclaredMethod(_bugType, "DetectAndLookAtPlayers", Type.EmptyTypes, (Type[])null)); if (_chitterField == null || _chitterField.FieldType != typeof(AudioClip[]) || _startMethod == null || _detectMethod == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Hoarding Bug chatter methods/field were not found. Sound replacement is disabled; check game compatibility."); return; } string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Audio", "Chatter"); Directory.CreateDirectory(text); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Reading chatter from: " + text)); string[] source = Directory.GetFiles(text).OrderBy<string, string>((string path) => path, StringComparer.OrdinalIgnoreCase).ToArray(); foreach (string item in source.Where(IsWave)) { LoadPcmWave(item); } PublishClips(); string[] array = source.Where((string path) => string.Equals(Path.GetExtension(path), ".ogg", StringComparison.OrdinalIgnoreCase)).ToArray(); if (array.Length != 0) { ((MonoBehaviour)this).StartCoroutine(LoadOgg(array)); } else if (_chatterClips.Length == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No valid chatter clips found. Original game chatter is preserved."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not initialize Redacted Loot Bug: " + ex)); } } private static bool IsWave(string path) { string extension = Path.GetExtension(path); if (!string.Equals(extension, ".wav", StringComparison.OrdinalIgnoreCase)) { return string.Equals(extension, ".wave", StringComparison.OrdinalIgnoreCase); } return true; } private void LoadPcmWave(string path) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) AudioClip val = null; try { PcmWaveData pcmWaveData = PcmWaveReader.Read(File.ReadAllBytes(path)); val = AudioClip.Create("RedactedLootBug_" + Path.GetFileNameWithoutExtension(path), pcmWaveData.Frames, pcmWaveData.Channels, pcmWaveData.SampleRate, false); if ((Object)(object)val == (Object)null || !val.SetData(pcmWaveData.Samples, 0)) { throw new InvalidDataException("Unity could not populate the audio clip."); } if ((int)val.loadState != 2) { throw new InvalidDataException("Unity audio clip is not ready: " + ((object)val.loadState/*cast due to .constrained prefix*/).ToString()); } AudioClip obj = val; ((Object)obj).hideFlags = (HideFlags)(((Object)obj).hideFlags | 0x20); _ownedClips.Add(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Decoded " + Path.GetFileName(path) + ": " + pcmWaveData.Frames + " frames, " + pcmWaveData.Channels + " channels, " + pcmWaveData.SampleRate + " Hz, state=" + ((object)val.loadState/*cast due to .constrained prefix*/).ToString() + ".")); } catch (Exception ex) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } ((BaseUnityPlugin)this).Logger.LogError((object)("Could not load " + Path.GetFileName(path) + ": " + ex)); } } private IEnumerator LoadOgg(string[] files) { foreach (string path in files) { UnityWebRequest request = null; UnityWebRequestAsyncOperation val; try { request = UnityWebRequestMultimedia.GetAudioClip(new Uri(Path.GetFullPath(path)).AbsoluteUri, (AudioType)14); request.timeout = 30; val = request.SendWebRequest(); } catch (Exception ex) { if (request != null) { request.Dispose(); } ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not open " + Path.GetFileName(path) + ": " + ex.Message)); continue; } UnityWebRequest val2 = request; try { yield return val; if ((int)request.result != 1) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not load " + Path.GetFileName(path) + ": " + request.error)); continue; } AudioClip content; try { content = DownloadHandlerAudioClip.GetContent(request); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not decode " + Path.GetFileName(path) + ": " + ex2.Message)); goto end_IL_00ea; } if ((Object)(object)content == (Object)null || content.samples <= 0 || (int)content.loadState != 2) { if ((Object)(object)content != (Object)null) { Object.Destroy((Object)(object)content); } ((BaseUnityPlugin)this).Logger.LogWarning((object)("Skipping empty or unready OGG clip: " + Path.GetFileName(path))); } else { ((Object)content).name = "RedactedLootBug_" + Path.GetFileNameWithoutExtension(path); ((Object)content).hideFlags = (HideFlags)(((Object)content).hideFlags | 0x20); _ownedClips.Add(content); } end_IL_00ea:; } finally { ((IDisposable)val2)?.Dispose(); } } PublishClips(); if (_chatterClips.Length == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No valid chatter clips found. Original game chatter is preserved."); } } private void PublishClips() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown if (_ownedClips.Count != 0) { _chatterClips = _ownedClips.ToArray(); if (_harmony == null) { _harmony = new Harmony("madjack.redactedlootbug"); HarmonyMethod val = new HarmonyMethod(typeof(RedactedLootBugPlugin), "HoarderStartPrefix", (Type[])null); val.priority = 800; _harmony.Patch((MethodBase)_startMethod, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val2 = new HarmonyMethod(typeof(RedactedLootBugPlugin), "HoarderDetectPrefix", (Type[])null); val2.priority = 0; _harmony.Patch((MethodBase)_detectMethod, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Patched " + _bugType.Assembly.GetName().Name + ": HoarderBugAI.Start and DetectAndLookAtPlayers.")); } Object[] array = Object.FindObjectsOfType(_bugType); for (int i = 0; i < array.Length; i++) { ApplyChatter(array[i], "existing bug scan"); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded " + _chatterClips.Length + " chatter clip(s). Only normal Hoarding Bug chatter is replaced.")); } } private static void HoarderStartPrefix(object __instance) { ApplyChatter(__instance, "Start prefix"); } private static void HoarderDetectPrefix(object __instance) { ApplyChatter(__instance, "chatter detection prefix"); } private static void ApplyChatter(object bug, string reason) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (bug == null || _chatterClips.Length == 0) { return; } try { if (_chitterField.GetValue(bug) != _chatterClips) { _chitterField.SetValue(bug, _chatterClips); } if (!_reportedApplySuccess) { _reportedApplySuccess = true; _log.LogInfo((object)("Applied custom chatter to a Hoarding Bug (" + reason + "); first clip=" + ((Object)_chatterClips[0]).name + ", state=" + ((object)_chatterClips[0].loadState/*cast due to .constrained prefix*/).ToString() + ".")); } } catch (Exception ex) { if (!_reportedApplyError) { _reportedApplyError = true; _log.LogError((object)("Could not replace Hoarding Bug chatter: " + ex)); } } } } }