Decompiled source of MoreLoadingQuotes v1.0.0

plugins/MoreLoadingQuotes.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("MoreLoadingQuotes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("More loading quotes for Gamble With Your Friends")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MoreLoadingQuotes")]
[assembly: AssemblyTitle("MoreLoadingQuotes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 MoreLoadingQuotes
{
	[BepInPlugin("com.ananas1k.gwyf.moreloadingquotes", "More Loading Quotes", "1.0.0")]
	public class MoreLoadingQuotesPlugin : BaseUnityPlugin
	{
		private sealed class QuoteParts
		{
			public readonly string Quote;

			public readonly string Author;

			public readonly string Formatted;

			public QuoteParts(string quote, string author, string formatted)
			{
				Quote = quote;
				Author = author;
				Formatted = formatted;
			}
		}

		private const string PluginGuid = "com.ananas1k.gwyf.moreloadingquotes";

		private const string PluginName = "More Loading Quotes";

		private const string PluginVersion = "1.0.0";

		private const string PluginFolderName = "MoreLoadingQuotes";

		private const string QuotesFileName = "quotes.txt";

		private const string EnglishQuotesFileName = "en_quotes.txt";

		private const string RussianQuotesFileName = "ru_quotes.txt";

		private const string RussianTranslationPackageName = "RTLC-GWYF_Russian_Translation";

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

		private static readonly Dictionary<int, string[]> VanillaQuotesByInstance = new Dictionary<int, string[]>();

		private static readonly Dictionary<string, QuoteParts> QuotePartsByDisplayedText = new Dictionary<string, QuoteParts>(StringComparer.Ordinal);

		private static readonly Dictionary<string, QuoteParts> QuotePartsByQuoteText = new Dictionary<string, QuoteParts>(StringComparer.Ordinal);

		private static readonly object QuoteLock = new object();

		private static readonly string[] EmptyQuotes = new string[0];

		private static MoreLoadingQuotesPlugin Instance;

		private static ConfigEntry<bool> EnableCustomQuotes;

		private static ConfigEntry<bool> ReplaceVanillaQuotes;

		private static ConfigEntry<bool> LiveReload;

		private static ConfigEntry<string> QuoteFilePath;

		private static ConfigEntry<string> QuoteAuthorFormat;

		private static ConfigEntry<int> ConfigLocalizationLanguage;

		private static ConfigEntry<float> ConfigLineSpacing;

		private static ConfigEntry<float> ConfigTextBoxMinHeight;

		private static ConfigEntry<float> ConfigAuthorVerticalOffset;

		private static ConfigEntry<float> ConfigAuthorFontScale;

		private static string activeQuoteFilePath;

		private static string[] cachedQuotes = EmptyQuotes;

		private static DateTime cachedQuoteFileWriteTimeUtc = DateTime.MinValue;

		private static bool useRussianQuotes;

		private static FieldInfo targetTextField;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00a8: Expected O, but got Unknown
			Instance = this;
			BindConfig();
			useRussianQuotes = ShouldUseRussianQuotes();
			activeQuoteFilePath = ResolveQuoteFilePath();
			EnsureQuoteFileExists(activeQuoteFilePath);
			LoadQuotes(force: true);
			targetTextField = AccessTools.Field(typeof(LoadingQuotes), "targetText");
			harmony = new Harmony("com.ananas1k.gwyf.moreloadingquotes");
			harmony.Patch((MethodBase)AccessTools.Method(typeof(LoadingQuotes), "ShowRandomQuote", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MoreLoadingQuotesPlugin), "PatchShowRandomQuote", (Type[])null), new HarmonyMethod(typeof(MoreLoadingQuotesPlugin), "PatchShowRandomQuotePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("More Loading Quotes 1.0.0 loaded. " + (useRussianQuotes ? "Russian" : "English") + " quote file: " + activeQuoteFilePath));
		}

		private void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void BindConfig()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			EnableCustomQuotes = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableCustomQuotes", true, "If true, loads extra loading quotes from en_quotes.txt or ru_quotes.txt.");
			ReplaceVanillaQuotes = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceVanillaQuotes", false, "If true, only custom quotes from quotes.txt will be used. If false, custom quotes are added to the vanilla quote pool.");
			LiveReload = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LiveReload", true, "If true, quotes.txt is re-read when it changes, so testing new quotes does not require restarting the game.");
			QuoteFilePath = ((BaseUnityPlugin)this).Config.Bind<string>("General", "QuoteFilePath", string.Empty, "Optional custom quote file path. Relative paths are resolved from the BepInEx plugins folder. Leave empty to use automatic en_quotes.txt/ru_quotes.txt selection.");
			QuoteAuthorFormat = ((BaseUnityPlugin)this).Config.Bind<string>("General", "QuoteAuthorFormat", "{0}\\n- {1}", "Format used for quote lines written as: quote | author. {0}=quote, {1}=author. Use \\n for line breaks.");
			ConfigLocalizationLanguage = ((BaseUnityPlugin)this).Config.Bind<int>("Localization", "Language", 0, new ConfigDescription("0=Auto, 1=English, 2=Russian. Auto uses Russian quotes when RTLC-GWYF_Russian_Translation is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			ConfigLineSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "LineSpacing", 35f, new ConfigDescription("Extra TextMeshPro line spacing for loading quotes. Increase if wrapped quote lines overlap.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>()));
			ConfigTextBoxMinHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "TextBoxMinHeight", 260f, new ConfigDescription("Minimum height for the loading quote text box. Increase if the quote author is clipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
			ConfigAuthorVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "AuthorVerticalOffset", -125f, new ConfigDescription("Vertical offset for the separate quote author text. Negative values move it down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-300f, 100f), Array.Empty<object>()));
			ConfigAuthorFontScale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "AuthorFontScale", 0.55f, new ConfigDescription("Author font size as a multiplier of the quote font size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
		}

		private static void PatchShowRandomQuote(LoadingQuotes __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null || EnableCustomQuotes == null || !EnableCustomQuotes.Value)
				{
					return;
				}
				if (LiveReload != null && LiveReload.Value && (Object)(object)Instance != (Object)null)
				{
					Instance.LoadQuotes(force: false);
				}
				string[] array = GetCachedQuotes();
				if (array.Length == 0)
				{
					return;
				}
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!PatchedInstances.Contains(instanceID))
				{
					string[] source = (AccessTools.Field(typeof(LoadingQuotes), "quotes").GetValue(__instance) as string[]) ?? EmptyQuotes;
					if (!VanillaQuotesByInstance.TryGetValue(instanceID, out var value))
					{
						value = CopyQuotes(source);
						VanillaQuotesByInstance[instanceID] = value;
					}
					string[] value2 = ((ReplaceVanillaQuotes != null && ReplaceVanillaQuotes.Value) ? NormalizeQuotes(array) : MergeQuotes(value, array));
					AccessTools.Field(typeof(LoadingQuotes), "quotes").SetValue(__instance, value2);
					ApplyTextLayout(__instance);
					PatchedInstances.Add(instanceID);
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failed to add custom loading quotes: " + ex.Message);
			}
		}

		private static void PatchShowRandomQuotePostfix(LoadingQuotes __instance)
		{
			try
			{
				ApplyTextLayout(__instance);
			}
			catch (Exception ex)
			{
				LogWarning("Failed to adjust loading quote layout: " + ex.Message);
			}
		}

		private static void ApplyTextLayout(LoadingQuotes loadingQuotes)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI targetText = GetTargetText(loadingQuotes);
			if ((Object)(object)targetText == (Object)null)
			{
				return;
			}
			((TMP_Text)targetText).richText = true;
			EnableTextWrapping(targetText);
			((TMP_Text)targetText).overflowMode = (TextOverflowModes)0;
			((TMP_Text)targetText).lineSpacing = ((ConfigLineSpacing == null) ? 35f : ConfigLineSpacing.Value);
			((TMP_Text)targetText).maxVisibleCharacters = 99999;
			((TMP_Text)targetText).maxVisibleWords = 99999;
			((TMP_Text)targetText).maxVisibleLines = 99999;
			((TMP_Text)targetText).extraPadding = true;
			float num = ((ConfigTextBoxMinHeight == null) ? 260f : ConfigTextBoxMinHeight.Value);
			RectTransform rectTransform = ((TMP_Text)targetText).rectTransform;
			if ((Object)(object)rectTransform != (Object)null && num > 0f)
			{
				Rect rect = rectTransform.rect;
				if (((Rect)(ref rect)).height < num)
				{
					rectTransform.SetSizeWithCurrentAnchors((Axis)1, num);
				}
			}
			ApplyAuthorText(targetText);
			((TMP_Text)targetText).ForceMeshUpdate(false, false);
		}

		private static void ApplyAuthorText(TextMeshProUGUI targetText)
		{
			if (!TryGetQuoteParts(((TMP_Text)targetText).text, out var parts))
			{
				SetAuthorObjectActive(targetText, active: false, null);
				return;
			}
			if (!string.Equals(((TMP_Text)targetText).text, parts.Quote, StringComparison.Ordinal))
			{
				((TMP_Text)targetText).text = parts.Quote;
			}
			SetAuthorObjectActive(targetText, active: true, parts.Author);
		}

		private static bool TryGetQuoteParts(string displayedText, out QuoteParts parts)
		{
			parts = null;
			string text = NormalizeRuntimeText(displayedText);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (QuotePartsByDisplayedText.TryGetValue(text, out parts))
			{
				return true;
			}
			if (QuotePartsByQuoteText.TryGetValue(text, out parts))
			{
				return true;
			}
			return TrySplitFormattedQuote(text, out parts);
		}

		private static void SetAuthorObjectActive(TextMeshProUGUI targetText, bool active, string author)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI orCreateAuthorText = GetOrCreateAuthorText(targetText);
			if ((Object)(object)orCreateAuthorText == (Object)null)
			{
				return;
			}
			((Component)orCreateAuthorText).gameObject.SetActive(active);
			if (!active)
			{
				return;
			}
			RectTransform rectTransform = ((TMP_Text)targetText).rectTransform;
			RectTransform rectTransform2 = ((TMP_Text)orCreateAuthorText).rectTransform;
			if ((Object)(object)rectTransform != (Object)null && (Object)(object)rectTransform2 != (Object)null)
			{
				rectTransform2.anchorMin = rectTransform.anchorMin;
				rectTransform2.anchorMax = rectTransform.anchorMax;
				rectTransform2.pivot = rectTransform.pivot;
				Rect rect = rectTransform.rect;
				float num;
				if (!(((Rect)(ref rect)).width > 0f))
				{
					num = rectTransform.sizeDelta.x;
				}
				else
				{
					rect = rectTransform.rect;
					num = ((Rect)(ref rect)).width;
				}
				rectTransform2.sizeDelta = new Vector2(num, 90f);
				rectTransform2.anchoredPosition = rectTransform.anchoredPosition + new Vector2(0f, (ConfigAuthorVerticalOffset == null) ? (-125f) : ConfigAuthorVerticalOffset.Value);
				((Transform)rectTransform2).localScale = Vector3.one;
				((Transform)rectTransform2).localRotation = Quaternion.identity;
			}
			((TMP_Text)orCreateAuthorText).font = ((TMP_Text)targetText).font;
			((TMP_Text)orCreateAuthorText).fontSharedMaterial = ((TMP_Text)targetText).fontSharedMaterial;
			((Graphic)orCreateAuthorText).color = ((Graphic)targetText).color;
			((TMP_Text)orCreateAuthorText).alignment = (TextAlignmentOptions)514;
			((TMP_Text)orCreateAuthorText).richText = true;
			((TMP_Text)orCreateAuthorText).overflowMode = (TextOverflowModes)0;
			((TMP_Text)orCreateAuthorText).enableAutoSizing = false;
			((TMP_Text)orCreateAuthorText).fontSize = ((TMP_Text)targetText).fontSize * ((ConfigAuthorFontScale == null) ? 0.55f : ConfigAuthorFontScale.Value);
			((TMP_Text)orCreateAuthorText).lineSpacing = ((TMP_Text)targetText).lineSpacing;
			((TMP_Text)orCreateAuthorText).maxVisibleCharacters = 99999;
			((TMP_Text)orCreateAuthorText).maxVisibleWords = 99999;
			((TMP_Text)orCreateAuthorText).maxVisibleLines = 99999;
			((TMP_Text)orCreateAuthorText).extraPadding = true;
			((Graphic)orCreateAuthorText).raycastTarget = false;
			((TMP_Text)orCreateAuthorText).text = "- " + author;
			((TMP_Text)orCreateAuthorText).ForceMeshUpdate(false, false);
		}

		private static TextMeshProUGUI GetOrCreateAuthorText(TextMeshProUGUI targetText)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((TMP_Text)targetText).transform.parent;
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			Transform val = parent.Find("MoreLoadingQuotes_Author");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<TextMeshProUGUI>();
			}
			GameObject val2 = new GameObject("MoreLoadingQuotes_Author", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(parent, false);
			val2.transform.SetSiblingIndex(((TMP_Text)targetText).transform.GetSiblingIndex() + 1);
			return val2.AddComponent<TextMeshProUGUI>();
		}

		private static void EnableTextWrapping(TextMeshProUGUI targetText)
		{
			try
			{
				PropertyInfo property = typeof(TMP_Text).GetProperty("textWrappingMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.PropertyType.IsEnum)
				{
					object value = Enum.Parse(property.PropertyType, "Normal");
					property.SetValue(targetText, value, null);
					return;
				}
				PropertyInfo property2 = typeof(TMP_Text).GetProperty("enableWordWrapping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property2 != null)
				{
					property2.SetValue(targetText, true, null);
				}
			}
			catch
			{
			}
		}

		private static TextMeshProUGUI GetTargetText(LoadingQuotes loadingQuotes)
		{
			if ((Object)(object)loadingQuotes == (Object)null || targetTextField == null)
			{
				return null;
			}
			try
			{
				object? value = targetTextField.GetValue(loadingQuotes);
				return (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
			}
			catch
			{
				return null;
			}
		}

		private static string ResolveQuoteFilePath()
		{
			string text = ((QuoteFilePath.Value == null) ? string.Empty : QuoteFilePath.Value.Trim());
			if (!string.IsNullOrEmpty(text))
			{
				if (!Path.IsPathRooted(text))
				{
					return Path.Combine(Paths.PluginPath, text);
				}
				return text;
			}
			string text2 = (useRussianQuotes ? "ru_quotes.txt" : "en_quotes.txt");
			string text3 = Path.Combine(Paths.PluginPath, "MoreLoadingQuotes", text2);
			if (File.Exists(text3))
			{
				return text3;
			}
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (!string.IsNullOrEmpty(directoryName))
			{
				string text4 = Path.Combine(directoryName, text2);
				if (File.Exists(text4))
				{
					return text4;
				}
			}
			string text5 = Path.Combine(Paths.PluginPath, "MoreLoadingQuotes", "quotes.txt");
			if (File.Exists(text5))
			{
				return text5;
			}
			return text3;
		}

		private static bool ShouldUseRussianQuotes()
		{
			if (ConfigLocalizationLanguage != null)
			{
				if (ConfigLocalizationLanguage.Value == 1)
				{
					return false;
				}
				if (ConfigLocalizationLanguage.Value == 2)
				{
					return true;
				}
			}
			return IsRussianLocalizationDetected();
		}

		private static bool IsRussianLocalizationDetected()
		{
			if (TryGetManagedRussianTranslationEnabled(out var enabled))
			{
				return enabled;
			}
			if (IsManagedThunderstoreProfile())
			{
				return false;
			}
			if (HasRussianTranslationPackageFiles())
			{
				return true;
			}
			try
			{
				foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
				{
					string text = pluginInfo.Key ?? string.Empty;
					string text2 = ((pluginInfo.Value != null && pluginInfo.Value.Metadata != null) ? (pluginInfo.Value.Metadata.Name ?? string.Empty) : string.Empty);
					string text3 = ((pluginInfo.Value != null && pluginInfo.Value.Metadata != null) ? (pluginInfo.Value.Metadata.GUID ?? string.Empty) : string.Empty);
					if (IsRussianTranslationPluginText((text + " " + text2 + " " + text3).ToLowerInvariant()))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool TryGetManagedRussianTranslationEnabled(out bool enabled)
		{
			enabled = false;
			try
			{
				string managedModsFilePath = GetManagedModsFilePath();
				if (string.IsNullOrEmpty(managedModsFilePath) || !File.Exists(managedModsFilePath))
				{
					return false;
				}
				string[] array = File.ReadAllLines(managedModsFilePath);
				bool flag = false;
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (array[i].StartsWith("- ", StringComparison.Ordinal))
					{
						if (flag)
						{
							return true;
						}
						flag = false;
					}
					bool result;
					if (text.StartsWith("name:", StringComparison.OrdinalIgnoreCase) && text.IndexOf("RTLC-GWYF_Russian_Translation", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						flag = true;
					}
					else if (flag && text.StartsWith("enabled:", StringComparison.OrdinalIgnoreCase) && bool.TryParse(text.Substring("enabled:".Length).Trim(), out result))
					{
						enabled = result;
						return true;
					}
				}
				return flag;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsManagedThunderstoreProfile()
		{
			string managedModsFilePath = GetManagedModsFilePath();
			if (!string.IsNullOrEmpty(managedModsFilePath))
			{
				return File.Exists(managedModsFilePath);
			}
			return false;
		}

		private static string GetManagedModsFilePath()
		{
			try
			{
				DirectoryInfo directoryInfo = Directory.GetParent(Paths.PluginPath)?.Parent;
				return (directoryInfo == null) ? null : Path.Combine(directoryInfo.FullName, "mods.yml");
			}
			catch
			{
				return null;
			}
		}

		private static bool HasRussianTranslationPackageFiles()
		{
			try
			{
				string text = Path.Combine(Paths.PluginPath, "RTLC-GWYF_Russian_Translation");
				if (!Directory.Exists(text))
				{
					return false;
				}
				if (File.Exists(Path.Combine(text, "RTLC.GWYF", "RTLC.GWYF.Text.dll")))
				{
					return true;
				}
				return Directory.GetFiles(text, "RTLC.GWYF.Text.dll", SearchOption.AllDirectories).Length != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsRussianTranslationPluginText(string text)
		{
			if (!text.Contains("rtlc.gwyf.text") && !text.Contains("gwyf_russian_translation") && !text.Contains("gwyf russian translation"))
			{
				return text.Contains("rtlc-gwyf_russian_translation");
			}
			return true;
		}

		private static void EnsureQuoteFileExists(string filePath)
		{
			try
			{
				string directoryName = Path.GetDirectoryName(filePath);
				if (!string.IsNullOrEmpty(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				if (!File.Exists(filePath))
				{
					File.WriteAllText(filePath, GetQuoteFileTemplate(useRussianQuotes), Encoding.UTF8);
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failed to create quote file '" + filePath + "': " + ex.Message);
			}
		}

		private static string GetQuoteFileTemplate(bool russian)
		{
			if (russian)
			{
				return "# More Loading Quotes\n# Recommended format: Quote text | Author\n# Example: Gambling is just math with dramatic lighting. | A broke statistician\n# Already formatted lines are also accepted. Use \\n for manual line breaks.\n# Empty lines and lines starting with # or // are ignored.\n# Put your Russian quotes below this line.\n";
			}
			return "# More Loading Quotes\n# Recommended format: Quote text | Author\n# Example: Gambling is just math with dramatic lighting. | A broke statistician\n# Already formatted lines are also accepted. Use \\n for manual line breaks.\n# Empty lines and lines starting with # or // are ignored.\n# Put your English quotes below this line.\n";
		}

		private void LoadQuotes(bool force)
		{
			lock (QuoteLock)
			{
				try
				{
					useRussianQuotes = ShouldUseRussianQuotes();
					string b = ResolveQuoteFilePath();
					if (!string.Equals(activeQuoteFilePath, b, StringComparison.OrdinalIgnoreCase))
					{
						activeQuoteFilePath = b;
						cachedQuoteFileWriteTimeUtc = DateTime.MinValue;
						PatchedInstances.Clear();
						force = true;
					}
					EnsureQuoteFileExists(activeQuoteFilePath);
					if (string.IsNullOrEmpty(activeQuoteFilePath) || !File.Exists(activeQuoteFilePath))
					{
						cachedQuotes = EmptyQuotes;
						cachedQuoteFileWriteTimeUtc = DateTime.MinValue;
						PatchedInstances.Clear();
						return;
					}
					DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(activeQuoteFilePath);
					if (!force && lastWriteTimeUtc == cachedQuoteFileWriteTimeUtc)
					{
						return;
					}
					Dictionary<string, QuoteParts> dictionary = new Dictionary<string, QuoteParts>(StringComparer.Ordinal);
					Dictionary<string, QuoteParts> dictionary2 = new Dictionary<string, QuoteParts>(StringComparer.Ordinal);
					List<string> list = new List<string>();
					string[] array = File.ReadAllLines(activeQuoteFilePath, Encoding.UTF8);
					for (int i = 0; i < array.Length; i++)
					{
						string text = array[i].Trim();
						if (!string.IsNullOrEmpty(text) && !text.StartsWith("#", StringComparison.Ordinal) && !text.StartsWith("//", StringComparison.Ordinal))
						{
							list.Add(ParseQuoteLine(text, dictionary, dictionary2));
						}
					}
					cachedQuotes = NormalizeQuotes(list.ToArray());
					QuotePartsByDisplayedText.Clear();
					QuotePartsByQuoteText.Clear();
					foreach (KeyValuePair<string, QuoteParts> item in dictionary)
					{
						QuotePartsByDisplayedText[item.Key] = item.Value;
					}
					foreach (KeyValuePair<string, QuoteParts> item2 in dictionary2)
					{
						QuotePartsByQuoteText[item2.Key] = item2.Value;
					}
					cachedQuoteFileWriteTimeUtc = lastWriteTimeUtc;
					PatchedInstances.Clear();
					((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Loaded {0} custom {1} loading quote(s).", cachedQuotes.Length, useRussianQuotes ? "Russian" : "English"));
				}
				catch (Exception ex)
				{
					cachedQuotes = EmptyQuotes;
					cachedQuoteFileWriteTimeUtc = DateTime.MinValue;
					PatchedInstances.Clear();
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to load custom loading quotes: " + ex.Message));
				}
			}
		}

		private static string ParseQuoteLine(string line, Dictionary<string, QuoteParts> displayedParts, Dictionary<string, QuoteParts> quoteParts)
		{
			string text = line.Replace("\\n", "\n").Trim();
			int num = text.IndexOf('|');
			if (num < 0)
			{
				return text;
			}
			string text2 = text.Substring(0, num).Trim();
			string text3 = text.Substring(num + 1).Trim().TrimStart(new char[1] { '|' })
				.Trim();
			if (string.IsNullOrEmpty(text2) || string.IsNullOrEmpty(text3))
			{
				return text;
			}
			string text4 = FormatQuoteWithAuthor(text2, text3);
			QuoteParts value = new QuoteParts(text2, text3, text4);
			displayedParts[NormalizeRuntimeText(text4)] = value;
			quoteParts[NormalizeRuntimeText(text2)] = value;
			return text4;
		}

		private static bool TrySplitFormattedQuote(string text, out QuoteParts parts)
		{
			parts = null;
			int num = text.LastIndexOf("\n- ", StringComparison.Ordinal);
			if (num < 0)
			{
				return false;
			}
			string text2 = text.Substring(0, num).Trim();
			string text3 = text.Substring(num + 3).Trim();
			if (string.IsNullOrEmpty(text2) || string.IsNullOrEmpty(text3))
			{
				return false;
			}
			parts = new QuoteParts(text2, text3, text);
			return true;
		}

		private static string NormalizeRuntimeText(string text)
		{
			if (text == null)
			{
				return string.Empty;
			}
			return text.Replace("\r\n", "\n").Replace("\r", "\n").Trim();
		}

		private static string FormatQuoteWithAuthor(string quote, string author)
		{
			string text = ((QuoteAuthorFormat == null || string.IsNullOrEmpty(QuoteAuthorFormat.Value)) ? "{0}\\n- {1}" : QuoteAuthorFormat.Value);
			text = text.Replace("\\n", "\n");
			try
			{
				return string.Format(text, quote, author);
			}
			catch
			{
				return quote + "\n- " + author;
			}
		}

		private static string[] GetCachedQuotes()
		{
			lock (QuoteLock)
			{
				if (cachedQuotes.Length == 0)
				{
					return EmptyQuotes;
				}
				string[] array = new string[cachedQuotes.Length];
				Array.Copy(cachedQuotes, array, cachedQuotes.Length);
				return array;
			}
		}

		private static string[] CopyQuotes(string[] source)
		{
			if (source == null || source.Length == 0)
			{
				return EmptyQuotes;
			}
			string[] array = new string[source.Length];
			Array.Copy(source, array, source.Length);
			return array;
		}

		private static string[] MergeQuotes(string[] vanillaQuotes, string[] customQuotes)
		{
			List<string> list = new List<string>();
			AddUniqueQuotes(list, vanillaQuotes);
			AddUniqueQuotes(list, customQuotes);
			return list.ToArray();
		}

		private static string[] NormalizeQuotes(string[] quotes)
		{
			List<string> list = new List<string>();
			AddUniqueQuotes(list, quotes);
			return list.ToArray();
		}

		private static void AddUniqueQuotes(List<string> target, string[] source)
		{
			if (source == null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(target, StringComparer.Ordinal);
			for (int i = 0; i < source.Length; i++)
			{
				string text = ((source[i] == null) ? string.Empty : source[i].Trim());
				if (!string.IsNullOrEmpty(text) && !hashSet.Contains(text))
				{
					target.Add(text);
					hashSet.Add(text);
				}
			}
		}

		private static void LogWarning(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)message);
			}
		}
	}
}