Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SimpleSilksongLocalizer v0.1.0
SimpleSilksongLocalizer.dll
Decompiled 7 months agousing 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(); } } }