Decompiled source of BigWalkLocalizationAPI v1.1.0

BepInEx/plugins/BigWalkLocalizationAPI.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BigWalkLocalizationAPI.Api;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BigWalkLocalizationAPI")]
[assembly: AssemblyDescription("Big Walk Localization API for Big Walk by Ice Box Studio")]
[assembly: AssemblyProduct("BigWalkLocalizationAPI")]
[assembly: ComVisible(false)]
[assembly: Guid("e335fa34-e0fc-41e6-9c93-88cf9ff63f57")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace BigWalkLocalizationAPI
{
	[BepInPlugin("IceBoxStudio.BigWalk.LocalizationAPI", "BigWalkLocalizationAPI", "1.1.0")]
	public sealed class BigWalkLocalizationAPI : BasePlugin
	{
		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			bool flag = default(bool);
			try
			{
				new Harmony("IceBoxStudio.BigWalk.LocalizationAPI").PatchAll(Assembly.GetExecutingAssembly());
				ManualLogSource logger = Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(14, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("BigWalkLocalizationAPI");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initialized.");
				}
				logger.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to initialize the localization API: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				logger2.LogError(val2);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "IceBoxStudio.BigWalk.LocalizationAPI";

		public const string PLUGIN_NAME = "BigWalkLocalizationAPI";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace BigWalkLocalizationAPI.Patches
{
	[HarmonyPatch(typeof(LocalizationManager), "SetLanguage", new Type[] { typeof(LocalizationLanguage) })]
	public static class LocalizationManagerSetLanguagePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			LocalizationApi.NotifyLanguageChanged();
		}
	}
}
namespace BigWalkLocalizationAPI.Api
{
	internal sealed class ConfigSectionTag
	{
		private readonly ModLocalizer _localizer;

		private readonly string _key;

		public string Section { get; }

		public int? Order { get; }

		internal ConfigSectionTag(ModLocalizer localizer, string section, string key, int order)
		{
			_localizer = localizer;
			_key = key;
			Section = section;
			Order = order;
		}

		internal bool TryGetDisplayName(out string displayName)
		{
			displayName = _localizer.GetLocalizedText(_key);
			return !string.Equals(displayName, _key, StringComparison.Ordinal);
		}
	}
	internal sealed class ConfigEntryTag
	{
		private readonly ModLocalizer _localizer;

		private readonly string _key;

		public int? Order { get; }

		public double? SliderStep { get; }

		internal ConfigEntryTag(ModLocalizer localizer, string key, int order, double? sliderStep)
		{
			_localizer = localizer;
			_key = key;
			Order = order;
			SliderStep = sliderStep;
		}

		internal bool TryGetText(string propertyName, out string text)
		{
			string text2 = (string.Equals(propertyName, "DisplayName", StringComparison.Ordinal) ? ".name" : ".description");
			string text3 = _key + text2;
			text = _localizer.GetLocalizedText(text3);
			return !string.Equals(text, text3, StringComparison.Ordinal);
		}

		internal bool TryGetDisplayValue(object value, out string displayValue)
		{
			displayValue = null;
			string text = NormalizeValue(value);
			if (text.Length == 0)
			{
				return false;
			}
			string text2 = _key + "." + text;
			string localizedText = _localizer.GetLocalizedText(text2);
			if (string.Equals(localizedText, text2, StringComparison.Ordinal))
			{
				return false;
			}
			displayValue = localizedText;
			return true;
		}

		private static string NormalizeValue(object value)
		{
			string text = Convert.ToString(value, CultureInfo.InvariantCulture);
			if (string.IsNullOrWhiteSpace(text))
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length + 4);
			for (int i = 0; i < text.Length; i++)
			{
				char c = text[i];
				if (!char.IsLetterOrDigit(c))
				{
					if (stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] != '_')
					{
						stringBuilder.Append('_');
					}
					continue;
				}
				if (char.IsUpper(c) && i > 0 && char.IsLower(text[i - 1]) && stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] != '_')
				{
					stringBuilder.Append('_');
				}
				stringBuilder.Append(char.ToLowerInvariant(c));
			}
			return stringBuilder.ToString().Trim('_');
		}
	}
	public static class LocalizationApi
	{
		public const string DefaultLanguage = "English";

		private const string LanguageSaveKey = "setting_language";

		private static readonly Dictionary<string, ModLocalizer> Localizers = new Dictionary<string, ModLocalizer>(StringComparer.OrdinalIgnoreCase);

		private static bool _languageApplied;

		public static string CurrentLanguage
		{
			get
			{
				TryGetCurrentGameLanguage(out var language);
				return language;
			}
		}

		public static event Action<string> LanguageChanged;

		public static ModLocalizer For(string pluginGuid)
		{
			if (string.IsNullOrWhiteSpace(pluginGuid))
			{
				throw new ArgumentException("Plugin GUID cannot be empty.", "pluginGuid");
			}
			if (!Localizers.TryGetValue(pluginGuid, out var value))
			{
				value = new ModLocalizer(pluginGuid);
				Localizers.Add(pluginGuid, value);
			}
			return value;
		}

		public static bool TryGetCurrentGameLanguage(out string language)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_languageApplied && TryGetSavedLanguage(out language))
				{
					return true;
				}
				LocalizationManager instance = LocalizationManager.instance;
				language = ((instance == null) ? "English" : ((object)instance.currentLanguage/*cast due to .constrained prefix*/).ToString());
				if (string.IsNullOrWhiteSpace(language))
				{
					language = "English";
				}
				return instance != null;
			}
			catch
			{
				language = "English";
				return false;
			}
		}

		public static string GetConfigDescription(ConfigEntryBase entry)
		{
			if (entry != null)
			{
				ConfigDescription description = entry.Description;
				object[] array = ((description != null) ? description.Tags : null) ?? Array.Empty<object>();
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i] is ConfigEntryTag configEntryTag && configEntryTag.TryGetText("Description", out var text))
					{
						return text;
					}
				}
			}
			if (entry == null)
			{
				return null;
			}
			ConfigDescription description2 = entry.Description;
			if (description2 == null)
			{
				return null;
			}
			return description2.Description;
		}

		public static string GetConfigDisplayName(ConfigEntryBase entry)
		{
			if (entry != null)
			{
				ConfigDescription description = entry.Description;
				object[] array = ((description != null) ? description.Tags : null) ?? Array.Empty<object>();
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i] is ConfigEntryTag configEntryTag && configEntryTag.TryGetText("DisplayName", out var text))
					{
						return text;
					}
				}
			}
			if (entry == null)
			{
				return null;
			}
			ConfigDefinition definition = entry.Definition;
			if (definition == null)
			{
				return null;
			}
			return definition.Key;
		}

		public static string GetConfigSection(string section, ConfigFile config)
		{
			if (section == null || config == null)
			{
				return section;
			}
			foreach (ConfigEntryBase value in config.Values)
			{
				if (!string.Equals(value.Definition.Section, section, StringComparison.Ordinal))
				{
					continue;
				}
				ConfigDescription description = value.Description;
				object[] array = ((description != null) ? description.Tags : null) ?? Array.Empty<object>();
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i] is ConfigSectionTag configSectionTag && string.Equals(configSectionTag.Section, section, StringComparison.Ordinal) && configSectionTag.TryGetDisplayName(out var displayName))
					{
						return displayName;
					}
				}
			}
			return section;
		}

		public static bool TryGetConfigDisplayValue(ConfigEntryBase entry, object value, out string displayValue)
		{
			displayValue = null;
			if (entry == null || value == null)
			{
				return false;
			}
			ConfigDescription description = entry.Description;
			object[] array = ((description != null) ? description.Tags : null) ?? Array.Empty<object>();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] is ConfigEntryTag configEntryTag && configEntryTag.TryGetDisplayValue(value, out displayValue))
				{
					return true;
				}
			}
			return false;
		}

		internal static void NotifyLanguageChanged()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			_languageApplied = true;
			Action<string> languageChanged = LocalizationApi.LanguageChanged;
			if (languageChanged == null)
			{
				return;
			}
			string currentLanguage = CurrentLanguage;
			Delegate[] invocationList = languageChanged.GetInvocationList();
			bool flag = default(bool);
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<string>)obj)(currentLanguage);
				}
				catch (Exception ex)
				{
					ManualLogSource logger = BigWalkLocalizationAPI.Logger;
					if (logger != null)
					{
						BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Language change callback failed: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
						}
						logger.LogError(val);
					}
				}
			}
		}

		private static bool TryGetSavedLanguage(out string language)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			language = null;
			if (!PlayerPrefs.HasKey("setting_language"))
			{
				return false;
			}
			int num = PlayerPrefs.GetInt("setting_language");
			if (num < 1 || num > 15)
			{
				return false;
			}
			language = ((object)(LocalizationLanguage)num/*cast due to .constrained prefix*/).ToString();
			return !string.IsNullOrWhiteSpace(language);
		}
	}
	public sealed class ModLocalizer
	{
		private readonly Dictionary<string, Dictionary<string, string>> _localizations = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

		public string PluginGuid { get; }

		internal ModLocalizer(string pluginGuid)
		{
			PluginGuid = pluginGuid;
		}

		public void RegisterJson(string jsonPath)
		{
			if (string.IsNullOrWhiteSpace(jsonPath))
			{
				throw new ArgumentException("Localization file path cannot be empty.", "jsonPath");
			}
			if (!File.Exists(jsonPath))
			{
				throw new FileNotFoundException("Localization file not found.", jsonPath);
			}
			Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
			using (JsonDocument jsonDocument = JsonDocument.Parse(File.ReadAllText(jsonPath)))
			{
				if (jsonDocument.RootElement.ValueKind != JsonValueKind.Object)
				{
					throw new InvalidDataException("Localization file root must be a JSON object.");
				}
				foreach (JsonProperty item in jsonDocument.RootElement.EnumerateObject())
				{
					if (item.Value.ValueKind != JsonValueKind.Object)
					{
						continue;
					}
					Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
					foreach (JsonProperty item2 in item.Value.EnumerateObject())
					{
						if (item2.Value.ValueKind == JsonValueKind.String)
						{
							dictionary2[item2.Name] = item2.Value.GetString() ?? string.Empty;
						}
					}
					if (dictionary2.Count > 0)
					{
						dictionary[item.Name] = dictionary2;
					}
				}
			}
			if (!dictionary.ContainsKey("English"))
			{
				throw new InvalidDataException("Localization file must contain a English section.");
			}
			_localizations.Clear();
			foreach (KeyValuePair<string, Dictionary<string, string>> item3 in dictionary)
			{
				_localizations.Add(item3.Key, item3.Value);
			}
		}

		public string GetLocalizedText(string key, params object[] args)
		{
			if (string.IsNullOrEmpty(key))
			{
				return string.Empty;
			}
			string currentLanguage = LocalizationApi.CurrentLanguage;
			if (TryGetText(currentLanguage, key, out var text))
			{
				return Format(text, args);
			}
			if (!string.Equals(currentLanguage, "English", StringComparison.OrdinalIgnoreCase) && TryGetText("English", key, out var text2))
			{
				return Format(text2, args);
			}
			return key;
		}

		public ConfigDescription Config(string key, int entryOrder, string section, string sectionKey, int sectionOrder, AcceptableValueBase acceptableValues = null, double? sliderStep = null)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			if (string.IsNullOrWhiteSpace(key))
			{
				throw new ArgumentException("Localization key cannot be empty.", "key");
			}
			if (string.IsNullOrWhiteSpace(section))
			{
				throw new ArgumentException("Config section cannot be empty.", "section");
			}
			if (string.IsNullOrWhiteSpace(sectionKey))
			{
				throw new ArgumentException("Section localization key cannot be empty.", "sectionKey");
			}
			string text = key + ".description";
			string text2 = GetLocalizedText(text);
			if (string.Equals(text2, text, StringComparison.Ordinal))
			{
				text2 = string.Empty;
			}
			return new ConfigDescription(text2, acceptableValues, new object[2]
			{
				new ConfigSectionTag(this, section, sectionKey, sectionOrder),
				new ConfigEntryTag(this, key, entryOrder, sliderStep)
			});
		}

		private bool TryGetText(string language, string key, out string text)
		{
			text = null;
			if (_localizations.TryGetValue(language, out var value))
			{
				return value.TryGetValue(key, out text);
			}
			return false;
		}

		private static string Format(string text, object[] args)
		{
			if (args == null || args.Length == 0)
			{
				return text;
			}
			try
			{
				return string.Format(text, args);
			}
			catch (FormatException)
			{
				return text;
			}
		}
	}
}