using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; 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.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using ArabicSupportUnity; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Discord; using GreyAnnouncer.AudioClipLoad; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Sandbox; using ScriptableObjects; using SettingsMenu.Components; using TMPro; using UltrakULL.Harmony_Patches; using UltrakULL.audio; using UltrakULL.json; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.Networking; using UnityEngine.SceneManagement; 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: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: AssemblyCompany("UltrakULL")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5d3593b83edaaef43c4ff49e68f996fe97c408cb")] [assembly: AssemblyProduct("UltrakULL")] [assembly: AssemblyTitle("UltrakULL")] [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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { public ExtensionMarkerAttribute(string name) { } } } internal enum IsolatedArabicLetters { Hamza = 65152, Alef = 65165, AlefHamza = 65155, WawHamza = 65157, AlefMaksoor = 65159, AlefMaksora = 64508, HamzaNabera = 65161, Ba = 65167, Ta = 65173, Tha2 = 65177, Jeem = 65181, H7aa = 65185, Khaa2 = 65189, Dal = 65193, Thal = 65195, Ra2 = 65197, Zeen = 65199, Seen = 65201, Sheen = 65205, S9a = 65209, Dha = 65213, T6a = 65217, T6ha = 65221, Ain = 65225, Gain = 65229, Fa = 65233, Gaf = 65237, Kaf = 65241, Lam = 65245, Meem = 65249, Noon = 65253, Ha = 65257, Waw = 65261, Ya = 65265, AlefMad = 65153, TaMarboota = 65171, PersianPe = 64342, PersianChe = 64378, PersianZe = 64394, PersianGaf = 64402, PersianGaf2 = 64398, PersianYeh = 64508 } internal enum GeneralArabicLetters { Hamza = 1569, Alef = 1575, AlefHamza = 1571, WawHamza = 1572, AlefMaksoor = 1573, AlefMagsora = 1609, HamzaNabera = 1574, Ba = 1576, Ta = 1578, Tha2 = 1579, Jeem = 1580, H7aa = 1581, Khaa2 = 1582, Dal = 1583, Thal = 1584, Ra2 = 1585, Zeen = 1586, Seen = 1587, Sheen = 1588, S9a = 1589, Dha = 1590, T6a = 1591, T6ha = 1592, Ain = 1593, Gain = 1594, Fa = 1601, Gaf = 1602, Kaf = 1603, Lam = 1604, Meem = 1605, Noon = 1606, Ha = 1607, Waw = 1608, Ya = 1610, AlefMad = 1570, TaMarboota = 1577, PersianPe = 1662, PersianChe = 1670, PersianZe = 1688, PersianGaf = 1711, PersianGaf2 = 1705, PersianYeh = 1740 } internal struct ArabicMapping { public int from; public int to; public ArabicMapping(int from, int to) { this.from = from; this.to = to; } } internal class ArabicTable { private static ArabicMapping[] mapList; private static ArabicTable arabicMapper; internal static ArabicTable ArabicMapper { get { if (arabicMapper == null) { arabicMapper = new ArabicTable(); } return arabicMapper; } } private ArabicTable() { mapList = new ArabicMapping[42] { new ArabicMapping(1569, 65152), new ArabicMapping(1575, 65165), new ArabicMapping(1571, 65155), new ArabicMapping(1572, 65157), new ArabicMapping(1573, 65159), new ArabicMapping(1609, 64508), new ArabicMapping(1574, 65161), new ArabicMapping(1576, 65167), new ArabicMapping(1578, 65173), new ArabicMapping(1579, 65177), new ArabicMapping(1580, 65181), new ArabicMapping(1581, 65185), new ArabicMapping(1582, 65189), new ArabicMapping(1583, 65193), new ArabicMapping(1584, 65195), new ArabicMapping(1585, 65197), new ArabicMapping(1586, 65199), new ArabicMapping(1587, 65201), new ArabicMapping(1588, 65205), new ArabicMapping(1589, 65209), new ArabicMapping(1590, 65213), new ArabicMapping(1591, 65217), new ArabicMapping(1592, 65221), new ArabicMapping(1593, 65225), new ArabicMapping(1594, 65229), new ArabicMapping(1601, 65233), new ArabicMapping(1602, 65237), new ArabicMapping(1603, 65241), new ArabicMapping(1604, 65245), new ArabicMapping(1605, 65249), new ArabicMapping(1606, 65253), new ArabicMapping(1607, 65257), new ArabicMapping(1608, 65261), new ArabicMapping(1610, 65265), new ArabicMapping(1570, 65153), new ArabicMapping(1577, 65171), new ArabicMapping(1662, 64342), new ArabicMapping(1670, 64378), new ArabicMapping(1688, 64394), new ArabicMapping(1711, 64402), new ArabicMapping(1705, 64398), new ArabicMapping(1740, 64508) }; } internal int Convert(int toBeConverted) { for (int i = 0; i < mapList.Length; i++) { ArabicMapping arabicMapping = mapList[i]; if (arabicMapping.from == toBeConverted) { return arabicMapping.to; } } return toBeConverted; } } internal class TashkeelLocation { public char tashkeel; public int position; public TashkeelLocation(char tashkeel, int position) { this.tashkeel = tashkeel; this.position = position; } } internal class ArabicFixerTool { internal static bool showTashkeel = true; internal static bool combineTashkeel = true; internal static bool useHinduNumbers = true; internal static StringBuilder internalStringBuilder = new StringBuilder(); internal static void RemoveTashkeel(ref string str, out List tashkeelLocation) { tashkeelLocation = new List(); int lastSplitIndex = 0; internalStringBuilder.Clear(); internalStringBuilder.EnsureCapacity(str.Length); int num = 0; for (int i = 0; i < str.Length; i++) { if (str[i] == '\u064b') { tashkeelLocation.Add(new TashkeelLocation('\u064b', i)); num++; IncrementSB(ref str, i); } else if (str[i] == '\u064c') { tashkeelLocation.Add(new TashkeelLocation('\u064c', i)); num++; IncrementSB(ref str, i); } else if (str[i] == '\u064d') { tashkeelLocation.Add(new TashkeelLocation('\u064d', i)); num++; IncrementSB(ref str, i); } else if (str[i] == '\u064e') { if (num > 0 && combineTashkeel && tashkeelLocation[num - 1].tashkeel == '\u0651') { tashkeelLocation[num - 1].tashkeel = 'ﱠ'; IncrementSB(ref str, i); } else { tashkeelLocation.Add(new TashkeelLocation('\u064e', i)); num++; IncrementSB(ref str, i); } } else if (str[i] == '\u064f') { if (num > 0 && combineTashkeel && tashkeelLocation[num - 1].tashkeel == '\u0651') { tashkeelLocation[num - 1].tashkeel = 'ﱡ'; IncrementSB(ref str, i); } else { tashkeelLocation.Add(new TashkeelLocation('\u064f', i)); num++; IncrementSB(ref str, i); } } else if (str[i] == '\u0650') { if (num > 0 && combineTashkeel && tashkeelLocation[num - 1].tashkeel == '\u0651') { tashkeelLocation[num - 1].tashkeel = 'ﱢ'; IncrementSB(ref str, i); } else { tashkeelLocation.Add(new TashkeelLocation('\u0650', i)); num++; IncrementSB(ref str, i); } } else if (str[i] == '\u0651') { if (num > 0 && combineTashkeel) { if (tashkeelLocation[num - 1].tashkeel == '\u064e') { tashkeelLocation[num - 1].tashkeel = 'ﱠ'; IncrementSB(ref str, i); continue; } if (tashkeelLocation[num - 1].tashkeel == '\u064f') { tashkeelLocation[num - 1].tashkeel = 'ﱡ'; IncrementSB(ref str, i); continue; } if (tashkeelLocation[num - 1].tashkeel == '\u0650') { tashkeelLocation[num - 1].tashkeel = 'ﱢ'; IncrementSB(ref str, i); continue; } } tashkeelLocation.Add(new TashkeelLocation('\u0651', i)); num++; IncrementSB(ref str, i); } else if (str[i] == '\u0652') { tashkeelLocation.Add(new TashkeelLocation('\u0652', i)); num++; IncrementSB(ref str, i); } else if (str[i] == '\u0653') { tashkeelLocation.Add(new TashkeelLocation('\u0653', i)); num++; IncrementSB(ref str, i); } else if (str[i] == 'ﱠ') { IncrementSB(ref str, i); } else if (str[i] == 'ﱡ') { IncrementSB(ref str, i); } else if (str[i] == 'ﱢ') { IncrementSB(ref str, i); } } if (lastSplitIndex != 0) { IncrementSB(ref str, str.Length); str = internalStringBuilder.ToString(); } void IncrementSB(ref string reference, int num2) { if (num2 - lastSplitIndex > 0) { internalStringBuilder.Append(reference, lastSplitIndex, num2 - lastSplitIndex); } lastSplitIndex = num2 + 1; } } internal static void ReturnTashkeel(ref char[] letters, List tashkeelLocation) { Array.Resize(ref letters, letters.Length + tashkeelLocation.Count); for (int i = 0; i < tashkeelLocation.Count; i++) { TashkeelLocation tashkeelLocation2 = tashkeelLocation[i]; for (int num = letters.Length - 1; num > tashkeelLocation2.position; num--) { letters[num] = letters[num - 1]; } letters[tashkeelLocation2.position] = tashkeelLocation2.tashkeel; } } internal static string FixLine(string str) { RemoveTashkeel(ref str, out var tashkeelLocation); char[] array = new char[str.Length]; char[] letters = str.ToCharArray(); for (int i = 0; i < array.Length; i++) { array[i] = (char)ArabicTable.ArabicMapper.Convert(str[i]); } for (int j = 0; j < array.Length; j++) { bool flag = false; if (array[j] == 'ﻝ' && j < array.Length - 1) { if (array[j + 1] == 'ﺇ') { array[j] = 'ﻷ'; letters[j + 1] = '\uffff'; flag = true; } else if (array[j + 1] == 'ﺍ') { array[j] = 'ﻹ'; letters[j + 1] = '\uffff'; flag = true; } else if (array[j + 1] == 'ﺃ') { array[j] = 'ﻵ'; letters[j + 1] = '\uffff'; flag = true; } else if (array[j + 1] == 'ﺁ') { array[j] = 'ﻳ'; letters[j + 1] = '\uffff'; flag = true; } } if (!IsIgnoredCharacter(array[j])) { if (IsMiddleLetter(array, j)) { letters[j] = (char)(array[j] + 3); } else if (IsFinishingLetter(array, j)) { letters[j] = (char)(array[j] + 1); } else if (IsLeadingLetter(array, j)) { letters[j] = (char)(array[j] + 2); } } if (flag) { j++; } letters[j] = (char)HandleInduNumber(array[j], letters[j]); } if (showTashkeel && tashkeelLocation.Count > 0) { ReturnTashkeel(ref letters, tashkeelLocation); } internalStringBuilder.Clear(); internalStringBuilder.EnsureCapacity(letters.Length); List numberList = null; for (int num = letters.Length - 1; num >= 0; num--) { if (char.IsPunctuation(letters[num]) && num > 0 && num < letters.Length - 1 && (char.IsPunctuation(letters[num - 1]) || char.IsPunctuation(letters[num + 1]))) { if (letters[num] != '\uffff') { internalStringBuilder.Append(letters[num]); } } else if (letters[num] == ' ' && num > 0 && num < letters.Length - 1 && (char.IsLower(letters[num - 1]) || char.IsUpper(letters[num - 1]) || char.IsNumber(letters[num - 1])) && (char.IsLower(letters[num + 1]) || char.IsUpper(letters[num + 1]) || char.IsNumber(letters[num + 1]))) { AddNumber(letters[num]); } else if (char.IsNumber(letters[num]) || char.IsLower(letters[num]) || char.IsUpper(letters[num]) || char.IsSymbol(letters[num]) || char.IsPunctuation(letters[num])) { AddNumber(letters[num]); } else if ((letters[num] >= '\ud800' && letters[num] <= '\udbff') || (letters[num] >= '\udc00' && letters[num] <= '\udfff')) { AddNumber(letters[num]); } else { AppendNumbers(); if (letters[num] != '\uffff') { internalStringBuilder.Append(letters[num]); } } } AppendNumbers(); return internalStringBuilder.ToString(); void AddNumber(char value) { if (numberList == null) { numberList = new List(); } numberList.Add(value); } void AppendNumbers() { if (numberList != null && numberList.Count > 0) { for (int k = 0; k < numberList.Count; k++) { internalStringBuilder.Append(numberList[numberList.Count - 1 - k]); } numberList.Clear(); } } } internal static ushort HandleInduNumber(ushort letterOrigin, ushort letterFinal) { return letterOrigin switch { 48 => 1632, 49 => 1633, 50 => 1634, 51 => 1635, 52 => 1636, 53 => 1637, 54 => 1638, 55 => 1639, 56 => 1640, 57 => 1641, _ => letterFinal, }; } internal static bool IsIgnoredCharacter(char ch) { bool flag = char.IsPunctuation(ch); bool flag2 = char.IsNumber(ch); bool flag3 = char.IsLower(ch); bool flag4 = char.IsUpper(ch); bool flag5 = char.IsSymbol(ch); bool flag6 = ch == 'ﭖ' || ch == 'ﭺ' || ch == 'ﮊ' || ch == 'ﮒ' || ch == 'ﮎ'; bool flag7 = ch <= '\ufeff' && ch >= 'ﹰ'; bool flag8 = flag7 || flag6 || ch == 'ﯼ'; return flag || flag2 || flag3 || flag4 || flag5 || !flag8 || ch == 'a' || ch == '>' || ch == '<' || ch == '؛'; } internal static bool IsLeadingLetter(char[] letters, int index) { bool flag = index == 0 || letters[index - 1] == ' ' || char.IsPunctuation(letters[index - 1]) || letters[index - 1] == 'ﺍ' || letters[index - 1] == 'ﺩ' || letters[index - 1] == 'ﺫ' || letters[index - 1] == 'ﺭ' || letters[index - 1] == 'ﺯ' || letters[index - 1] == 'ﮊ' || letters[index - 1] == 'ﻭ' || letters[index - 1] == 'ﺁ' || letters[index - 1] == 'ﺃ' || letters[index - 1] == 'ﺀ' || letters[index - 1] == 'ﺇ' || letters[index - 1] == 'ﺅ'; bool flag2 = letters[index] != ' ' && letters[index] != 'ﺩ' && letters[index] != 'ﺫ' && letters[index] != 'ﺭ' && letters[index] != 'ﺯ' && letters[index] != 'ﮊ' && letters[index] != 'ﺍ' && letters[index] != 'ﺃ' && letters[index] != 'ﺇ' && letters[index] != 'ﺁ' && letters[index] != 'ﺅ' && letters[index] != 'ﻭ' && letters[index] != 'ﺀ'; bool flag3 = index < letters.Length - 1 && letters[index + 1] != ' ' && letters[index + 1] != '\n' && letters[index + 1] != '\r' && !char.IsPunctuation(letters[index + 1]) && !char.IsNumber(letters[index + 1]) && !char.IsSymbol(letters[index + 1]) && !char.IsLower(letters[index + 1]) && !char.IsUpper(letters[index + 1]) && letters[index + 1] != 'ﺀ'; if (flag && flag2 && flag3) { return true; } return false; } internal static bool IsFinishingLetter(char[] letters, int index) { bool flag = index != 0; bool flag2 = index != 0 && letters[index - 1] != ' ' && letters[index - 1] != 'ﺩ' && letters[index - 1] != 'ﺫ' && letters[index - 1] != 'ﺭ' && letters[index - 1] != 'ﺯ' && letters[index - 1] != 'ﮊ' && letters[index - 1] != 'ﻭ' && letters[index - 1] != 'ﺍ' && letters[index - 1] != 'ﺁ' && letters[index - 1] != 'ﺃ' && letters[index - 1] != 'ﺇ' && letters[index - 1] != 'ﺅ' && letters[index - 1] != 'ﺀ' && !char.IsPunctuation(letters[index - 1]) && !char.IsSymbol(letters[index - 1]); bool flag3 = letters[index] != ' ' && letters[index] != 'ﺀ'; if (flag2 && flag3) { return true; } return false; } internal static bool IsMiddleLetter(char[] letters, int index) { bool flag = index != 0 && letters[index] != 'ﺍ' && letters[index] != 'ﺩ' && letters[index] != 'ﺫ' && letters[index] != 'ﺭ' && letters[index] != 'ﺯ' && letters[index] != 'ﮊ' && letters[index] != 'ﻭ' && letters[index] != 'ﺁ' && letters[index] != 'ﺃ' && letters[index] != 'ﺇ' && letters[index] != 'ﺅ' && letters[index] != 'ﺀ'; bool flag2 = index != 0 && letters[index - 1] != 'ﺍ' && letters[index - 1] != 'ﺩ' && letters[index - 1] != 'ﺫ' && letters[index - 1] != 'ﺭ' && letters[index - 1] != 'ﺯ' && letters[index - 1] != 'ﮊ' && letters[index - 1] != 'ﻭ' && letters[index - 1] != 'ﺁ' && letters[index - 1] != 'ﺃ' && letters[index - 1] != 'ﺇ' && letters[index - 1] != 'ﺅ' && letters[index - 1] != 'ﺀ' && !char.IsPunctuation(letters[index - 1]) && letters[index - 1] != '>' && letters[index - 1] != '<' && letters[index - 1] != ' ' && letters[index - 1] != '*'; bool flag3 = index < letters.Length - 1 && letters[index + 1] != ' ' && letters[index + 1] != '\r' && letters[index + 1] != 'ﺀ' && !char.IsNumber(letters[index + 1]) && !char.IsSymbol(letters[index + 1]) && !char.IsPunctuation(letters[index + 1]); if (flag3 && flag2 && flag) { try { if (char.IsPunctuation(letters[index + 1])) { return false; } return true; } catch { return false; } } return false; } } namespace GreyAnnouncer.AudioClipLoad { public static class StringExtension { [SpecialName] public sealed class $34505F560D9EACF86A87F3ED1F85E448 { [SpecialName] public static class $D2C87DABA57FE47E39897F3C24A0705C { } [ExtensionMarker("$D2C87DABA57FE47E39897F3C24A0705C")] public AudioType TryGetAudioType() { throw null; } } public static AudioType TryGetAudioType(this string value) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) string[] array = value.Split('.'); for (int i = 1; i <= array.Length; i++) { AudioType unityAudioType = GetUnityAudioType(array[^i]); if ((int)unityAudioType > 0) { return unityAudioType; } } return (AudioType)0; } [Description("https://docs.unity3d.com/2022.3/Documentation//ScriptReference/AudioType.html")] private static AudioType GetUnityAudioType(string extension) { //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) if (1 == 0) { } AudioType result = (AudioType)(extension switch { "aac" => 1, "aiff" => 2, "aif" => 2, "aifc" => 2, "it" => 10, "mod" => 12, "mp3" => 13, "mpga" => 13, "mpeg" => 13, "ogg" => 14, "s3m" => 17, "wav" => 20, "xm" => 21, "xma" => 22, "vag" => 23, _ => 0, }); if (1 == 0) { } return result; } } } namespace UltrakULL { public class NeedDebugMode : Attribute { } public class NeedRework : Attribute { } public class NonSenseNeedChange : Attribute { } public static class Core { public static bool wasLanguageReset; public static void HandleSceneSwitch(Scene scene, ref GameObject canvas) { string currentSceneName = SceneObjects.GetCurrentSceneName(); if (currentSceneName == "Intro" || currentSceneName == "Bootstrap") { return; } GameObject game = SceneObjects.GetInactiveRootObject("Canvas"); if (!Object.op_Implicit((Object)(object)game)) { Logging.Fatal("UNABLE TO FIND CANVAS IN CURRENT SCENE", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); return; } string text = currentSceneName; string text2 = text; if (text2 == "Main Menu") { if (wasLanguageReset) { wasLanguageReset = false; HudMessageReceiver instance = MonoSingleton.Instance; if (instance != null) { instance.SendHudMessage("The currently set language file could not be loaded.\nLanguage has been reset to English to avoid problems.", "", "", 0, false, false, true); } } MainMenu.Patch(game); Options.Patch(ref game); } else if (LanguageManager.IsEnglish) { Logging.Warn("Current language is English, not patching.", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); } else { Logging.Message("Regular scene", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); PatchingBaseElements(ref game); HandleLevelPatching(currentSceneName, ref game); } } private static void PatchingBaseElements(ref GameObject canvasObj) { Logging.Message("Attempting to patch base elements", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); try { _PauseMenu.PatchPauseMenu(ref canvasObj); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } try { Cheats.PatchCheatConsentPanel(ref canvasObj); } catch (Exception ex2) { Console.WriteLine(ex2.ToString()); } try { Sandbox.PatchAlterMenu(); } catch (Exception ex3) { Console.WriteLine(ex3.ToString()); } try { HUDMessages.PatchDeathScreen(ref canvasObj); } catch (Exception ex4) { Console.WriteLine(ex4.ToString()); } try { LevelStatWindow.PatchStats(ref canvasObj); } catch (Exception ex5) { Console.WriteLine(ex5.ToString()); } try { HUDMessages.PatchMisc(ref canvasObj); } catch (Exception ex6) { Console.WriteLine(ex6.ToString()); } try { Options.Patch(ref canvasObj); } catch (Exception ex7) { Console.WriteLine(ex7.ToString()); } Logging.Message("Base elements patched", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); } private static void HandleLevelPatching(string levelName, ref GameObject canvasObj) { if (levelName.Contains("Tutorial")) { Logging.Message("Tutorial", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); } else if (levelName.Contains("-S")) { Logging.Message("Secret", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); SecretLevels.Patch(ref canvasObj); } if (levelName.Contains("0-")) { Logging.Message("Prelude", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); Prelude.Patch(ref canvasObj); } else if (levelName.Contains("1-") || levelName.Contains("2-") || levelName.Contains("3-")) { Logging.Message("Act 1", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); Act1.PatchAct1(ref canvasObj); } else if (levelName.Contains("4-") || levelName.Contains("5-") || levelName.Contains("6-")) { Logging.Message("Act 2", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); Act2.PatchAct2(ref canvasObj); } else if (levelName.Contains("7-") || levelName.Contains("8-") || levelName.Contains("9-")) { Logging.Message("Act 3", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); Act3.PatchAct3(ref canvasObj); } else if (levelName.Contains("P-")) { Logging.Message("Prime", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); PrimeSanctum.Patch(); } else if (levelName == "uk_construct") { Logging.Message("Sandbox", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); Sandbox.Patch(ref canvasObj); } else if (levelName == "Endless") { Logging.Message("CyberGrind", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); CyberGrind.PatchCg(); } else if (levelName.Contains("Intermission") || levelName.Contains("EarlyAccessEnd")) { Logging.Message("Intermission", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); Intermission.Patch(ref canvasObj); } else if (levelName == "CreditsMuseum2") { Logging.Message("DevMuseum", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Core.cs"); DevMuseum.Patch(); } } public static async void ApplyPostInitFixes(GameObject canvasObj) { await Task.Delay(250); if (SceneObjects.GetCurrentSceneName() == "Main Menu") { TextMeshProUGUI openLangFolderText = SceneObjects.GetTextMeshProUGUI(SceneObjects.FindDescendant(canvasObj, "OptionsMenu", "Language Page", "Scroll Rect (1)", "Contents", "OpenLangFolder", "Slot Text")); if ((Object)(object)openLangFolderText != (Object)null) { ((TMP_Text)openLangFolderText).text = "Open language folder"; } } } } public static class FontManager { public static Sprite[] CustomRankImages; public static Sprite ArabicUltrakillLogo; public static bool TMPFontReady; public static TMP_FontAsset MeseumFontAsset; public static TMP_FontAsset TwinFont; private static TMP_FontAsset defaultMainFont; private static TMP_FontAsset defaultMuseumFont; private static TMP_FontAsset defaultTerminalFont; private static TMP_FontAsset defaultSecretFont; public static void Initialize() { LanguageManager.OnLanguageChanged += ApplyLanguageFonts; } public static void LoadFonts() { Logging.Message("Loading font resource bundle...", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\FontManager.cs"); AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(MainPatch.ModFolder, "basegameasset.bundle")); MeseumFontAsset = val.LoadAsset("GFSGaraldus SDF"); TMPFontReady = true; } public static void LoadLangFonts(Lang lang) { if ((Object)(object)lang.FontBundle != (Object)null) { return; } AssetBundle val = AssetBundle.LoadFromFile(lang.FontBundlePath); if ((Object)(object)val == (Object)null) { Logging.Warn("Failed to load language font bundle: " + lang.FontBundlePath, addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\FontManager.cs"); return; } StringBuilder stringBuilder = new StringBuilder(); TMP_FontAsset[] array = val.LoadAllAssets(); foreach (TMP_FontAsset val2 in array) { stringBuilder.AppendLine(((Object)val2).name); } Logging.Info(stringBuilder.ToString() ?? "", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\FontManager.cs"); lang.FontBundle = val; FontsMetadata fonts = lang.Json.metadata.fonts; lang.MainFontAsset = val.LoadAsset("WenQuanYi.Bitmap.Song.12px"); lang.MuseumAsset = val.LoadAsset("WenYuanSerifSC-Regular"); lang.TerminalAsset = val.LoadAsset("fusion-pixel-10px-monospaced-zh_hans"); lang.SecretTerminalAsset = val.LoadAsset("WenQuanYi.Bitmap.Song.16px"); } private static void ResolveFonts(Lang lang) { Lang lang2 = lang; if (lang2.MainFontAsset == null) { TMP_FontAsset val = (lang2.MainFontAsset = defaultMainFont); } lang2 = lang; if (lang2.MuseumAsset == null) { TMP_FontAsset val = (lang2.MuseumAsset = defaultMuseumFont); } lang2 = lang; if (lang2.TerminalAsset == null) { TMP_FontAsset val = (lang2.TerminalAsset = defaultTerminalFont); } lang2 = lang; if (lang2.SecretTerminalAsset == null) { TMP_FontAsset val = (lang2.SecretTerminalAsset = defaultSecretFont); } } private static void ApplyLanguageFonts(ValueChangedEvent change) { if (!TMPFontReady) { return; } RemoveFallbacksOf(change.OldValue); Lang newValue = change.NewValue; if (newValue != null && !newValue.IsEnglish) { LoadLangFonts(newValue); ResolveFonts(newValue); if (newValue.UseFontFallback) { RegisterFallbacksForLoadedFonts(newValue); } } } public static void RefreshFallback() { Lang current = LanguageManager.Current; if (TMPFontReady && current != null && !current.IsEnglish && current.UseFontFallback) { RegisterFallbacksForLoadedFonts(current); } } private static void RegisterFallbacksForLoadedFonts(Lang lang) { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset val in array) { if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)val).name?.ToLowerInvariant(); if (!string.IsNullOrEmpty(text) && !text.Contains("_alignedto_") && !((Object)(object)val == (Object)(object)lang.MainFontAsset) && !((Object)(object)val == (Object)(object)lang.MuseumAsset) && !((Object)(object)val == (Object)(object)lang.TerminalAsset) && !((Object)(object)val == (Object)(object)lang.SecretTerminalAsset)) { TMP_FontAsset fallback = null; if (text.Contains("tahoma")) { fallback = lang.TerminalAsset; } else if (text.Contains("bittypix")) { fallback = lang.SecretTerminalAsset; } else if (text.Contains("garaldus") || text.Contains("garamond") || text.Contains("museum")) { fallback = lang.MuseumAsset; } else if (text.Contains("vcr-osd-replayed")) { fallback = lang.MainFontAsset; } if (text.Contains("vcr_osd_mono_ui")) { TwinFont = val; } AddFallback(lang, val, fallback); } } } public static TMP_FontAsset GetTwinFont(string sourceFontName) { string text = sourceFontName?.ToLowerInvariant(); bool flag = !string.IsNullOrEmpty(text) && (text.Contains("garaldus") || text.Contains("garamond") || text.Contains("museum")); TMP_FontAsset val = (flag ? (MeseumFontAsset ?? TwinFont) : TwinFont); Lang current = LanguageManager.Current; if (current == null || current.IsEnglish || current.UseFontFallback) { return val; } return flag ? (current.MuseumAsset ?? current.MainFontAsset ?? val) : (current.MainFontAsset ?? val); } private static void AddFallback(Lang lang, TMP_FontAsset primary, TMP_FontAsset fallback) { if (!((Object)(object)primary == (Object)null) && !((Object)(object)fallback == (Object)null) && !((Object)(object)primary == (Object)(object)fallback)) { if (primary.fallbackFontAssetTable == null) { List list = (primary.fallbackFontAssetTable = new List()); } if (!primary.fallbackFontAssetTable.Contains(fallback)) { primary.fallbackFontAssetTable.Add(fallback); lang.AppliedFallbacks.Add((primary, fallback)); } } } private static void RemoveFallbacksOf(Lang lang) { if (lang == null) { return; } foreach (var (val, item) in lang.AppliedFallbacks) { if (val != null) { val.fallbackFontAssetTable?.Remove(item); } } lang.AppliedFallbacks.Clear(); } } public static class Logging { public static ManualLogSource UllLogger = Logger.CreateLogSource("ULL LOGGING"); public static void Debug(string text, bool addCallerFilePath = false, [CallerFilePath] string callerFilePath = "") { UllLogger.LogDebug((object)TryAddCallerName(text, addCallerFilePath, callerFilePath)); } public static void Message(string text, bool addCallerFilePath = false, [CallerFilePath] string callerFilePath = "") { UllLogger.LogMessage((object)TryAddCallerName(text, addCallerFilePath, callerFilePath)); } public static void Warn(string text, bool addCallerFilePath = false, [CallerFilePath] string callerFilePath = "") { UllLogger.LogWarning((object)TryAddCallerName(text, addCallerFilePath, callerFilePath)); } public static void Error(string text, bool addCallerFilePath = false, [CallerFilePath] string callerFilePath = "") { UllLogger.LogError((object)TryAddCallerName(text, addCallerFilePath, callerFilePath)); } public static void Fatal(string text, bool addCallerFilePath = false, [CallerFilePath] string callerFilePath = "") { UllLogger.LogFatal((object)TryAddCallerName(text, addCallerFilePath, callerFilePath)); } public static void Info(string text, bool addCallerFilePath = false, [CallerFilePath] string callerFilePath = "") { UllLogger.LogInfo((object)TryAddCallerName(text, addCallerFilePath, callerFilePath)); } private static string TryAddCallerName(string text, bool addCallerFilePath, string callerFilePath) { return addCallerFilePath ? ("[" + GetFileName(callerFilePath) + "] " + text) : text; } private static string GetFileName(string callerFilePath) { return Path.GetFileNameWithoutExtension(callerFilePath); } } [BepInPlugin("clearwater.ultrakill.ultrakull", "clearwater.ultrakull.ultrakULL", "1.3.0")] public class MainPatch : BaseUnityPlugin { private const string Guid = "clearwater.ultrakill.ultrakull"; private const string InternalName = "clearwater.ultrakull.ultrakULL"; private const string InternalVersion = "1.3.0"; public static MainPatch Instance; public bool ready; public static string ModFolder => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public static string GetVersion() { return "1.3.0"; } public void OnApplicationQuit() { LanguageManager.DumpLastLanguage(); } public void DisableMod() { ready = false; } private void Awake() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) Instance = this; Debug.unityLogger.filterLogType = (LogType)4; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)4; Logging.Warn("UltrakULL Loading... | Version v.1.3.0", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); try { Logging.Warn("--- Loading default fonts ---", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); FontManager.LoadFonts(); Logging.Warn("--- Register events ---", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); FontManager.Initialize(); TextMeshProFontSwap.Initialize(); SubtitleLocalizer.Initialize(); TextureSwapper.Initialize(); Logging.Warn("--- Initializing language manager ---", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); LanguageManager.InitializeManager("1.3.0"); Logging.Warn("--- Patching vanilla game functions ---", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); new Harmony("clearwater.ultrakull.ultrakULL").PatchAll(); Logging.Warn(" --- All done. Enjoy! ---", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); SceneManager.sceneLoaded += onSceneLoaded; ready = true; } catch (Exception ex) { Logging.Fatal("An error occured while initialising!", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); Logging.Fatal(ex.ToString(), addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); ready = false; } } public void onSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!ready || LanguageManager.CurrentLanguage == null) { Logging.Error("UltrakULL has been deactivated to prevent crashing. Check the console for any errors!", addCallerFilePath: false, "H:\\C#Project\\UltrakULL-1\\src\\Core\\Main.cs"); return; } SceneObjects.ClearObjectCaches(scene, mode); FontManager.RefreshFallback(); GameObject canvas = SceneObjects.GetInactiveRootObject("Canvas"); Core.HandleSceneSwitch(scene, ref canvas); AudioSwapper.OnSceneLoaded(SceneObjects.GetCurrentSceneName()); RunDeferred(canvas); } private async void RunDeferred(GameObject canvasObj) { await Task.Delay(250); Core.ApplyPostInitFixes(canvasObj); SubtitledAudioSourcesReplacer.ReplaceSubsAndAudio(); TextureSwapper.Apply(); } } public class SubtitledSourcesConfig { [JsonProperty("scenes")] public Dictionary> Scenes; } public class SubtitledObjectReference { [JsonProperty("objects")] public List Objects; [JsonProperty("audio")] public string AudioPath; [JsonProperty("lines")] public List Lines; public SubtitleData ToSubtitleData() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown return new SubtitleData { lines = ((IEnumerable)Lines).Select((Func)((Line line) => new SubtitleDataLine { subtitle = ColorIfNecessary(LanguageManager.CurrentLanguage.subtitles.GetField(line.Reference), line.Color), time = line.Delay })).ToArray() }; } private static string ColorIfNecessary(string line, string color) { if (color == null) { return line; } return "" + line + ""; } } public class Line { [JsonProperty("line")] public string Reference; [JsonProperty("delay")] public float Delay; [JsonProperty("color")] public string Color; } public static class SubtitledAudioSourcesReplacer { public static SubtitledSourcesConfig Config; public static void ReplaceSubsAndAudio() { if (!TryLoadMetadata(out var references)) { return; } List<(AudioSource source, string path)> audioReplacements = new List<(AudioSource, string)>(); foreach (SubtitledObjectReference item in references) { foreach (string @object in item.Objects) { GameObject val = SceneObjects.GetObject(@object); SubtitledAudioSource component = val.GetComponent(); if (ActiveDubbingEnabled()) { audioReplacements.Add((val.GetComponentInChildren(), Path.Combine(AudioSwapper.SpeechFolder, item.AudioPath))); } if ((Object)(object)component != (Object)null) { ReflectionUtils.SetPrivate(component, typeof(SubtitledAudioSource), "subtitles", item.ToSubtitleData()); } } } AudioSwapper.WhenReady(delegate { foreach (var item2 in audioReplacements) { item2.source.clip = AudioSwapper.SwapClipWithFile(item2.source.clip, item2.path); } }); } private static bool ActiveDubbingEnabled() { return LanguageManager.configFile.Bind("General", "activeDubbing", "False", (ConfigDescription)null).Value != "False"; } private static bool TryLoadMetadata(out List references) { if (Config != null && Config.Scenes.TryGetValue(SceneObjects.GetCurrentSceneName(), out references)) { return true; } references = null; return false; } } public static class SubtitleLocalizer { private static readonly Dictionary map = new Dictionary(StringComparer.Ordinal); private static readonly MethodInfo DisplaySubtitle = AccessTools.Method(typeof(SubtitleController), "DisplaySubtitle", new Type[3] { typeof(string), typeof(AudioSource), typeof(bool) }, (Type[])null); private static readonly MethodInfo LocalizeMethod = AccessTools.Method(typeof(SubtitleLocalizer), "Localize", (Type[])null, (Type[])null); public static void Initialize() { LanguageManager.OnLanguageChanged += delegate { Rebuild(); }; } private static void Rebuild() { map.Clear(); Subtitles subtitles = LanguageManager.allLanguages.Values.FirstOrDefault((Lang l) => l.IsEnglish)?.Json?.subtitles; Subtitles subtitles2 = LanguageManager.Current?.Json?.subtitles; if (subtitles == null || subtitles2 == null) { return; } FieldInfo[] fields = typeof(Subtitles).GetFields(); foreach (FieldInfo fieldInfo in fields) { string text = fieldInfo.GetValue(subtitles) as string; string text2 = fieldInfo.GetValue(subtitles2) as string; if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && text != text2) { map[text] = text2; } } } public static string Localize(string caption) { if (string.IsNullOrEmpty(caption) || LanguageManager.IsEnglish) { return caption; } string value; return map.TryGetValue(caption, out value) ? value : caption; } public static IEnumerable InjectLocalize(IEnumerable instructions) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown List list = instructions.ToList(); List list2 = new List(list.Count + 4); for (int i = 0; i < list.Count; i++) { list2.Add(list[i]); if (i + 3 < list.Count && IsDisplaySubtitleCall(list[i + 3])) { list2.Add(new CodeInstruction(OpCodes.Call, (object)LocalizeMethod)); } } return list2; } private static bool IsDisplaySubtitleCall(CodeInstruction instruction) { return instruction.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)DisplaySubtitle); } } internal static class StaticBatchAtlasSwapper { private readonly struct Template { public readonly string Name; public readonly int Width; public readonly int Height; public readonly Color32[] Pixels; public Template(string name, int width, int height, Color32[] pixels) { Name = name; Width = width; Height = height; Pixels = pixels; } } private sealed class AtlasState(Texture2D texture, Color32[] originalPixels) { public readonly Texture2D Texture = texture; public readonly Color32[] OriginalPixels = originalPixels; public readonly List<(string Name, RectInt Rect)> Regions = new List<(string, RectInt)>(); } private readonly struct FeaturePoint { public readonly int X; public readonly int Y; public readonly Color32 Color; public readonly int Contrast; public FeaturePoint(int x, int y, Color32 color, int contrast) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) X = x; Y = y; Color = color; Contrast = contrast; } } private static readonly List