using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using ShiftAtMidnightLocalizationAPI.Api;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShiftAtMidnightLocalizationAPI")]
[assembly: AssemblyDescription("Localization API for Shift At Midnight mods")]
[assembly: AssemblyProduct("ShiftAtMidnightLocalizationAPI")]
[assembly: ComVisible(false)]
[assembly: Guid("79870812-2aca-43d5-b058-5844d23fb3b4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ShiftAtMidnightLocalizationAPI
{
public static class PluginInfo
{
public const string PLUGIN_GUID = "IceBoxStudio.ShiftAtMidnight.LocalizationAPI";
public const string PLUGIN_NAME = "ShiftAtMidnightLocalizationAPI";
public const string PLUGIN_VERSION = "1.0.0";
}
[BepInPlugin("IceBoxStudio.ShiftAtMidnight.LocalizationAPI", "ShiftAtMidnightLocalizationAPI", "1.0.0")]
public sealed class ShiftAtMidnightLocalizationAPI : 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.ShiftAtMidnight.LocalizationAPI").PatchAll(Assembly.GetExecutingAssembly());
ManualLogSource logger = Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(14, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("ShiftAtMidnightLocalizationAPI");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.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);
}
}
}
}
namespace ShiftAtMidnightLocalizationAPI.Patches
{
[HarmonyPatch(typeof(LanguageManager), "OnLanguageLoaded")]
public static class LanguageManagerOnLanguageLoadedPatch
{
[HarmonyPostfix]
public static void Postfix()
{
LocalizationApi.NotifyLanguageChanged();
}
}
}
namespace ShiftAtMidnightLocalizationAPI.Api
{
public static class LocalizationApi
{
private sealed class LocalizedConfigDescription
{
public ModLocalizer Localizer;
public string Key;
public object[] Arguments;
}
public const string DefaultLanguage = "ENGLISH";
private const string LanguagePreferenceKey = "Language";
private static readonly Dictionary<string, ModLocalizer> Localizers = new Dictionary<string, ModLocalizer>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<ConfigEntryBase, LocalizedConfigDescription> ConfigDescriptions = new Dictionary<ConfigEntryBase, LocalizedConfigDescription>();
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)
{
try
{
string text = (PlayerPrefs.HasKey("Language") ? PlayerPrefs.GetString("Language", "ENGLISH") : "ENGLISH");
language = (string.IsNullOrWhiteSpace(text) ? "ENGLISH" : text);
return true;
}
catch
{
language = "ENGLISH";
return false;
}
}
public static string GetConfigDescription(ConfigEntryBase entry)
{
if (entry != null && ConfigDescriptions.TryGetValue(entry, out var value))
{
return value.Localizer.GetLocalizedText(value.Key, value.Arguments);
}
if (entry == null)
{
return null;
}
ConfigDescription description = entry.Description;
if (description == null)
{
return null;
}
return description.Description;
}
internal static void RegisterConfigDescription(ConfigEntryBase entry, ModLocalizer localizer, string key, object[] arguments)
{
if (entry == null)
{
throw new ArgumentNullException("entry");
}
if (localizer == null)
{
throw new ArgumentNullException("localizer");
}
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("Localization key cannot be empty.", "key");
}
ConfigDescriptions[entry] = new LocalizedConfigDescription
{
Localizer = localizer,
Key = key,
Arguments = arguments
};
}
internal static void NotifyLanguageChanged()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
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 = ShiftAtMidnightLocalizationAPI.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);
}
}
}
}
}
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 void RegisterConfigDescription(ConfigEntryBase entry, string key, params object[] args)
{
LocalizationApi.RegisterConfigDescription(entry, this, key, args);
}
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;
}
}
}
}