using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Xml;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalEnums;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using TeamCherry.Localization;
using UnityEngine;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SimpleSilksongLocalizer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+9037140b01be5b0bad4d9e3f007d5c35de03136c")]
[assembly: AssemblyProduct("SimpleSilksongLocalizer")]
[assembly: AssemblyTitle("SimpleSilksongLocalizer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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 BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace SimpleSilksongLocalizer
{
public static class Extensions
{
public static TValue GetOrInsertNew<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key) where TValue : new()
{
if (dict.TryGetValue(key, out TValue value))
{
return value;
}
return dict[key] = new TValue();
}
}
public static class LanguagePatch
{
[HarmonyPatch(typeof(Language), "DoSwitch")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> SlackenXmlReader(IEnumerable<CodeInstruction> instructions)
{
//IL_0003: 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_004a: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(XmlReader), "Create", new Type[1] { typeof(TextReader) }, (Type[])null), (string)null)
});
CodeInstruction val2 = Transpilers.EmitDelegate<Func<StringReader, XmlReader>>((Func<StringReader, XmlReader>)delegate(StringReader reader)
{
XmlReaderSettings settings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
return XmlReader.Create(reader, settings);
});
val.Set(val2.opcode, val2.operand);
return val.InstructionEnumeration();
}
[HarmonyPatch(typeof(Language), "DoSwitch")]
[HarmonyPostfix]
private static void InsertCurrentLanguageExtraStrings()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
if (!SimpleSilksongLocalizerPlugin.ModExtraEntries.TryGetValue(Language._currentLanguage, out Dictionary<string, Dictionary<string, string>> value))
{
return;
}
foreach (KeyValuePair<string, Dictionary<string, string>> item in value)
{
item.Deconstruct(out var key, out var value2);
string key2 = key;
Dictionary<string, string> dictionary = value2;
Dictionary<string, string> orInsertNew = Language._currentEntrySheets.GetOrInsertNew(key2);
foreach (KeyValuePair<string, string> item2 in dictionary)
{
item2.Deconstruct(out key, out var value3);
string key3 = key;
string value4 = value3;
orInsertNew[key3] = value4;
}
}
}
[HarmonyPatch(typeof(Language), "HasLanguageFile")]
[HarmonyPostfix]
private static void HasModdedLanguageFile(ref bool __result, string lang, string sheetTitle)
{
if (__result)
{
return;
}
foreach (KeyValuePair<string, LocalizationSettings> modLocalizationDirectory in SimpleSilksongLocalizerPlugin.ModLocalizationDirectories)
{
modLocalizationDirectory.Deconstruct(out var key, out var value);
string path = key;
LocalizationSettings localizationSettings = value;
string path2 = Path.Combine(path, lang, sheetTitle);
if (File.Exists(path2))
{
__result = true;
break;
}
string text = ((object)(LanguageCode)(ref Language._currentLanguage)).ToString();
string text2 = localizationSettings?.GetFallbackLang(text);
if (string.IsNullOrEmpty(text2) || text2 == text || !File.Exists(Path.Combine(path, text2, sheetTitle)))
{
continue;
}
__result = true;
break;
}
}
[HarmonyPatch(typeof(Language), "GetLanguageFileContents")]
[HarmonyPostfix]
private static void AddModdedLanguageFileContents(ref string __result, string sheetTitle)
{
string text = string.Empty;
string key;
LocalizationSettings value;
foreach (KeyValuePair<string, LocalizationSettings> modLocalizationDirectory in SimpleSilksongLocalizerPlugin.ModLocalizationDirectories)
{
modLocalizationDirectory.Deconstruct(out key, out value);
string path = key;
LocalizationSettings localizationSettings = value;
string text2 = ((object)(LanguageCode)(ref Language._currentLanguage)).ToString();
string text3 = localizationSettings?.GetFallbackLang(text2);
if (!string.IsNullOrEmpty(text3) && !(text3 == text2))
{
string path2 = Path.Combine(path, text3, sheetTitle);
if (File.Exists(path2))
{
text += File.ReadAllText(path2);
}
}
}
text += __result;
foreach (KeyValuePair<string, LocalizationSettings> modLocalizationDirectory2 in SimpleSilksongLocalizerPlugin.ModLocalizationDirectories)
{
modLocalizationDirectory2.Deconstruct(out key, out value);
string path3 = key;
string path4 = Path.Combine(path3, ((object)(LanguageCode)(ref Language._currentLanguage)).ToString(), sheetTitle);
if (File.Exists(path4))
{
text += File.ReadAllText(path4);
}
}
__result = text;
}
}
internal class LocalizationSettings
{
internal class FallbackSettings
{
[JsonProperty(/*Could not decode attribute arguments.*/)]
[JsonConverter(typeof(StringEnumConverter))]
public LanguageCode Language { get; set; }
[JsonProperty(/*Could not decode attribute arguments.*/)]
public string[]? Excluded { get; set; }
}
[JsonProperty(/*Could not decode attribute arguments.*/)]
public string[]? CustomSheets { get; set; }
[JsonProperty(/*Could not decode attribute arguments.*/)]
public LanguageCode[]? CustomLanguages { get; set; }
[JsonProperty(/*Could not decode attribute arguments.*/)]
public FallbackSettings? Fallback { get; set; }
public string GetFallbackLang(string sourceLanguage)
{
//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_0051: Unknown result type (might be due to invalid IL or missing references)
if (!SimpleSilksongLocalizerPlugin.EnableFallbacks.Value || Fallback == null || (Fallback.Excluded != null && Fallback.Excluded.Contains(sourceLanguage)))
{
return string.Empty;
}
LanguageCode language = Fallback.Language;
return ((int)language != 0) ? string.Empty : ((object)(LanguageCode)(ref language)).ToString();
}
}
public class MenuLanguageSettingPatch
{
[HarmonyPatch(typeof(MenuLanguageSetting), "RefreshAvailableLanguages")]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> SupportAllAvailableLanguages(IEnumerable<CodeInstruction> instructions)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Expected O, but got Unknown
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Expected O, but got Unknown
CodeInstruction del = Transpilers.EmitDelegate<Func<SupportedLanguages[]>>((Func<SupportedLanguages[]>)delegate
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
List<SupportedLanguages> list = new List<SupportedLanguages>();
foreach (string availableLanguage in Language._availableLanguages)
{
if (Enum.TryParse<LanguageCode>(availableLanguage, out LanguageCode result))
{
list.Add((SupportedLanguages)result);
}
}
return list.ToArray();
});
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[3]
{
new CodeMatch((OpCode?)OpCodes.Ldtoken, (object)typeof(SupportedLanguages), (string)null),
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Type), "GetTypeFromHandle", new Type[1] { typeof(RuntimeTypeHandle) }, (Type[])null), (string)null),
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Enum), "GetValues", new Type[1] { typeof(Type) }, (Type[])null), (string)null)
}).Repeat((Action<CodeMatcher>)delegate(CodeMatcher matcher)
{
matcher.RemoveInstructions(2).SetAndAdvance(del.opcode, del.operand);
}, (Action<string>)null);
return val.InstructionEnumeration();
}
[HarmonyPatch(typeof(MenuLanguageSetting), "UpdateLangsArray")]
[HarmonyPostfix]
public static void UpdateLangsArrayStrings(ref string[] ___optionList, SupportedLanguages[] ___langs)
{
___optionList = ___langs.Select(delegate(SupportedLanguages opt)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
LanguageCode val = (LanguageCode)opt;
return ((object)(LanguageCode)(ref val)).ToString();
}).ToArray();
}
}
[BepInPlugin("capitalistspz.simplesilksonglocalizer", "SimpleSilksongLocalizer", "0.1.0")]
public class SimpleSilksongLocalizerPlugin : BaseUnityPlugin
{
internal static Dictionary<string, LocalizationSettings?> ModLocalizationDirectories = new Dictionary<string, LocalizationSettings>();
internal static List<string> ModCustomSheets = new List<string>();
internal static List<LanguageCode> ModCustomLanguages = new List<LanguageCode>();
internal static Dictionary<LanguageCode, Dictionary<string, Dictionary<string, string>>> ModExtraEntries = new Dictionary<LanguageCode, Dictionary<string, Dictionary<string, string>>>();
internal static ConfigEntry<bool> EnableFallbacks;
public static ManualLogSource Logger;
private Harmony harmony;
private string[] originalSheetTitles;
public const string Id = "capitalistspz.simplesilksonglocalizer";
public static string Name => "SimpleSilksongLocalizer";
public static string Version => "0.1.0";
public void RegisterSheet(string sheetTitle)
{
ModCustomSheets.Add(sheetTitle);
}
public static void AddLocalizationDirectory(string localizationDirectory)
{
//IL_0066: Expected O, but got Unknown
DirectoryInfo directoryInfo = new DirectoryInfo(localizationDirectory);
FileInfo fileInfo = directoryInfo.EnumerateFiles("LocalizationSettings.json").FirstOrDefault();
if (fileInfo == null)
{
ModLocalizationDirectories.Add(localizationDirectory, null);
return;
}
string fullName = fileInfo.FullName;
try
{
LocalizationSettings localizationSettings = JsonConvert.DeserializeObject<LocalizationSettings>(File.ReadAllText(fullName));
if (localizationSettings != null)
{
ModLocalizationDirectories.Add(localizationDirectory, localizationSettings);
}
}
catch (JsonSerializationException val)
{
JsonSerializationException arg = val;
Logger.LogError((object)$"Failed to parse language settings at '{fullName}': {arg}");
}
catch (Exception arg2)
{
Logger.LogError((object)$"Unexpected exception: {arg2}");
}
}
public static void AddSheet(LanguageCode languageCode, string sheet, Dictionary<string, string> entries)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
Dictionary<string, string> orInsertNew = ModExtraEntries.GetOrInsertNew(languageCode).GetOrInsertNew(sheet);
foreach (KeyValuePair<string, string> entry in entries)
{
entry.Deconstruct(out var key, out var value);
string key2 = key;
string value2 = value;
orInsertNew[key2] = value2;
}
}
public static void AddSheetEntry(LanguageCode languageCode, string sheet, string key, string value)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
Dictionary<string, string> orInsertNew = ModExtraEntries.GetOrInsertNew(languageCode).GetOrInsertNew(sheet);
orInsertNew[key] = value;
}
private void Awake()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
harmony = new Harmony("capitalistspz.simplesilksonglocalizer");
EnableFallbacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Fallbacks", "Enable", false, "Enable fallback strings for untranslated text, if the source has them enabled");
Logger.LogInfo((object)("Plugin " + Name + " (capitalistspz.simplesilksonglocalizer) has loaded!"));
}
private void FindDirectories()
{
DirectoryInfo directoryInfo = new DirectoryInfo(Paths.PluginPath);
foreach (DirectoryInfo item in directoryInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
{
foreach (DirectoryInfo item2 in item.EnumerateDirectories("SSL.Localization", SearchOption.TopDirectoryOnly))
{
AddLocalizationDirectory(item2.FullName);
}
}
}
private void Start()
{
FindDirectories();
Apply();
}
private void OnEnable()
{
if (((MonoBehaviour)this).didStart && !harmony.GetPatchedMethods().Any())
{
Apply();
}
}
private void OnDisable()
{
Unapply();
}
private void Apply()
{
foreach (LocalizationSettings value in ModLocalizationDirectories.Values)
{
if (value != null)
{
if (value.CustomSheets != null)
{
ModCustomSheets.AddRange(value.CustomSheets);
}
if (value.CustomLanguages != null)
{
ModCustomLanguages.AddRange(value.CustomLanguages);
}
}
}
originalSheetTitles = Language._settings.sheetTitles;
Language._settings.sheetTitles = Language._settings.sheetTitles.Union(ModCustomSheets).ToArray();
harmony.PatchAll(typeof(LanguagePatch));
harmony.PatchAll(typeof(MenuLanguageSettingPatch));
Language.LoadAvailableLanguages();
Language.LoadLanguage();
}
private void Unapply()
{
harmony.UnpatchSelf();
Language._settings.sheetTitles = originalSheetTitles;
Language.LoadAvailableLanguages();
Language.LoadLanguage();
}
}
}