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.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BoplFixedMath; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("OctoLib")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OctoLib")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b53f1668-a5e9-4325-b51a-d9755681ae6c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace OctoLib; public static class Abilities { public class BaseAbilityRegistration { public string BaseAbilityName { get; set; } public string NewAbilityName { get; set; } public Texture2D IconTexture { get; set; } public Assembly OwnerAssembly { get; set; } } public class CustomAbilityRegistration { public string NewAbilityName { get; set; } public Texture2D IconTexture { get; set; } public GameObject GameObjectPrefab { get; set; } public Assembly OwnerAssembly { get; set; } } public class AbilityCooldown { public string AbilityName { get; set; } public Fix Cooldown { get; set; } } public class AbilityOffensive { public string AbilityName { get; set; } public bool Offensive { get; set; } } public class AbilityBackground { public string AbilityName { get; set; } public Texture2D Background { get; set; } public Assembly OwnerAssembly { get; set; } } [HarmonyPatch(typeof(SteamManager), "Awake")] public static class SteamManagerPatch { [HarmonyPostfix] public static void Postfix(SteamManager __instance, ref NamedSpriteList ___abilityIconsFull) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if (___abilityIconsFull.sprites.Count != 30) { return; } NamedSprite item = default(NamedSprite); foreach (CustomAbilityRegistration item2 in _ability) { Object.DontDestroyOnLoad((Object)(object)item2.GameObjectPrefab); Texture2D iconTexture = item2.IconTexture; Texture2D backgroundTexture = GetBackgroundTexture(item2.NewAbilityName); Texture2D val = CreateAbilityTexture(iconTexture, backgroundTexture); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, Vector4.op_Implicit(Vector2.zero), false); bool isOffensive = GetIsOffensive(item2.NewAbilityName); ((NamedSprite)(ref item))..ctor(item2.NewAbilityName, val2, item2.GameObjectPrefab, isOffensive); ___abilityIconsFull.sprites.Add(item); } } } [HarmonyPatch(typeof(AbilityGrid), "Awake")] private static class AbilityGridAwakePatch { [HarmonyPrefix] public static void Prefix(AbilityGrid __instance) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (_hasInjected || _abilitywithbase.Count == 0) { return; } Traverse val = Traverse.Create((object)__instance); NamedSpriteList value = val.Field("abilityIcons").GetValue(); if (value?.sprites == null) { Plugin.Logger.LogWarning((object)"[OctoLib] Could not find abilityIcons list!"); return; } if (Plugin.debugLogged.Value) { foreach (NamedSprite sprite in value.sprites) { Plugin.Logger.LogWarning((object)("[OctoLib] Ability Names: '" + sprite.name + "'")); } } foreach (BaseAbilityRegistration item in _abilitywithbase) { InjectAbility(value, item); } foreach (CustomAbilityRegistration item2 in _ability) { InjectCustomAbility(value, item2); } _hasInjected = true; } } private static readonly List _abilitywithbase = new List(); private static readonly List _cooldowns = new List(); private static readonly List _offensive = new List(); private static readonly List _backgrounds = new List(); private static readonly List _ability = new List(); private static bool _hasInjected = false; public static void NewAbilityWithBase(string baseAbilityName, string newAbilityName, Texture2D iconTexture) { if (string.IsNullOrEmpty(baseAbilityName) || string.IsNullOrEmpty(newAbilityName)) { Plugin.Logger.LogWarning((object)"[OctoLib] NewAbilityWithBase: base or new name is empty!"); return; } Assembly callingAssembly = GetCallingAssembly(); _abilitywithbase.Add(new BaseAbilityRegistration { BaseAbilityName = baseAbilityName, NewAbilityName = newAbilityName, IconTexture = iconTexture, OwnerAssembly = callingAssembly }); Plugin.Logger.LogInfo((object)("[OctoLib] Registered: " + newAbilityName + " (based on '" + baseAbilityName + "') from " + callingAssembly.GetName().Name)); } public static void NewAbility(string newAbilityName, Texture2D iconTexture, GameObject GameObjectPrefab) { if (string.IsNullOrEmpty(newAbilityName)) { Plugin.Logger.LogWarning((object)"[OctoLib] NewAbilityWithBase: base or new name is empty!"); return; } Assembly callingAssembly = GetCallingAssembly(); _ability.Add(new CustomAbilityRegistration { NewAbilityName = newAbilityName, IconTexture = iconTexture, GameObjectPrefab = GameObjectPrefab, OwnerAssembly = callingAssembly }); Plugin.Logger.LogInfo((object)("[OctoLib] Registered: " + newAbilityName + " from " + callingAssembly.GetName().Name)); } public static void AbilitySetCooldown(string AbilityName, Fix Cooldown) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(AbilityName)) { Plugin.Logger.LogWarning((object)"[OctoLib] AbilitySetCooldown: name is empty!"); return; } _cooldowns.Add(new AbilityCooldown { AbilityName = AbilityName, Cooldown = Cooldown }); } public static void AbilitySetOffensive(string AbilityName, bool Offensive) { if (string.IsNullOrEmpty(AbilityName)) { Plugin.Logger.LogWarning((object)"[OctoLib] AbilitySetCooldown: name is empty!"); return; } _offensive.Add(new AbilityOffensive { AbilityName = AbilityName, Offensive = Offensive }); } public static void AbilitySetBackground(string AbilityName, Texture2D Background) { if (string.IsNullOrEmpty(AbilityName)) { Plugin.Logger.LogWarning((object)"[OctoLib] AbilitySetCooldown: name is empty!"); return; } Assembly callingAssembly = GetCallingAssembly(); _backgrounds.Add(new AbilityBackground { AbilityName = AbilityName, Background = Background, OwnerAssembly = callingAssembly }); } private static void InjectAbility(NamedSpriteList list, BaseAbilityRegistration reg) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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) Plugin.Logger.LogWarning((object)("[OctoLib] Start adding ability: '" + reg.NewAbilityName + "'")); NamedSprite val = default(NamedSprite); NamedSprite val2 = default(NamedSprite); bool flag = false; foreach (NamedSprite sprite in list.sprites) { if (sprite.name.Equals("Random")) { val2 = sprite; Plugin.Logger.LogWarning((object)"[OctoLib] Random Sprite found!"); } if (sprite.name.Equals(reg.BaseAbilityName)) { val = sprite; flag = true; } } if (!flag) { Plugin.Logger.LogWarning((object)("[OctoLib] Base ability '" + reg.BaseAbilityName + "' not found!")); return; } GameObject val3 = Object.Instantiate(val.associatedGameObject); Object.DontDestroyOnLoad((Object)(object)val3); ((Object)val3).name = reg.NewAbilityName; Fix cooldown = GetCooldown(reg.NewAbilityName); if (cooldown != (Fix)(-1f)) { Ability component = val3.GetComponent(); if ((Object)(object)component != (Object)null) { component.Cooldown = cooldown; } } Texture2D iconTexture = reg.IconTexture; Texture2D backgroundTexture = GetBackgroundTexture(reg.NewAbilityName); Sprite val5; if ((Object)(object)iconTexture != (Object)null) { Texture2D val4 = CreateAbilityTexture(iconTexture, backgroundTexture); val5 = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), new Vector2(0.5f, 0.5f), val2.sprite.pixelsPerUnit, 0u, (SpriteMeshType)0, Vector4.op_Implicit(Vector2.zero), false); ((Texture)val5.texture).filterMode = ((Texture)val2.sprite.texture).filterMode; ((Texture)val5.texture).wrapMode = ((Texture)val2.sprite.texture).wrapMode; } else { val5 = val2.sprite; } bool isOffensive = GetIsOffensive(reg.NewAbilityName); NamedSprite item = default(NamedSprite); ((NamedSprite)(ref item))..ctor(reg.NewAbilityName, val5, val3, isOffensive); list.sprites.Add(item); Plugin.Logger.LogInfo((object)("[OctoLib] Injected: " + reg.NewAbilityName)); } private static void InjectCustomAbility(NamedSpriteList list, CustomAbilityRegistration reg) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) Plugin.Logger.LogWarning((object)("[OctoLib] Start adding ability: '" + reg.NewAbilityName + "'")); NamedSprite val = default(NamedSprite); Object.DontDestroyOnLoad((Object)(object)reg.GameObjectPrefab); foreach (NamedSprite sprite in list.sprites) { if (sprite.name.Equals("Random")) { val = sprite; Plugin.Logger.LogWarning((object)"[OctoLib] Random sprite found!"); break; } } Fix cooldown = GetCooldown(reg.NewAbilityName); if (cooldown != (Fix)(-1f)) { Ability component = reg.GameObjectPrefab.GetComponent(); if ((Object)(object)component != (Object)null) { component.Cooldown = cooldown; } } Texture2D iconTexture = reg.IconTexture; Texture2D backgroundTexture = GetBackgroundTexture(reg.NewAbilityName); Sprite val3; if ((Object)(object)iconTexture != (Object)null) { Texture2D val2 = CreateAbilityTexture(iconTexture, backgroundTexture); val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), new Vector2(0.5f, 0.5f), val.sprite.pixelsPerUnit, 0u, (SpriteMeshType)0, Vector4.op_Implicit(Vector2.zero), false); ((Texture)val3.texture).filterMode = ((Texture)val.sprite.texture).filterMode; ((Texture)val3.texture).wrapMode = ((Texture)val.sprite.texture).wrapMode; } else { val3 = val.sprite; } bool isOffensive = GetIsOffensive(reg.NewAbilityName); NamedSprite item = default(NamedSprite); ((NamedSprite)(ref item))..ctor(reg.NewAbilityName, val3, reg.GameObjectPrefab, isOffensive); list.sprites.Add(item); Plugin.Logger.LogInfo((object)("[OctoLib] Injected: " + reg.NewAbilityName)); } private static Assembly GetCallingAssembly() { StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: false); for (int i = 0; i < stackTrace.FrameCount; i++) { Assembly assembly = stackTrace.GetFrame(i).GetMethod()?.DeclaringType?.Assembly; if (assembly != null && assembly != typeof(Abilities).Assembly && assembly != typeof(Textures).Assembly) { return assembly; } } return Assembly.GetExecutingAssembly(); } private static bool GetIsOffensive(string abilityName) { foreach (AbilityOffensive item in _offensive) { if (item.AbilityName == abilityName) { return item.Offensive; } } return false; } private static Fix GetCooldown(string abilityName) { //IL_0028: 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_004c: 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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) foreach (AbilityCooldown cooldown in _cooldowns) { if (abilityName == cooldown.AbilityName) { return cooldown.Cooldown; } } return (Fix)(-1L); } private static Texture2D GetBackgroundTexture(string abilityName) { foreach (AbilityBackground background in _backgrounds) { if (background.AbilityName == abilityName) { return background.Background; } } return null; } private static Texture2D CreateAbilityTexture(Texture2D AbilityTexture, Texture2D AbilityBGTexture = null) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)AbilityBGTexture == (Object)null) { AbilityBGTexture = Textures.LoadFromAssembly("AbilityBg", Plugin.OctoLibAssembly); } Texture2D val = new Texture2D(2048, 2048, (TextureFormat)4, true); Color[] array = (Color[])(object)new Color[4194304]; for (int i = 0; i < array.Length; i++) { array[i] = Color.clear; } val.SetPixels(array); if ((Object)(object)AbilityBGTexture != (Object)null) { Color[] pixels = AbilityBGTexture.GetPixels(); int width = ((Texture)AbilityBGTexture).width; int height = ((Texture)AbilityBGTexture).height; int num = 0; int num2 = 2048 - height; for (int j = 0; j < height; j++) { for (int k = 0; k < width; k++) { if (num + k < 2048 && num2 + j < 2048) { val.SetPixel(num + k, num2 + j, pixels[j * width + k]); } } } } if ((Object)(object)AbilityTexture != (Object)null) { Color[] pixels2 = AbilityTexture.GetPixels(); int width2 = ((Texture)AbilityTexture).width; int height2 = ((Texture)AbilityTexture).height; int num3 = 0; int num4 = 0; for (int l = 0; l < height2; l++) { for (int m = 0; m < width2; m++) { if (num3 + m < 2048 && num4 + l < 2048) { val.SetPixel(num3 + m, num4 + l, pixels2[l * width2 + m]); } } } } val.Apply(); return val; } } public static class Animations { } public static class Audio { public class NewSoundRegistration { public string NewSoundName { get; set; } public string NewSoundFolder { get; set; } public bool IsLoop { get; set; } } [HarmonyPatch(typeof(AudioManager), "Awake")] public static class AudioManagerPatch { [HarmonyPostfix] public static void Awake(AudioManager __instance) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (_hasInjected) { return; } int num = __instance.sounds.Length; FieldInfo field = typeof(AudioManager).GetField("timesSoundPlayed", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = typeof(AudioManager).GetField("isSoundLooping", BindingFlags.Instance | BindingFlags.NonPublic); field.SetValue(__instance, new int[__instance.sounds.Length + _sounds.Count]); field2.SetValue(__instance, new bool[__instance.sounds.Length + _sounds.Count]); Sound[] array = (Sound[])(object)new Sound[__instance.sounds.Length + _sounds.Count]; Array.Copy(__instance.sounds, array, __instance.sounds.Length); foreach (NewSoundRegistration sound in _sounds) { Sound val = SoundInject(sound); array[num] = val; array[num].source = ((Component)__instance).gameObject.AddComponent(); num++; } __instance.sounds = array; __instance.ReInitializeSfx(); if (Plugin.debugLogged.Value) { for (int i = 0; i < __instance.sounds.Length; i++) { Plugin.Logger.LogInfo((object)("AudioManager sounds name: " + __instance.sounds[i].name)); } } _hasInjected = true; } } private static readonly List _sounds = new List(); private static bool _hasInjected = false; public static void AddSound(string NewSoundName, string NewSoundFolder, bool IsLoop = false) { if (string.IsNullOrEmpty(NewSoundName)) { Plugin.Logger.LogWarning((object)"[OctoLib] NewSoundName: name is empty!"); return; } if (string.IsNullOrEmpty(NewSoundFolder)) { Plugin.Logger.LogWarning((object)"[OctoLib] NewSoundFolder: name is empty!"); return; } _sounds.Add(new NewSoundRegistration { NewSoundName = NewSoundName, NewSoundFolder = NewSoundFolder, IsLoop = IsLoop }); } public static string GetFilePath(string name, string path) { Plugin.Logger.LogInfo((object)("FilePath is " + path)); List list = new List(Directory.GetFiles(path)); foreach (string item in list) { if (item.EndsWith(name)) { return item; } } return null; } public static string FilePathToFileUrl(string path) { return new UriBuilder("file", string.Empty) { Path = path.Replace("%", $"%{37:X2}").Replace("[", $"%{91:X2}").Replace("]", $"%{93:X2}") }.Uri.AbsoluteUri; } public static AudioClip GetAudioClip(string filePath, AudioType fileType) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 Plugin.Logger.LogInfo((object)(FilePathToFileUrl(filePath) ?? "")); UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(FilePathToFileUrl(filePath), fileType); try { UnityWebRequestAsyncOperation val = audioClip.SendWebRequest(); while (!((AsyncOperation)val).isDone) { Thread.Sleep(100); } if ((int)audioClip.result != 1) { Plugin.Logger.LogError((object)("[OctoLib] Failed to load audio " + filePath + ": " + audioClip.error)); return null; } AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip); ((Object)content).name = Path.GetFileNameWithoutExtension(filePath); return content; } finally { ((IDisposable)audioClip)?.Dispose(); } } private static AudioType GetAudioType(string path) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) string text = Path.GetExtension(path).ToLower(); AudioType result = (AudioType)0; if (text == ".ogg") { result = (AudioType)14; } if (text == ".wav") { result = (AudioType)20; } if (text == ".mp3") { result = (AudioType)13; } return result; } private static Sound SoundInject(NewSoundRegistration reg) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) string filePath = GetFilePath(reg.NewSoundName, reg.NewSoundFolder); AudioClip audioClip = GetAudioClip(filePath, GetAudioType(filePath)); if ((Object)(object)audioClip == (Object)null) { Plugin.Logger.LogError((object)("AudioClip in path " + GetFilePath(reg.NewSoundName, reg.NewSoundFolder) + " is null")); } string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(reg.NewSoundName); Plugin.Logger.LogInfo((object)("new sound name: " + fileNameWithoutExtension)); return new Sound { name = fileNameWithoutExtension, clip = audioClip, volume = 1f, pitch = 1f, loop = reg.IsLoop }; } } public static class Localization { [HarmonyPatch(typeof(LocalizationTable), "getText")] private static class LocalizationTablePatch { [HarmonyPrefix] public static bool Prefix(string enText, string[] languageArray, ref string __result) { //IL_0018: 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: Unknown result type (might be due to invalid IL or missing references) if (_translations.TryGetValue(enText, out var value)) { Language language = Settings.Get().Language; if (value.TryGetValue(language, out var value2)) { __result = value2.ToUpper(); return false; } } return true; } } private static readonly Dictionary> _translations = new Dictionary>(StringComparer.OrdinalIgnoreCase); private static bool _hasInjected = false; public static void AddTranslation(string englishText, Language language, string translatedText) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(englishText) && !string.IsNullOrEmpty(translatedText)) { if (!_translations.ContainsKey(englishText)) { _translations[englishText] = new Dictionary(); } _translations[englishText][language] = translatedText; Plugin.Logger.LogInfo((object)$"[OctoLib] Translation added: '{englishText}' → {language}"); } } public static void AddTranslations(string englishText, params (Language lang, string text)[] translations) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < translations.Length; i++) { var (language, translatedText) = translations[i]; AddTranslation(englishText, language, translatedText); } } } [BepInPlugin("com.OctoLab.OctoLib", "OctoLib", "0.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; public static ConfigEntry debugLogged; public static Assembly OctoLibAssembly; private void Awake() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; OctoLibAssembly = Assembly.GetExecutingAssembly(); debugLogged = ((BaseUnityPlugin)this).Config.Bind("Debug", "DebugLogger", false, "Show some debug logs"); Harmony val = new Harmony("com.OctoLab.OctoLib"); val.PatchAll(); Logger.LogInfo((object)"OctoLib is working"); CharacterSelectHandler_online.clientSideMods_you_can_increment_this_to_enable_matchmaking_for_your_mods__please_dont_use_it_to_cheat_thats_really_cringe_especially_if_its_desyncing_others___you_didnt_even_win_on_your_opponents_screen___I_cannot_imagine_a_sadder_existence++; } } public static class Textures { private static readonly Dictionary _cache = new Dictionary(); public static Texture2D Load(string name, bool usePointFilter = true) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown if (string.IsNullOrEmpty(name)) { return null; } if (_cache.TryGetValue(name, out var value)) { return value; } byte[] array = LoadRawBytes(name); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (usePointFilter) { ((Texture)val).filterMode = (FilterMode)0; } ImageConversion.LoadImage(val, array, false); ((Object)val).name = name; _cache[name] = val; return val; } public static byte[] LoadRawBytes(string name) { if (string.IsNullOrEmpty(name)) { return null; } Assembly callingAssembly = GetCallingAssembly(); string[] manifestResourceNames = callingAssembly.GetManifestResourceNames(); if (Plugin.debugLogged.Value) { Plugin.Logger.LogInfo((object)("=== Embedded Resources in " + callingAssembly.GetName().Name + " ===")); string[] array = manifestResourceNames; foreach (string text in array) { Plugin.Logger.LogInfo((object)(" - " + text)); } Plugin.Logger.LogInfo((object)"====================================="); } string text2 = FindResourceName(manifestResourceNames, name); if (text2 != null) { return LoadFromResource(callingAssembly, text2); } string directoryName = Path.GetDirectoryName(callingAssembly.Location); string[] array2 = new string[3] { Path.Combine(directoryName, name), Path.Combine(directoryName, name + ".png"), Path.Combine(directoryName, name.ToLower() + ".png") }; string[] array3 = array2; foreach (string text3 in array3) { if (File.Exists(text3)) { Plugin.Logger.LogInfo((object)("[OctoLib] Loaded from file: " + text3)); return File.ReadAllBytes(text3); } } Plugin.Logger.LogWarning((object)("[OctoLib] Texture not found: " + name)); return null; } private static Assembly GetCallingAssembly() { StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: false); for (int i = 0; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); Assembly assembly = frame.GetMethod()?.DeclaringType?.Assembly; if (assembly != null && assembly != typeof(Textures).Assembly) { return assembly; } } return Assembly.GetExecutingAssembly(); } private static string FindResourceName(string[] allResources, string name) { string value = name.ToLower(); foreach (string text in allResources) { if (text.Equals(name, StringComparison.OrdinalIgnoreCase) || text.Equals(name + ".png", StringComparison.OrdinalIgnoreCase) || text.ToLower().Contains(value)) { return text; } } return null; } private static byte[] LoadFromResource(Assembly asm, string resourceName) { Stream stream = null; try { stream = asm.GetManifestResourceStream(resourceName); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Plugin.Logger.LogInfo((object)("[OctoLib] Loaded embedded: " + resourceName)); return array; } finally { stream?.Dispose(); } } public static Texture2D GetTexture(string filePath) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 Plugin.Logger.LogInfo((object)(Audio.FilePathToFileUrl(filePath) ?? "")); UnityWebRequest val = new UnityWebRequest(Audio.FilePathToFileUrl(filePath)); try { UnityWebRequestAsyncOperation val2 = val.SendWebRequest(); while (!((AsyncOperation)val2).isDone) { Thread.Sleep(100); } if ((int)val.result != 1) { Plugin.Logger.LogError((object)("[OctoLib] Failed to load image " + filePath + ": " + val.error)); return null; } return DownloadHandlerTexture.GetContent(val); } finally { ((IDisposable)val)?.Dispose(); } } public static Texture2D LoadFromFiles(string name, string folder) { string filePath = Audio.GetFilePath(name, folder); if (_cache.TryGetValue(filePath, out var value)) { return value; } Texture2D texture = GetTexture(filePath); _cache[filePath] = texture; return texture; } public static Texture2D LoadFromAssembly(string name, Assembly assembly, bool usePointFilter = true) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (string.IsNullOrEmpty(name) || assembly == null) { return null; } byte[] array = LoadRawBytesFromAssembly(name, assembly); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (usePointFilter) { ((Texture)val).filterMode = (FilterMode)0; } ImageConversion.LoadImage(val, array, false); ((Object)val).name = name; _cache[name] = val; return val; } private static byte[] LoadRawBytesFromAssembly(string name, Assembly assembly) { if (string.IsNullOrEmpty(name)) { return null; } string[] manifestResourceNames = assembly.GetManifestResourceNames(); string text = FindResourceName(manifestResourceNames, name); if (text == null) { return null; } return LoadFromResource(assembly, text); } public static Texture2D ExtractTextureFromSprite(Sprite sprite) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if ((Object)(object)sprite == (Object)null) { Debug.LogError((object)"[SpriteExtractor] Sprite is null!"); return null; } Texture2D texture = sprite.texture; if ((Object)(object)texture == (Object)null) { Debug.LogError((object)"[SpriteExtractor] Sprite texture is null!"); return null; } Rect rect = sprite.rect; Texture2D val = new Texture2D((int)((Rect)(ref rect)).width, (int)((Rect)(ref rect)).height, texture.format, false); Color[] pixels = texture.GetPixels((int)((Rect)(ref rect)).x, (int)((Rect)(ref rect)).y, (int)((Rect)(ref rect)).width, (int)((Rect)(ref rect)).height); val.SetPixels(pixels); val.Apply(); return val; } public static void ClearCache() { _cache.Clear(); } }