Decompiled source of TidyLogs v1.0.0

Plugins/TidyLogs.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Logging;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using TidyLogs;
using UIFramework;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "TidyLogs", "1.0.0", "Supercopia", null)]
[assembly: MelonPriority(-1000)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TidyLogs")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TidyLogs")]
[assembly: AssemblyTitle("TidyLogs")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 TidyLogs
{
	internal static class BundleLoader
	{
		private static GameObject? _bundleRoot;

		public static GameObject? TextFixedPrefab { get; private set; }

		public static GameObject? DropdownDynamicPrefab { get; private set; }

		public static void Load()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("TidyLogs.Assets.tidylogs_ui");
			if (stream == null)
			{
				Core.Log.Warning("BundleLoader: embedded bundle not found.");
				return;
			}
			MemoryStream val = new MemoryStream();
			byte[] array = new byte[4096];
			Il2CppStructArray<byte> val2 = new Il2CppStructArray<byte>(array);
			int num;
			while ((num = stream.Read(array, 0, array.Length)) > 0)
			{
				val2 = Il2CppStructArray<byte>.op_Implicit(array);
				((Stream)val).Write(val2, 0, num);
			}
			((Stream)val).Flush();
			AssetBundle val3 = AssetBundle.LoadFromStream((Stream)(object)val);
			((Stream)val).Close();
			if ((Object)(object)val3 == (Object)null)
			{
				Core.Log.Warning("BundleLoader: failed to load asset bundle.");
				return;
			}
			_bundleRoot = val3.LoadAsset<GameObject>("UIframework");
			val3.Unload(false);
			if ((Object)(object)_bundleRoot == (Object)null)
			{
				Core.Log.Warning("BundleLoader: UIframework asset not found in bundle.");
				return;
			}
			_bundleRoot = Object.Instantiate<GameObject>(_bundleRoot);
			_bundleRoot.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_bundleRoot);
			foreach (Transform componentsInChild in _bundleRoot.GetComponentsInChildren<Transform>(true))
			{
				if (((Object)componentsInChild).name == "PrefEntryTextFixed")
				{
					TextFixedPrefab = ((Component)componentsInChild).gameObject;
				}
				else if (((Object)componentsInChild).name == "PrefEntryDropdownDynamic")
				{
					DropdownDynamicPrefab = ((Component)componentsInChild).gameObject;
				}
			}
			if ((Object)(object)TextFixedPrefab != (Object)null)
			{
				TextFixedPrefab.AddComponent<PrefText>();
			}
			if ((Object)(object)DropdownDynamicPrefab != (Object)null)
			{
				DropdownDynamicPrefab.AddComponent<PrefDropDown>();
			}
			Core.Log.Msg($"BundleLoader: TextFixed={(Object)(object)TextFixedPrefab != (Object)null}, DropdownDynamic={(Object)(object)DropdownDynamicPrefab != (Object)null}");
		}
	}
	public class Core : MelonPlugin
	{
		internal static Instance Log;

		public override void OnEarlyInitializeMelon()
		{
			Log = ((MelonBase)this).LoggerInstance;
			try
			{
				Config.Load();
				LogFilter.Install();
				Log.Msg($"TidyLogs installed — prefChatter={Config.SuppressPrefChatter}, modMode={Config.ModMode}, pluginMode={Config.PluginMode}, il2cppMsg={Config.SuppressIl2CppMessages}, il2cppWarn={Config.SuppressIl2CppWarnings}, warnings={Config.SuppressedWarnings.Count}.");
			}
			catch (Exception value)
			{
				Log.Error($"TidyLogs install failed: {value}");
			}
		}

		public override void OnApplicationStarted()
		{
			try
			{
				RegisterUIFramework();
			}
			catch (Exception)
			{
			}
		}

		private void RegisterUIFramework()
		{
			BundleLoader.Load();
			MelonPreferences_Category category = MelonPreferences.GetCategory("TidyLogs");
			if (category == null)
			{
				return;
			}
			ModelMod val = UI.Register((MelonBase)(object)this, (MelonPreferences_Category[])(object)new MelonPreferences_Category[1] { category });
			ModelMelonCategory val2 = ((SelectableModelBase)val).SubModels.OfType<ModelMelonCategory>().FirstOrDefault();
			if (val2 != null)
			{
				((SelectableModelBase)val2).SubModels.RemoveAll(delegate(IModelable m)
				{
					ModelMelonEntry val3 = (ModelMelonEntry)(object)((m is ModelMelonEntry) ? m : null);
					return val3 != null && val3.PrefEntry.BoxedValue is List<string>;
				});
			}
			NukeUI.Build(val);
		}

		public override void OnDeinitializeMelon()
		{
			Log.Msg($"TidyLogs: {LogFilter.SuppressedCount} line(s) suppressed this session.");
		}
	}
	internal static class Config
	{
		public enum LoadMode
		{
			Verbose,
			Trimmed,
			OneLinePer,
			SingleLine
		}

		internal static MelonPreferences_Category? Category;

		internal static MelonPreferences_Entry<List<string>>? NukedLinesEntry;

		private static readonly List<string> DefaultPrefPatterns = new List<string> { "MelonPreferences Loaded from", "MelonPreferences Saved to", "Preferences Loaded!", "Preferences Saved!" };

		private static readonly List<string> DefaultIl2CppPatterns = new List<string> { "Registered mono type ", "has unsupported return type", "has unsupported parameter", "Class::Init signatures have been exhausted" };

		private static readonly List<string> DefaultWarnings = new List<string> { "THIS WARNING IS NOT BUG" };

		public static bool SuppressPrefChatter { get; private set; } = true;


		public static List<string> PrefChatterPatterns { get; private set; } = new List<string>();


		public static LoadMode ModMode { get; private set; } = LoadMode.Verbose;


		public static LoadMode PluginMode { get; private set; } = LoadMode.Verbose;


		public static bool SuppressIl2CppMessages { get; private set; } = true;


		public static bool SuppressIl2CppWarnings { get; private set; } = true;


		public static List<string> Il2CppNoisePatterns { get; private set; } = new List<string>();


		public static List<string> SuppressedWarnings { get; private set; } = new List<string>();


		public static List<string> NukedLines { get; set; } = new List<string>();


		public static void Load()
		{
			MelonPreferences_Category val = MelonPreferences.CreateCategory("TidyLogs", "TidyLogs");
			val.SetFilePath("UserData/TidyLogs.cfg", true, false);
			MelonPreferences_Entry<bool> val2 = val.CreateEntry<bool>("SuppressPrefChatter", true, (string)null, "Master toggle for MelonPreferences load/save chatter suppression.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<List<string>> val3 = val.CreateEntry<List<string>>("PrefChatterPatterns", DefaultPrefPatterns, (string)null, "Substrings matched against normal (white) log messages. When SuppressPrefChatter is true, any message containing one of these substrings is dropped.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<string> val4 = val.CreateEntry<string>("ModMode", "Verbose", (string)null, "Mod load output verbosity. Verbose keeps MelonLoader's default output. Trimmed removes the opening separator per mod (4 lines instead of 5, Lum-compatible).", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<string> val5 = val.CreateEntry<string>("PluginMode", "Verbose", (string)null, "Plugin load output verbosity. Same values as ModMode.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<bool> val6 = val.CreateEntry<bool>("SuppressIl2CppMessages", true, (string)null, "Suppress normal (white) [Il2CppInterop] log messages that match Il2CppNoisePatterns. These are type registration confirmations and internal housekeeping notes with no actionable information.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<bool> val7 = val.CreateEntry<bool>("SuppressIl2CppWarnings", true, (string)null, "Suppress warning-level (yellow) [Il2CppInterop] messages that match Il2CppNoisePatterns. These warn that a specific method bridge could not be generated because the signature references an un-injected managed type; almost always safe to ignore for mod users, occasionally relevant when developing a mod that relies on Unity or native code invoking that specific method.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<List<string>> val8 = val.CreateEntry<List<string>>("Il2CppNoisePatterns", DefaultIl2CppPatterns, (string)null, "Substrings matched against [Il2CppInterop] messages and warnings. A message is suppressed if (a) its section is 'Il2CppInterop', (b) it contains any of these substrings, and (c) the corresponding SuppressIl2CppMessages / SuppressIl2CppWarnings toggle is true.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<List<string>> val9 = val.CreateEntry<List<string>>("SuppressedWarnings", DefaultWarnings, (string)null, "Substrings matched against warning and error messages regardless of section. Matching entries are dropped entirely (including any embedded stack trace in the same message). Be conservative here — real warnings may contain useful information.", false, false, (ValueValidator)null, (string)null);
			MelonPreferences_Entry<List<string>> val10 = val.CreateEntry<List<string>>("NukedLines", new List<string>(), (string)null, "Exact-match lines to suppress. Managed via the NUKE tab in UIFramework, or edit directly here.", false, false, (ValueValidator)null, (string)null);
			Category = val;
			NukedLinesEntry = val10;
			((MelonPreferences_Entry)val2).Description = "Master toggle for MelonPreferences load/save chatter suppression.";
			((MelonPreferences_Entry)val3).Description = "Substrings matched against normal (white) log messages. When SuppressPrefChatter is true, any message containing one of these substrings is dropped.";
			((MelonPreferences_Entry)val4).Description = "Mod load output verbosity. Allowed values: Verbose | Trimmed. Verbose keeps MelonLoader's default output. Trimmed removes the closing separator per mod block (4 lines instead of 5, Lum-compatible).";
			((MelonPreferences_Entry)val5).Description = "Plugin load output verbosity. Same values as ModMode.";
			((MelonPreferences_Entry)val6).Description = "Suppress normal (white) [Il2CppInterop] log messages that match Il2CppNoisePatterns. These are type registration confirmations and internal housekeeping notes with no actionable information.";
			((MelonPreferences_Entry)val7).Description = "Suppress warning-level (yellow) [Il2CppInterop] messages that match Il2CppNoisePatterns. These warn that a specific method bridge could not be generated because the signature references an un-injected managed type; almost always safe to ignore for mod users, occasionally relevant when developing a mod that relies on Unity or native code invoking that specific method.";
			((MelonPreferences_Entry)val8).Description = "Substrings matched against [Il2CppInterop] messages and warnings. A message is suppressed if (a) its section is 'Il2CppInterop', (b) it contains any of these substrings, and (c) the corresponding SuppressIl2CppMessages / SuppressIl2CppWarnings toggle is true.";
			((MelonPreferences_Entry)val9).Description = "Substrings matched against warning and error messages regardless of section. Matching entries are dropped entirely (including any embedded stack trace in the same message). Be conservative here — real warnings may contain useful information.";
			((MelonPreferences_Entry)val10).Description = "Exact-match lines to suppress. Managed via the NUKE tab in UIFramework, or edit directly here.";
			SuppressPrefChatter = val2.Value;
			PrefChatterPatterns = val3.Value ?? new List<string>();
			ModMode = (Enum.TryParse<LoadMode>(val4.Value, ignoreCase: true, out var result) ? result : LoadMode.Verbose);
			PluginMode = (Enum.TryParse<LoadMode>(val5.Value, ignoreCase: true, out var result2) ? result2 : LoadMode.Verbose);
			SuppressIl2CppMessages = val6.Value;
			SuppressIl2CppWarnings = val7.Value;
			Il2CppNoisePatterns = val8.Value ?? new List<string>();
			SuppressedWarnings = val9.Value ?? new List<string>();
			NukedLines = val10.Value ?? new List<string>();
		}
	}
	internal static class LogFilter
	{
		private enum Phase
		{
			Unknown,
			Plugins,
			Mods
		}

		private enum BlockState
		{
			Idle,
			HoldingSeparator,
			InBlock,
			TrimmedBlock
		}

		private readonly struct CollectedMod
		{
			public readonly string Name;

			public readonly string Version;

			public readonly string Author;

			public readonly ColorARGB NameColor;

			public readonly ColorARGB AuthorColor;

			public CollectedMod(string name, string version, string author, ColorARGB nameColor, ColorARGB authorColor)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				Name = name;
				Version = version;
				Author = author;
				NameColor = nameColor;
				AuthorColor = authorColor;
			}
		}

		private const string Separator = "------------------------------";

		private const string Il2CppSection = "Il2CppInterop";

		private const string AssemblyLinePrefix = "Assembly: ";

		private const string AuthorPrefix = "by ";

		private const string LoadingPluginsLine = "Loading Plugins...";

		private const string LoadingModsLine = "Loading Mods...";

		private static Delegate _origLogMsg = null;

		private static Delegate _origLogMelonInfo = null;

		private static Delegate _origLogError = null;

		private static ColorARGB _defaultMelonColor;

		private static ColorARGB _defaultTextColor;

		private static readonly object _gate = new object();

		private static Phase _phase = Phase.Unknown;

		private static BlockState _state = BlockState.Idle;

		private static ColorARGB _heldSeparatorColor;

		private static string? _capturedName;

		private static string? _capturedVersion;

		private static string? _capturedAuthor;

		private static ColorARGB _capturedNameColor;

		private static ColorARGB _capturedAuthorColor;

		private static readonly List<CollectedMod> _collected = new List<CollectedMod>();

		public static int SuppressedCount;

		private const string Reset = "\u001b[0m";

		public static void Install()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Assembly assembly = typeof(MelonLogger).Assembly;
			_defaultMelonColor = (ColorARGB)typeof(MelonLogger).GetField("DefaultMelonColor", BindingFlags.Static | BindingFlags.Public).GetValue(null);
			_defaultTextColor = (ColorARGB)typeof(MelonLogger).GetField("DefaultTextColor", BindingFlags.Static | BindingFlags.Public).GetValue(null);
			Type type = assembly.GetType("MelonLoader.InternalUtils.BootstrapInterop");
			PropertyInfo property = type.GetProperty("Library", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			object value = property.GetValue(null);
			Type type2 = value.GetType();
			_origLogMsg = SwapField(value, type2, "<LogMsg>k__BackingField", "FilteredLogMsg");
			_origLogMelonInfo = SwapField(value, type2, "<LogMelonInfo>k__BackingField", "FilteredLogMelonInfo");
			_origLogError = SwapField(value, type2, "<LogError>k__BackingField", "FilteredLogError");
			_phase = Phase.Plugins;
		}

		private static Delegate SwapField(object library, Type libraryType, string fieldName, string filterMethodName)
		{
			FieldInfo fieldInfo = libraryType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new InvalidOperationException(fieldName + " not found");
			Delegate @delegate = (Delegate)fieldInfo.GetValue(library);
			Type type = @delegate.GetType();
			MethodInfo method = typeof(LogFilter).GetMethod(filterMethodName, BindingFlags.Static | BindingFlags.NonPublic);
			Delegate value = Delegate.CreateDelegate(type, method);
			fieldInfo.SetValue(library, value);
			return @delegate;
		}

		private static void EmitSingleLineSummary()
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (_collected.Count == 0)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			for (int i = 0; i < _collected.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
					stringBuilder2.Append(", ");
				}
				CollectedMod collectedMod = _collected[i];
				stringBuilder.Append(Ansi(collectedMod.NameColor)).Append(collectedMod.Name).Append("\u001b[0m")
					.Append(' ')
					.Append(collectedMod.Version);
				stringBuilder2.Append(collectedMod.Name).Append(' ').Append(collectedMod.Version);
				if (!string.IsNullOrEmpty(collectedMod.Author))
				{
					stringBuilder.Append(" by ").Append(Ansi(collectedMod.AuthorColor)).Append(collectedMod.Author)
						.Append("\u001b[0m");
					stringBuilder2.Append(" by ").Append(collectedMod.Author);
				}
			}
			EmitOriginalMsgColored(stringBuilder.ToString(), stringBuilder2.ToString(), _defaultTextColor);
			_collected.Clear();
		}

		private static Config.LoadMode CurrentMode()
		{
			Phase phase = _phase;
			if (1 == 0)
			{
			}
			Config.LoadMode result = phase switch
			{
				Phase.Plugins => Config.PluginMode, 
				Phase.Mods => Config.ModMode, 
				_ => Config.LoadMode.Verbose, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private unsafe static void FilteredLogMsg(ColorARGB* msgColor, string msg, int msgLength, ColorARGB* sectionColor, string section, int sectionLength, string strippedMsg, int strippedMsgLength)
		{
			if (msg != null)
			{
				if (Config.SuppressPrefChatter && ContainsAny(msg, Config.PrefChatterPatterns))
				{
					SuppressedCount++;
					return;
				}
				if (Config.SuppressIl2CppMessages && section == "Il2CppInterop" && ContainsAny(msg, Config.Il2CppNoisePatterns))
				{
					SuppressedCount++;
					return;
				}
				if (Config.NukedLines.Count > 0 && IsNuked(msg, section))
				{
					SuppressedCount++;
					return;
				}
				if (msg == "Loading Plugins...")
				{
					lock (_gate)
					{
						_phase = Phase.Plugins;
					}
				}
				else if (msg == "Loading Mods...")
				{
					lock (_gate)
					{
						_phase = Phase.Mods;
					}
				}
				Config.LoadMode loadMode = CurrentMode();
				if (loadMode != 0)
				{
					if (HandleModLoadLine(msg, msgColor, loadMode))
					{
						SuppressedCount++;
						return;
					}
					if (loadMode == Config.LoadMode.SingleLine && (msg.EndsWith(" Plugins loaded.", StringComparison.Ordinal) || msg.EndsWith(" Plugin loaded.", StringComparison.Ordinal) || msg.EndsWith(" Mods loaded.", StringComparison.Ordinal) || msg.EndsWith(" Mod loaded.", StringComparison.Ordinal)))
					{
						lock (_gate)
						{
							EmitSingleLineSummary();
						}
					}
				}
			}
			_origLogMsg.DynamicInvoke(Pointer.Box(msgColor, typeof(ColorARGB*)), msg, msgLength, Pointer.Box(sectionColor, typeof(ColorARGB*)), section, sectionLength, strippedMsg, strippedMsgLength);
		}

		private static bool IsNuked(string msg, string? section)
		{
			string item = ((section != null) ? ("[" + section + "] " + msg) : msg);
			return Config.NukedLines.Contains(item);
		}

		private static bool ContainsAny(string msg, List<string> needles)
		{
			for (int i = 0; i < needles.Count; i++)
			{
				string value = needles[i];
				if (!string.IsNullOrEmpty(value) && msg.Contains(value, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private unsafe static bool HandleModLoadLine(string msg, ColorARGB* msgColor, Config.LoadMode mode)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			lock (_gate)
			{
				if (msg == "------------------------------")
				{
					return HandleSeparator(msgColor, mode);
				}
				switch (_state)
				{
				case BlockState.HoldingSeparator:
					FlushHeldSeparator();
					_state = BlockState.Idle;
					return false;
				case BlockState.TrimmedBlock:
					return false;
				case BlockState.InBlock:
					if (msg.StartsWith("by ", StringComparison.Ordinal))
					{
						_capturedAuthor = msg.Substring("by ".Length);
						_capturedAuthorColor = ((msgColor != null) ? (*msgColor) : _defaultMelonColor);
						return true;
					}
					if (msg.StartsWith("Assembly: ", StringComparison.Ordinal))
					{
						return true;
					}
					FlushAbandoned(mode);
					return false;
				default:
					return false;
				}
			}
		}

		private unsafe static bool HandleSeparator(ColorARGB* msgColor, Config.LoadMode mode)
		{
			switch (_state)
			{
			case BlockState.InBlock:
				EmitCompactLine(mode);
				_state = BlockState.Idle;
				return true;
			case BlockState.TrimmedBlock:
				SuppressedCount++;
				_state = BlockState.Idle;
				return true;
			case BlockState.HoldingSeparator:
				FlushHeldSeparator();
				CaptureHeldSeparator(msgColor);
				return true;
			default:
				CaptureHeldSeparator(msgColor);
				_state = BlockState.HoldingSeparator;
				return true;
			}
		}

		private unsafe static void CaptureHeldSeparator(ColorARGB* msgColor)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			_heldSeparatorColor = ((msgColor != null) ? (*msgColor) : _defaultMelonColor);
		}

		private unsafe static void FilteredLogMelonInfo(ColorARGB* nameColor, string name, int nameLength, string info, int infoLength)
		{
			Config.LoadMode loadMode = CurrentMode();
			if (loadMode != 0 && name != null)
			{
				if (loadMode == Config.LoadMode.Trimmed)
				{
					lock (_gate)
					{
						if (_state == BlockState.HoldingSeparator)
						{
							FlushHeldSeparator();
							_state = BlockState.TrimmedBlock;
						}
					}
				}
				else if (CaptureNameLine(name, info, nameColor))
				{
					SuppressedCount++;
					return;
				}
			}
			_origLogMelonInfo.DynamicInvoke(Pointer.Box(nameColor, typeof(ColorARGB*)), name, nameLength, info, infoLength);
		}

		private unsafe static bool CaptureNameLine(string name, string info, ColorARGB* nameColor)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			lock (_gate)
			{
				if (_state != BlockState.HoldingSeparator)
				{
					return false;
				}
				_capturedName = name;
				_capturedVersion = info ?? "";
				_capturedNameColor = ((nameColor != null) ? (*nameColor) : _defaultMelonColor);
				_state = BlockState.InBlock;
				return true;
			}
		}

		private static void FilteredLogError(string msg, int msgLength, string section, int sectionLength, bool warning)
		{
			if (msg != null)
			{
				if (ContainsAny(msg, Config.SuppressedWarnings))
				{
					SuppressedCount++;
					return;
				}
				if (Config.SuppressIl2CppWarnings && section == "Il2CppInterop" && ContainsAny(msg, Config.Il2CppNoisePatterns))
				{
					SuppressedCount++;
					return;
				}
				if (Config.NukedLines.Count > 0 && IsNuked(msg, section))
				{
					SuppressedCount++;
					return;
				}
			}
			_origLogError.DynamicInvoke(msg, msgLength, section, sectionLength, warning);
		}

		private static string Ansi(ColorARGB c)
		{
			return $"\u001b[38;2;{((ColorARGB)(ref c)).R};{((ColorARGB)(ref c)).G};{((ColorARGB)(ref c)).B}m";
		}

		private static void EmitCompactLine(Config.LoadMode mode)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			if (_capturedName == null)
			{
				ClearCapture();
				return;
			}
			string capturedName = _capturedName;
			string text = _capturedVersion ?? "";
			string text2 = _capturedAuthor ?? "";
			ColorARGB capturedNameColor = _capturedNameColor;
			ColorARGB capturedAuthorColor = _capturedAuthorColor;
			switch (mode)
			{
			case Config.LoadMode.OneLinePer:
			{
				string coloredMsg = (string.IsNullOrEmpty(text2) ? $"{Ansi(capturedNameColor)}{capturedName}{"\u001b[0m"} {text}" : $"{Ansi(capturedNameColor)}{capturedName}{"\u001b[0m"} {text} by {Ansi(capturedAuthorColor)}{text2}{"\u001b[0m"}");
				string strippedMsg = (string.IsNullOrEmpty(text2) ? (capturedName + " " + text) : $"{capturedName} {text} by {text2}");
				EmitOriginalMsgColored(coloredMsg, strippedMsg, _defaultTextColor);
				break;
			}
			case Config.LoadMode.SingleLine:
				_collected.Add(new CollectedMod(capturedName, text, text2, capturedNameColor, capturedAuthorColor));
				break;
			}
			ClearCapture();
		}

		private static void FlushAbandoned(Config.LoadMode mode)
		{
			if (_capturedName != null)
			{
				EmitCompactLine(mode);
			}
			ClearCapture();
			_state = BlockState.Idle;
		}

		private unsafe static void FlushHeldSeparator()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			ColorARGB heldSeparatorColor = _heldSeparatorColor;
			_origLogMsg.DynamicInvoke(Pointer.Box(&heldSeparatorColor, typeof(ColorARGB*)), "------------------------------", "------------------------------".Length, Pointer.Box(null, typeof(ColorARGB*)), null, 0, "------------------------------", "------------------------------".Length);
		}

		private static void ClearCapture()
		{
			_capturedName = null;
			_capturedVersion = null;
			_capturedAuthor = null;
		}

		private unsafe static void EmitOriginalMsgColored(string coloredMsg, string strippedMsg, ColorARGB msgColor)
		{
			_origLogMsg.DynamicInvoke(Pointer.Box(&msgColor, typeof(ColorARGB*)), coloredMsg, coloredMsg.Length, Pointer.Box(null, typeof(ColorARGB*)), null, 0, strippedMsg, strippedMsg.Length);
		}
	}
	internal class NukeInputModel : ModelEntryItem
	{
		public override string Identifier => "NukeInput";

		public override string DisplayName => "";

		public override string Description => (Config.NukedLines.Count == 0) ? "No lines nuked." : string.Join("\n", Config.NukedLines);

		public NukeInputModel(ModelCategoryItem parentCategory)
			: base(parentCategory)
		{
		}

		public override GameObject GetNewUIInstance()
		{
			GameObject prefab = UI.GetPrefab((InputType)6);
			Object.DestroyImmediate((Object)(object)prefab.GetComponent<ButtonEntry>());
			prefab.AddComponent<NukeInputController>();
			Transform val = prefab.transform.Find("Data/Label");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
			Transform val2 = prefab.transform.Find("Data/Button");
			if ((Object)(object)val2 != (Object)null)
			{
				foreach (TextMeshProUGUI componentsInChild in ((Component)val2).GetComponentsInChildren<TextMeshProUGUI>())
				{
					((TMP_Text)componentsInChild).text = "NUKE";
				}
				LayoutElement component = ((Component)val2).GetComponent<LayoutElement>();
				if ((Object)(object)component != (Object)null)
				{
					component.minWidth = 80f;
				}
			}
			if ((Object)(object)BundleLoader.TextFixedPrefab == (Object)null)
			{
				Core.Log.Warning("NukeInputModel: TextFixedPrefab not loaded.");
				return prefab;
			}
			GameObject val3 = Object.Instantiate<GameObject>(BundleLoader.TextFixedPrefab);
			Transform val4 = val3.transform.Find("Data/Control");
			if ((Object)(object)val4 != (Object)null)
			{
				Transform val5 = prefab.transform.Find("Data");
				val4.SetParent(val5, false);
				((Component)val4).gameObject.SetActive(true);
				HorizontalLayoutGroup component2 = ((Component)val5).GetComponent<HorizontalLayoutGroup>();
				if ((Object)(object)component2 != (Object)null)
				{
					((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetAsLastSibling();
				}
			}
			Object.Destroy((Object)(object)val3);
			return prefab;
		}
	}
	internal class ReviveModel : ModelEntryItem
	{
		public override string Identifier => "Revive";

		public override string DisplayName => "";

		public override string Description => "";

		public ReviveModel(ModelCategoryItem parentCategory)
			: base(parentCategory)
		{
		}

		public override GameObject GetNewUIInstance()
		{
			GameObject prefab = UI.GetPrefab((InputType)6);
			Object.DestroyImmediate((Object)(object)prefab.GetComponent<ButtonEntry>());
			prefab.AddComponent<ReviveController>();
			Transform val = prefab.transform.Find("Data/Label");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
			Transform val2 = prefab.transform.Find("Data/Button");
			if ((Object)(object)val2 != (Object)null)
			{
				foreach (TextMeshProUGUI componentsInChild in ((Component)val2).GetComponentsInChildren<TextMeshProUGUI>())
				{
					((TMP_Text)componentsInChild).text = "Revive";
				}
				LayoutElement component = ((Component)val2).GetComponent<LayoutElement>();
				if ((Object)(object)component != (Object)null)
				{
					component.minWidth = 120f;
				}
			}
			if ((Object)(object)BundleLoader.DropdownDynamicPrefab == (Object)null)
			{
				Core.Log.Warning("ReviveModel: DropdownDynamicPrefab not loaded.");
				return prefab;
			}
			GameObject val3 = Object.Instantiate<GameObject>(BundleLoader.DropdownDynamicPrefab);
			Transform val4 = val3.transform.Find("Data/Dropdown");
			if ((Object)(object)val4 != (Object)null)
			{
				Transform val5 = prefab.transform.Find("Data");
				val4.SetParent(val5, false);
				((Component)val4).gameObject.SetActive(true);
				HorizontalLayoutGroup component2 = ((Component)val5).GetComponent<HorizontalLayoutGroup>();
				if ((Object)(object)component2 != (Object)null)
				{
					((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetAsLastSibling();
				}
			}
			Object.Destroy((Object)(object)val3);
			return prefab;
		}
	}
	[RegisterTypeInIl2Cpp]
	internal class NukeInputController : Entry
	{
		private TMP_InputField? _input;

		public override void ModelSet()
		{
			((Entry)this).ModelSet();
			Transform obj = ((Component)this).gameObject.transform.Find("Data/Control");
			_input = ((obj != null) ? ((Component)obj).GetComponent<TMP_InputField>() : null);
			Transform val = ((Component)this).gameObject.transform.Find("Data/Button");
			if ((Object)(object)val != (Object)null)
			{
				Button component = ((Component)val).GetComponent<Button>();
				if (component != null)
				{
					((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)OnNukeClicked));
				}
			}
		}

		private void OnNukeClicked()
		{
			if (!((Object)(object)_input == (Object)null))
			{
				string text = _input.text?.Trim();
				if (!string.IsNullOrEmpty(text) && !Config.NukedLines.Contains(text))
				{
					Config.NukedLines.Add(text);
					NukeUI.SaveNukedLines();
					_input.text = "";
					NukeUI.RefreshAll();
				}
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	internal class ReviveController : Entry
	{
		private TMP_Dropdown? _dropdown;

		public override void ModelSet()
		{
			((Entry)this).ModelSet();
			Transform obj = ((Component)this).gameObject.transform.Find("Data/Dropdown");
			_dropdown = ((obj != null) ? ((Component)obj).GetComponent<TMP_Dropdown>() : null);
			NukeUI.SetReviveDropdown(_dropdown);
			NukeUI.RebuildDropdown();
			Transform val = ((Component)this).gameObject.transform.Find("Data/Button");
			if ((Object)(object)val != (Object)null)
			{
				Button component = ((Component)val).GetComponent<Button>();
				if (component != null)
				{
					((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)OnReviveClicked));
				}
			}
		}

		private void OnReviveClicked()
		{
			if ((Object)(object)_dropdown == (Object)null)
			{
				return;
			}
			int value = _dropdown.value;
			if (value > 0)
			{
				int num = value - 1;
				if (num < Config.NukedLines.Count)
				{
					Config.NukedLines.RemoveAt(num);
					NukeUI.SaveNukedLines();
				}
				NukeUI.RefreshAll();
			}
		}
	}
	internal static class NukeUI
	{
		private static TMP_Dropdown? _reviveDropdown;

		public static void Build(ModelMod mod)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			EmptyCategory val = new EmptyCategory("NUKE", "NUKE", (ModelModItem)null);
			((ModelCategoryItem)val).AddEntry((IEntry[])(object)new IEntry[2]
			{
				(IEntry)new NukeInputModel((ModelCategoryItem)(object)val),
				(IEntry)new ReviveModel((ModelCategoryItem)(object)val)
			});
			((ModelModItem)mod).AddModelCategory((ModelCategoryItem[])(object)new ModelCategoryItem[1] { (ModelCategoryItem)val });
		}

		internal static void SetReviveDropdown(TMP_Dropdown? dropdown)
		{
			_reviveDropdown = dropdown;
		}

		internal static void SaveNukedLines()
		{
			if (Config.NukedLinesEntry != null)
			{
				Config.NukedLinesEntry.Value = Config.NukedLines;
			}
			MelonPreferences_Category? category = Config.Category;
			if (category != null)
			{
				category.SaveToFile(false);
			}
		}

		internal static void RefreshAll()
		{
			Il2CppArrayBase<NukeInputController> val = Object.FindObjectsOfType<NukeInputController>();
			for (int i = 0; i < val.Count; i++)
			{
				((Entry)val[i]).DescriptionText = ((Config.NukedLines.Count == 0) ? "No lines nuked." : string.Join("\n", Config.NukedLines));
			}
			RebuildDropdown();
		}

		internal static void RebuildDropdown()
		{
			if ((Object)(object)_reviveDropdown == (Object)null)
			{
				return;
			}
			_reviveDropdown.ClearOptions();
			List<string> val = new List<string>();
			val.Add("");
			foreach (string nukedLine in Config.NukedLines)
			{
				val.Add(nukedLine);
			}
			_reviveDropdown.AddOptions(val);
			_reviveDropdown.value = 0;
		}
	}
}