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 Risk of Rain 2 Ukrainian v1.6.1
plugins/Risk_of_Rain_2_Ukrainian.dll
Decompiled 2 weeks agousing 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 BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using On.RoR2; using On.RoR2.UI; using R2API; using Risk_of_Rain_2_Ukrainian.ModFixes; using RoR2; using RoR2.UI; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Risk_of_Rain_2_Ukrainian")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Adds Ukrainian localization to Risk of Rain 2 and mods")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+601932d96d2b77a2a6fa24c9ce838026407419e9")] [assembly: AssemblyProduct("Risk_of_Rain_2_Ukrainian")] [assembly: AssemblyTitle("Risk_of_Rain_2_Ukrainian")] [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 Risk_of_Rain_2_Ukrainian { public static class Consts { public const string MasGenderToken = "<чр>"; public const string FemGenderToken = "<жр>"; public const string NeuGenderToken = "<ср>"; public const string MyLangName = "uk"; public const string ConfigFileName = "LanguageAPIWhitelist.conf"; } public class FontManager { public static AssetBundle assetBundle = AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Risk_of_Rain_2_Ukrainian.ukrainianfont")); public static TMP_FontAsset fontBomb; public static Material dropshadowMaterial; public static Material hologramMaterial; public static TMP_FontAsset fontBombDefault; public FontManager() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) fontBomb = assetBundle.LoadAsset<TMP_FontAsset>("Assets/BOMBARD+Ukrainian.asset"); dropshadowMaterial = assetBundle.LoadAsset<Material>("Assets/BOMBARD+Ukrainian.dropshadow.mat"); hologramMaterial = assetBundle.LoadAsset<Material>("Assets/BOMBARD+Ukrainian.hologram.mat"); fontBombDefault = Resources.Load<TMP_FontAsset>("TmpFonts/Bombardier/tmpBombDropShadow"); HGTextMeshProUGUI.OnCurrentLanguageChanged += new hook_OnCurrentLanguageChanged(HGTextMeshProUGUI_OnCurrentLanguageChanged); new Hook((MethodBase)typeof(TextMeshProUGUI).GetMethod("LoadFontAsset", (BindingFlags)(-1)), (Delegate)new Action<Action<TMP_Text>, TMP_Text>(OnLoadFontAsset)); new Hook((MethodBase)typeof(TextMeshPro).GetMethod("LoadFontAsset", (BindingFlags)(-1)), (Delegate)new Action<Action<TMP_Text>, TMP_Text>(OnLoadFontAsset)); } public void OnLoadFontAsset(Action<TMP_Text> orig, TMP_Text self) { orig(self); if ((Object)(object)self.font == (Object)(object)fontBombDefault) { self.font = fontBomb; if (self is TextMeshProUGUI) { self.fontMaterial = dropshadowMaterial; } if (self is TextMeshPro) { self.fontMaterial = hologramMaterial; } } } public void HGTextMeshProUGUI_OnCurrentLanguageChanged(orig_OnCurrentLanguageChanged orig) { orig.Invoke(); if (Object.op_Implicit((Object)(object)fontBomb)) { HGTextMeshProUGUI.defaultLanguageFont = fontBomb; } } } public enum Gender { Default, Mas, Fem, Neu } public class GrammaticalGenderManager { public HashSet<string> FemGenderTokensCollection = new HashSet<string>(); public HashSet<string> NeuGenderTokensCollection = new HashSet<string>(); public GrammaticalGenderManager() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Language.LoadAllTokensFromFolder += new hook_LoadAllTokensFromFolder(LanguageOnLoadAllTokensFromFolder); Util.GetBestBodyName += new hook_GetBestBodyName(UtilOnGetBestBodyName); } private void LanguageOnLoadAllTokensFromFolder(orig_LoadAllTokensFromFolder orig, string folder, List<KeyValuePair<string, string>> output) { if (!folder.StartsWith(RiskOfRain2UaPlugin.LocationDir)) { orig.Invoke(folder, output); return; } List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(3500); orig.Invoke(folder, list); for (int i = 0; i < list.Count; i++) { KeyValuePair<string, string> keyValuePair = list[i]; if (keyValuePair.Value.StartsWith("<жр>")) { list[i] = new KeyValuePair<string, string>(keyValuePair.Key, keyValuePair.Value.Substring("<жр>".Length)); FemGenderTokensCollection.Add(keyValuePair.Key); } if (keyValuePair.Value.StartsWith("<ср>")) { list[i] = new KeyValuePair<string, string>(keyValuePair.Key, keyValuePair.Value.Substring("<ср>".Length)); NeuGenderTokensCollection.Add(keyValuePair.Key); } } RiskOfRain2UaPlugin.Log.LogInfo((object)$"Found {FemGenderTokensCollection.Count} feminine tokens."); RiskOfRain2UaPlugin.Log.LogInfo((object)$"Found {NeuGenderTokensCollection.Count} neutral tokens."); output.AddRange(list); } private string UtilOnGetBestBodyName(orig_GetBestBodyName orig, GameObject bodyObject) { if (!Language.currentLanguage.name.Equals("uk", StringComparison.OrdinalIgnoreCase)) { return orig.Invoke(bodyObject); } return CustomGetBestBodyNameImpl(bodyObject); } private string CustomGetBestBodyNameImpl(GameObject bodyObject) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) CharacterBody val = null; string text = "???"; Gender gender = Gender.Default; if (Object.op_Implicit((Object)(object)bodyObject)) { val = bodyObject.GetComponent<CharacterBody>(); } if (Object.op_Implicit((Object)(object)val)) { text = val.GetUserName(); if (FemGenderTokensCollection.Contains(val.baseNameToken)) { gender = Gender.Fem; } else if (NeuGenderTokensCollection.Contains(val.baseNameToken)) { gender = Gender.Neu; } } else { IDisplayNameProvider component = bodyObject.GetComponent<IDisplayNameProvider>(); if (component != null) { text = component.GetDisplayName(); } } string text2 = text; if (Object.op_Implicit((Object)(object)val)) { if (val.isElite) { BuffIndex[] eliteBuffIndices = BuffCatalog.eliteBuffIndices; foreach (BuffIndex val2 in eliteBuffIndices) { if (val.HasBuff(val2)) { text2 = GetStringFormatted(BuffCatalog.GetBuffDef(val2).eliteDef.modifierToken, gender, text2); } } } if (Object.op_Implicit((Object)(object)val.inventory)) { if (val.inventory.GetItemCount(Items.InvadingDoppelganger) > 0) { text2 = GetStringFormatted("BODY_MODIFIER_DOPPELGANGER", gender, text2); } if (val.inventory.GetItemCount(Items.GummyCloneIdentifier) > 0) { text2 = GetStringFormatted("BODY_MODIFIER_GUMMYCLONE", gender, text2); } } } return text2; } public static string GetStringFormatted(string token, Gender gender, params object[] args) { switch (gender) { case Gender.Fem: { string text = token + "__F"; if (Language.currentLanguage.TokenIsRegistered(text)) { token = text; } break; } case Gender.Neu: { string text = token + "__N"; if (Language.currentLanguage.TokenIsRegistered(text)) { token = text; } break; } } return Language.GetStringFormatted(token, args); } } public class LanguageAPILoader { public LanguageAPILoader(string folder, string configFile) { if (!Directory.Exists(folder)) { return; } foreach (string item in File.ReadLines(configFile)) { if (File.Exists(Path.Join(folder.AsSpan(), item.AsSpan()))) { RiskOfRain2UaPlugin.Log.LogInfo((object)("Loading " + Path.Join(folder.AsSpan(), item.AsSpan()) + " for LanguageAPI.")); LanguageAPI.AddPath(Path.Join(folder.AsSpan(), item.AsSpan())); } else { RiskOfRain2UaPlugin.Log.LogWarning((object)(Path.Join(folder.AsSpan(), item.AsSpan()) + " is specified in " + Path.GetFileName(configFile) + ", but does not exist.")); } } } } public class PrismaticTrialsManager { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_OnEnable <>9__1_0; internal void <.ctor>b__1_0(orig_OnEnable orig, DisableIfGameModded self) { } } private string[] modWhiteList = new string[6] { "___0pseudopulse.__SeekersPatcherDLL", "___riskofthunder.RoR2BepInExPack", "_score.MiscFixes", "com.bepis.r2api.language", "com.bepis.r2api", "Risk_of_Rain_2_Ukrainian" }; public PrismaticTrialsManager() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if (OnlyWhiteListInstalled()) { object obj = <>c.<>9__1_0; if (obj == null) { hook_OnEnable val = delegate { }; <>c.<>9__1_0 = val; obj = (object)val; } DisableIfGameModded.OnEnable += (hook_OnEnable)obj; } } private bool OnlyWhiteListInstalled() { HashSet<string> hashSet = new HashSet<string>(modWhiteList); foreach (string key in Chainloader.PluginInfos.Keys) { if (!hashSet.Contains(key)) { return false; } } return true; } } [BepInPlugin("Risk_of_Rain_2_Ukrainian", "Risk_of_Rain_2_Ukrainian", "1.6.0")] public class RiskOfRain2UaPlugin : BaseUnityPlugin { public static RiskOfRain2UaPlugin Instance; public static string LocationDir; public GrammaticalGenderManager GrammaticalGenderManager; public FontManager FontManager; public PrismaticTrialsManager PrismaticTrialsManager; public LanguageAPILoader LanguageAPILoader; public WolfoQoL WolfoQoL; public static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; private void Awake() { Instance = this; LocationDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Language.collectLanguageRootFolders += LanguageOnCollectLanguageRootFolders; GrammaticalGenderManager = new GrammaticalGenderManager(); FontManager = new FontManager(); PrismaticTrialsManager = new PrismaticTrialsManager(); LanguageAPILoader = new LanguageAPILoader(Path.Join(LocationDir.AsSpan(), "lang_mods".AsSpan(), "uk".AsSpan()), Path.Join(LocationDir.AsSpan(), "lang_mods".AsSpan(), "LanguageAPIWhitelist.conf".AsSpan())); WolfoQoL = new WolfoQoL(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Risk_of_Rain_2_Ukrainian is loaded!"); } private void LanguageOnCollectLanguageRootFolders(List<string> folders) { folders.Add(Path.Combine(LocationDir, "lang")); folders.Add(Path.Combine(LocationDir, "lang_mods")); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Risk_of_Rain_2_Ukrainian"; public const string PLUGIN_NAME = "Risk_of_Rain_2_Ukrainian"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace Risk_of_Rain_2_Ukrainian.ModFixes { public class WolfoQoL { [CompilerGenerated] private static class <>O { public static hook_SetCurrentLanguage <0>__UpdateBoostedNameTokens; } public WolfoQoL() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown object obj = <>O.<0>__UpdateBoostedNameTokens; if (obj == null) { hook_SetCurrentLanguage val = UpdateBoostedNameTokens; <>O.<0>__UpdateBoostedNameTokens = val; obj = (object)val; } Language.SetCurrentLanguage += (hook_SetCurrentLanguage)obj; } public static void UpdateBoostedNameTokens(orig_SetCurrentLanguage orig, string newLanguage) { orig.Invoke(newLanguage); foreach (KeyValuePair<string, Gender> item in new Dictionary<string, Gender> { { "CHEF_PRIMARY_NAME", Gender.Neu }, { "CHEF_SECONDARY_NAME", Gender.Neu }, { "CHEF_SECONDARY_ALT_NAME", Gender.Fem }, { "CHEF_UTILITY_NAME", Gender.Neu }, { "CHEF_UTILITY_ALT_NAME", Gender.Default } }) { string stringFormatted = GrammaticalGenderManager.GetStringFormatted("CHEF_BOOSTED_FORMAT", item.Value, Language.GetString(item.Key)); LanguageAPI.AddOverlay(item.Key + "_B", stringFormatted); } foreach (KeyValuePair<string, Gender> item2 in new Dictionary<string, Gender> { { "VOIDSURVIVOR_PRIMARY_NAME", Gender.Neu }, { "VOIDSURVIVOR_SECONDARY_NAME", Gender.Fem }, { "VOIDSURVIVOR_UTILITY_NAME", Gender.Default }, { "VOIDSURVIVOR_SPECIAL_NAME", Gender.Neu } }) { string stringFormatted2 = GrammaticalGenderManager.GetStringFormatted("VOIDFIEND_BOOSTED_FORMAT", item2.Value, Language.GetString(item2.Key)); LanguageAPI.AddOverlay(item2.Key + "_B", stringFormatted2); } } } }