RUMBLE does not support other mod managers. If you want to use a manager, you must use the RUMBLE Mod Manager, a manager specifically designed for this game.
Decompiled source of AdvancedStructureSkins v1.1.0
Mods/AdvancedStructureSkins.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppRUMBLE.Environment; using Il2CppRUMBLE.Managers; using Il2CppRUMBLE.MoveSystem; using Il2CppRUMBLE.Players; using Il2CppSmartLocalization; using Il2CppSystem; using MelonLoader; using MelonLoader.Utils; using RumbleModUI; using RumbleModdingAPI; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(AdvancedStructureSkins), "Advanced Structure Skins", "1.1.0", "Cxntrxl", null)] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: MelonColor(255, 210, 180, 145)] [assembly: MelonAuthorColor(255, 5, 210, 240)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("AdvancedStructureSkins")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AdvancedStructureSkins")] [assembly: AssemblyTitle("AdvancedStructureSkins")] [assembly: AssemblyVersion("1.0.0.0")] public static class BuildInfo { public const string ModName = "Advanced Structure Skins"; public const string ModVersion = "1.1.0"; public const string ModAuthor = "Cxntrxl"; public const string Description = "Allows custom shaders and skins to be applied to structures, and provides mod developers with a simple API for loading their own shaders."; } public class AdvancedStructureSkins : MelonMod { public SkinHandler Skins = new SkinHandler(); public static Mod AssUI = new Mod(); public static Dictionary<string, ModSetting> Settings = new Dictionary<string, ModSetting>(); private float _clearCacheHoldTime = 0f; private const string SimpleShading = "Advanced Structure Skins Warning!\nYou're currently using RUMBLE's Simple Visual Settings. Advanced Structure Skins may behave strangely."; public override void OnLateInitializeMelon() { ((MelonBase)this).OnLateInitializeMelon(); PersistentSettings.LoadSettings(); Skins.Init(); UIInit(); AddLocalizationKeys(); Log("Advanced Structure Skins Initialized!"); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) ((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName); if (!(sceneName != "Gym") && !PersistentSettings.data.shownGraphicsNotification) { QualityManager qualityManager = Managers.GetQualityManager(); if (qualityManager.Config.QualityLevel <= 0) { SlabManager slabManager = Managers.GetSlabManager(); Nullable<int> val = default(Nullable<int>); slabManager.SpawnNotificationSlab("ASS.Notifications.SimpleShading", ref val, (ControllerType)1, (Il2CppReferenceArray<Location>)null); PersistentSettings.data.shownGraphicsNotification = true; PersistentSettings.SaveSettings(); } } } public override void OnUpdate() { ((MelonBase)this).OnUpdate(); if (Input.GetKey((KeyCode)308) && Input.GetKeyDown((KeyCode)115)) { CustomShaders.LogCache(); } if (Input.GetKeyDown((KeyCode)286)) { foreach (Structure item in Object.FindObjectsOfType<Structure>()) { if (!item.isSceneStructure) { Skins.ApplySkinTo(item); } } } if (Input.GetKey((KeyCode)287)) { _clearCacheHoldTime += Time.deltaTime; if (_clearCacheHoldTime >= 3f) { _clearCacheHoldTime = -100f; CustomShaders.ClearCache(); Skins.ReloadTexturesFromFile(); } } if (Input.GetKeyUp((KeyCode)287)) { _clearCacheHoldTime = 0f; } } public void UIInit() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown AssUI.ModName = "Advanced Structure Skins"; AssUI.ModVersion = "1.1.0"; AssUI.SetFolder("AdvancedStructureSkins"); AssUI.AddDescription("Keybinds", "", "Press F5 to reload shaders on currently spawned structures. " + Environment.NewLine + "Press Left Alt + S to print cached structure skins data." + Environment.NewLine + "Press and Hold F6 for 3s to clear cached data.", new Tags()); AddSetting("GlobalSkinEnabled", "Use Global Skin", defaultValue: true, 0, "Toggles on/off the global skin, allowing you to either select one skin for all structures or one skin per structure."); AddSetting("GlobalSkinPath", "Global Skin Path", "default", $"The path to the shader used by all structures if Global Skin is enabled. {Environment.NewLine}'myShader' maps to 'RUMBLE/UserData/Skins/myShader.bundle'.{Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("DiscSkinPath", "Disc Skin Path", "default", $"The path to the shader used by disc. {Environment.NewLine}'Disc/myShader' maps to 'RUMBLE/UserData/Skins/Disc/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("PillarSkinPath", "Pillar Skin Path", "default", $"The path to the shader used by pillar. {Environment.NewLine}'Pillar/myShader' maps to 'RUMBLE/UserData/Skins/Pillar/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("BallSkinPath", "Ball Skin Path", "default", $"The path to the shader used by ball. {Environment.NewLine}'Ball/myShader' maps to 'RUMBLE/UserData/Skins/Ball/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("RockCubeSkinPath", "Cube Skin Path", "default", $"The path to the shader used by cube. {Environment.NewLine}'Cube/myShader' maps to 'RUMBLE/UserData/Skins/Cube/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("WallSkinPath", "Wall Skin Path", "default", $"The path to the shader used by wall. {Environment.NewLine}'Wall/myShader' maps to 'RUMBLE/UserData/Skins/Wall/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("SmallRockSkinPath", "SmallRock Skin Path", "default", $"The path to the shader used by the small rocks found in the gym. {Environment.NewLine}'SmallRock/myShader' maps to 'RUMBLE/UserData/Skins/SmallRock/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AddSetting("LargeRockSkinPath", "Boulder Skin Path", "default", $"The path to the shader used by boulders. {Environment.NewLine}'LargeRock/myShader' maps to 'RUMBLE/UserData/Skins/LargeRock/myShader.bundle'. {Environment.NewLine}Enter 'default' to select the structure's default shader.{Environment.NewLine}{Environment.NewLine}Don't forget to press Enter after typing your shader path to save the value.{Environment.NewLine}The text box should say 'Current Value: myShader' before you hit save."); AssUI.GetFromFile(); UI.instance.UI_Initialized += delegate { UI.instance.AddMod(AssUI); }; AssUI.ModSaved += SavePersistentModUISettings; if (PersistentSettings.data.lastLoadedVersion != AssUI.ModVersion) { PersistentSettings.data.lastLoadedVersion = AssUI.ModVersion; foreach (KeyValuePair<string, string> modSetting in PersistentSettings.data.GetModSettings()) { AssUI.ChangeValue(modSetting.Key, modSetting.Value); } AssUI.SaveModData("Overwritten by Advanced Structure Skins v1.1.0"); } SavePersistentModUISettings(); } public void AddSetting(string dictionaryKey, string name, string defaultValue, string description) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Settings.Add(dictionaryKey, (ModSetting)(object)AssUI.AddToList(name, defaultValue, description, new Tags())); } public void AddSetting(string dictionaryKey, string name, bool defaultValue, int linkGroup, string description) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Settings.Add(dictionaryKey, (ModSetting)(object)AssUI.AddToList(name, defaultValue, linkGroup, description, new Tags())); } public void SavePersistentModUISettings() { PersistentSettings.data.ApplyFromModUISettings(Settings); PersistentSettings.SaveSettings(); } public void AddLocalizationKeys() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown LanguageManager.instance.RawTextDatabase.Add("ASS.Notifications.SimpleShading", "Advanced Structure Skins Warning!\nYou're currently using RUMBLE's Simple Visual Settings. Advanced Structure Skins may behave strangely."); LocalizedObject val = new LocalizedObject(LanguageManager.instance.LanguageDatabase["Rank.Mountain.Name"]); val.textValue = "Advanced Structure Skins Warning!\nYou're currently using RUMBLE's Simple Visual Settings. Advanced Structure Skins may behave strangely."; LanguageManager.instance.LanguageDatabase.Add("ASS.Notifications.SimpleShading", val); } public static void Log(object msg) { MelonLogger.Msg(msg); } public static void Warn(object msg) { MelonLogger.Warning(msg); } public static void Error(object msg) { MelonLogger.Error(msg); } } public static class CustomShaders { private static readonly Dictionary<string, string> CachedFilePaths = new Dictionary<string, string>(); private static readonly Dictionary<string, Shader> CachedShaders = new Dictionary<string, Shader>(); private static readonly Dictionary<string, Material> CachedMaterials = new Dictionary<string, Material>(); private static readonly Dictionary<string, List<MaterialPropertyOverride>> CachedOverrides = new Dictionary<string, List<MaterialPropertyOverride>>(); private static readonly Dictionary<string, AssetBundle> CachedBundles = new Dictionary<string, AssetBundle>(); public static Shader GetShader(string bundleName) { if (CachedShaders.TryGetValue(bundleName, out var value) && (Object)(object)value != (Object)null) { return value; } if (!CachedBundles.TryGetValue(bundleName, out var value2) || (Object)(object)value2 == (Object)null) { string text = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", bundleName + ".bundle"); if (!File.Exists(text)) { text = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", bundleName); if (!File.Exists(text)) { AdvancedStructureSkins.Warn("Shader bundle not found at path: " + text); return null; } } value2 = Calls.LoadAssetBundleFromFile(text); if ((Object)(object)value2 == (Object)null) { AdvancedStructureSkins.Warn("Failed to load AssetBundle from: " + text); return null; } CachedBundles[bundleName] = value2; CachedFilePaths[bundleName] = text; } Shader val = value2.LoadAsset<Shader>("shader"); if ((Object)(object)val == (Object)null) { AdvancedStructureSkins.Warn("Shader asset not found in bundle: " + bundleName); return null; } CachedShaders[bundleName] = val; return val; } public static Material GetMaterial(string bundleName) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown if (CachedMaterials.TryGetValue(bundleName, out var value) && (Object)(object)value != (Object)null) { return new Material(value); } if (!CachedBundles.TryGetValue(bundleName, out var value2) || (Object)(object)value2 == (Object)null) { string text = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", bundleName + ".bundle"); if (!File.Exists(text)) { text = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", bundleName); if (!File.Exists(text)) { AdvancedStructureSkins.Warn("Shader bundle not found at path: " + text); return null; } } value2 = Calls.LoadAssetBundleFromFile(text); if ((Object)(object)value2 == (Object)null) { AdvancedStructureSkins.Warn("Failed to load AssetBundle from: " + text); return null; } CachedBundles[bundleName] = value2; CachedFilePaths[bundleName] = text; } Material val = value2.LoadAsset<Material>("material"); if ((Object)(object)val == (Object)null) { AdvancedStructureSkins.Warn("Material asset not found in bundle: " + bundleName); return null; } CachedMaterials[bundleName] = val; return new Material(val); } public static List<MaterialPropertyOverride> GetOverrides(string bundleName) { if (CachedOverrides.TryGetValue(bundleName, out var value) && value != null) { return value; } if (!CachedBundles.TryGetValue(bundleName, out var value2) || (Object)(object)value2 == (Object)null) { string text = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", bundleName + ".bundle"); if (!File.Exists(text)) { text = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", bundleName); if (!File.Exists(text)) { AdvancedStructureSkins.Warn("Shader bundle not found at path: " + text); return null; } } value2 = Calls.LoadAssetBundleFromFile(text); if ((Object)(object)value2 == (Object)null) { AdvancedStructureSkins.Warn("Failed to load AssetBundle from: " + text); return null; } CachedBundles[bundleName] = value2; CachedFilePaths[bundleName] = text; } TextAsset val = value2.LoadAsset<TextAsset>("overrides"); if ((Object)(object)val == (Object)null) { AdvancedStructureSkins.Warn("Failed to load overrides from: " + bundleName); } List<MaterialPropertyOverride> overrides = ReadDataFile(val.text).overrides; if (overrides == null) { AdvancedStructureSkins.Warn("Material asset not found in bundle: " + bundleName); return null; } CachedOverrides[bundleName] = overrides; return overrides; } public static MaterialPropertyOverrides ReadDataFile(string data) { string[] array = data.Split("|"); MaterialPropertyOverrides materialPropertyOverrides = new MaterialPropertyOverrides(); int num = 0; while (num < array.Length - 1) { MaterialPropertyOverride materialPropertyOverride = new MaterialPropertyOverride(); materialPropertyOverride.propertyName = array[num]; num++; materialPropertyOverride.propertyType = int.Parse(array[num]); num++; switch (materialPropertyOverride.propertyType) { case 0: materialPropertyOverride.colorValue.r = float.Parse(array[num]); materialPropertyOverride.colorValue.g = float.Parse(array[num + 1]); materialPropertyOverride.colorValue.b = float.Parse(array[num + 2]); materialPropertyOverride.colorValue.a = float.Parse(array[num + 3]); num += 4; break; case 1: materialPropertyOverride.floatValue = float.Parse(array[num]); num++; break; case 2: materialPropertyOverride.floatValue = float.Parse(array[num]); num++; break; case 3: materialPropertyOverride.intValue = int.Parse(array[num]); num++; break; case 4: materialPropertyOverride.vectorValue.x = float.Parse(array[num]); materialPropertyOverride.vectorValue.y = float.Parse(array[num + 1]); materialPropertyOverride.vectorValue.z = float.Parse(array[num + 2]); materialPropertyOverride.vectorValue.w = float.Parse(array[num + 3]); num += 4; break; } int num2 = int.Parse(array[num]); num++; for (int i = 0; i < num2; i++) { materialPropertyOverride.targetStructures.Add(int.Parse(array[num])); num++; } materialPropertyOverrides.overrides.Add(materialPropertyOverride); } return materialPropertyOverrides; } public static void AddToCache(string bundleName, Shader shader = null, Material material = null) { if ((Object)(object)shader == (Object)null && (Object)(object)material == (Object)null) { AdvancedStructureSkins.Warn("Please specify a shader or material to add to cache."); return; } if (IsInShaderCache(bundleName)) { AdvancedStructureSkins.Warn("AddToCache Shader already exists in cache!"); } else if ((Object)(object)shader != (Object)null) { CachedShaders[bundleName] = shader; } if (IsInMaterialCache(bundleName)) { AdvancedStructureSkins.Warn("AddToCache Material already exists in cache!"); } else if ((Object)(object)material != (Object)null) { CachedMaterials[bundleName] = material; } } public static bool IsInAnyCache(string bundleName) { Shader value; bool flag = CachedShaders.TryGetValue(bundleName, out value); Material value2; bool flag2 = CachedMaterials.TryGetValue(bundleName, out value2); return flag || flag2; } public static bool IsInShaderCache(string bundleName) { Shader value; return CachedShaders.TryGetValue(bundleName, out value); } public static bool IsInMaterialCache(string bundleName) { Material value; return CachedMaterials.TryGetValue(bundleName, out value); } public static void ClearCache(bool keepDefaults = true) { Dictionary<string, Shader> dictionary = new Dictionary<string, Shader>(); Dictionary<string, Material> dictionary2 = new Dictionary<string, Material>(); foreach (string key in CachedShaders.Keys) { if (key.Contains("default_")) { dictionary.Add(key, CachedShaders[key]); } } foreach (string key2 in CachedMaterials.Keys) { if (key2.Contains("default_")) { dictionary2.Add(key2, CachedMaterials[key2]); } } CachedFilePaths.Clear(); CachedShaders.Clear(); CachedMaterials.Clear(); CachedOverrides.Clear(); CachedBundles.Clear(); if (!keepDefaults) { return; } foreach (string key3 in dictionary.Keys) { CachedShaders.Add(key3, dictionary[key3]); } foreach (string key4 in dictionary2.Keys) { CachedMaterials.Add(key4, dictionary2[key4]); } } public static void LogCache() { string text = "Cached Bundles"; foreach (string key in CachedFilePaths.Keys) { text = text + "\nFile Path: " + CachedFilePaths[key]; text = text + "\nBundle name: " + key; text += "\nBundle Contents: "; foreach (string item in (Il2CppArrayBase<string>)(object)CachedBundles[key].GetAllAssetNames()) { text += "\n"; text += item; } text += "\n\nLoaded Shader: "; text += ((Object)CachedShaders[key]).name; } AdvancedStructureSkins.Log(text); } } public class SkinHandler { [HarmonyPatch(typeof(Structure), "OnFetchFromPool")] public static class StructureSpawnPatch { private static void Postfix(ref Structure __instance) { try { if (!__instance.isSceneStructure) { Skins.ApplySkinTo(__instance); } } catch (Exception msg) { AdvancedStructureSkins.Log(msg); } } } private static readonly string[] Types = new string[7] { "Disc", "Pillar", "Ball", "RockCube", "Wall", "SmallRock", "LargeRock" }; private readonly string[] _texProperties = new string[4] { "Texture2D_2058E65A", "Texture2D_3812B1EC", "Texture2D_8F187FEF", "_Grounded_noise" }; private readonly string[] _texTypes = new string[4] { "Normal", "Main", "Mat", "Grounded" }; private readonly string[] _texPaths = new string[7] { "Skins/Disc/", "Skins/Pillar/", "Skins/Ball/", "Skins/Cube/", "Skins/Wall/", "Skins/SmallRock/", "Skins/LargeRock/" }; private List<SkinTextures>[] _textures = new List<SkinTextures>[7]; private readonly Random _rand = new Random(); public static SkinHandler Skins; public void Init() { Skins = this; ReloadTexturesFromFile(); AdvancedStructureSkins.Log("Structure Shaders passed loading"); } public void ReloadTexturesFromFile() { _textures = new List<SkinTextures>[7]; for (int i = 0; i < _textures.Length; i++) { _textures[i] = new List<SkinTextures>(); string text = Path.Combine(MelonEnvironment.UserDataDirectory, _texPaths[i]); if (!Directory.Exists(text)) { continue; } string[] directories = Directory.GetDirectories(text); if ((directories.Length == 0) | IsMultiTextureSingleSkin(directories)) { if (!Path.GetFileName(text).StartsWith("_")) { _textures[i].Add(new SkinTextures(text)); } continue; } string[] array = directories; foreach (string text2 in array) { if (!Path.GetFileName(text2).StartsWith("_")) { _textures[i].Add(new SkinTextures(text2)); } } } } private bool IsMultiTextureSingleSkin(string[] paths) { foreach (string path in paths) { if (!_texTypes.Contains<string>(Path.GetFileName(path), StringComparer.OrdinalIgnoreCase)) { return false; } } return true; } public void ApplySkinTo(Structure structure) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown if (!Types.Contains(((Object)((Component)structure).gameObject).name)) { return; } MeshRenderer componentInChildren = ((Component)structure).GetComponentInChildren<MeshRenderer>(); int num = Array.IndexOf(Types, ((Object)((Component)structure).gameObject).name); if (!Types.Contains(((Object)((Component)structure).gameObject).name)) { AdvancedStructureSkins.Warn("Found unsupported structure with name '" + ((Object)((Component)structure).gameObject).name + "'"); return; } if ((Object)(object)componentInChildren == (Object)null) { AdvancedStructureSkins.Error("Could not find MeshRenderer on structure!"); return; } if (!CustomShaders.IsInAnyCache("default_" + Types[num])) { Material val = new Material(((Renderer)componentInChildren).material); ((Object)val).hideFlags = (HideFlags)32; val.SetTexture("Texture2D_8F187FEF", (Texture)(object)Texture2D.blackTexture); CustomShaders.AddToCache("default_" + Types[num], val.shader, val); } bool flag = (bool)AdvancedStructureSkins.Settings["GlobalSkinEnabled"].SavedValue; string text = (string)AdvancedStructureSkins.Settings["GlobalSkinPath"].SavedValue; string text2 = (string)AdvancedStructureSkins.Settings[Types[num] + "SkinPath"].SavedValue; string text3 = (flag ? text : text2); if (text3 == "default") { text3 = "default_" + Types[num]; } text3 = text3.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (string.Equals(Path.GetFileName(text3), "random", StringComparison.OrdinalIgnoreCase)) { string path = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins", text3); path = Path.GetDirectoryName(path); string[] files = Directory.GetFiles(path, "*.bundle"); text3 = files[_rand.Next(files.Length)]; string relativeTo = Path.Combine(MelonEnvironment.UserDataDirectory, "Skins"); text3 = Path.GetRelativePath(relativeTo, text3); } ApplyTexturesTo(componentInChildren, num); ApplyShaderTo(componentInChildren, num, text3); ApplyOverridesTo(componentInChildren, num, text3); } private void ApplyTexturesTo(MeshRenderer mr, int type) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown Material material = CustomShaders.GetMaterial("default_" + Types[type]); MaterialPropertyBlock val = new MaterialPropertyBlock(); ((Renderer)mr).GetPropertyBlock(val); int index = _rand.Next(_textures[type].Count); for (int i = 0; i < _texProperties.Length; i++) { if (_textures[type].Count <= 0 || !_textures[type][index].HasTextureFor(i)) { ApplyDefaultTexturesTo(val, material, i); continue; } Texture2D texture = _textures[type][index].GetTexture(i); val.SetTexture(_texProperties[i], (Texture)(object)texture); } ((Renderer)mr).SetPropertyBlock(val); } private void ApplyDefaultTexturesTo(MaterialPropertyBlock properties, Material defaultMat, int textureIndex) { properties.SetTexture(_texProperties[textureIndex], (Texture)(object)Texture2D.blackTexture); Texture texture = defaultMat.GetTexture(_texProperties[textureIndex]); if (!((Object)(object)texture == (Object)null)) { properties.SetTexture(_texProperties[textureIndex], texture); } } private void ApplyShaderTo(MeshRenderer mr, int type, string path) { Material material = CustomShaders.GetMaterial(path); if (!((Object)(object)material == (Object)null)) { material.CopyMatchingPropertiesFromMaterial(((Renderer)mr).material); ((Renderer)mr).material = material; } } private void ApplyOverridesTo(MeshRenderer mr, int type, string path) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected I4, but got Unknown //IL_009b: 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) if (path.Contains("default_")) { return; } List<MaterialPropertyOverride> overrides = CustomShaders.GetOverrides(path); if (overrides == null) { return; } foreach (MaterialPropertyOverride item in overrides) { if (item.targetStructures.Contains(type)) { ShaderPropertyType val = (ShaderPropertyType)item.propertyType; ShaderPropertyType val2 = val; switch ((int)val2) { case 0: ((Renderer)mr).material.SetColor(item.propertyName, item.colorValue); break; case 1: ((Renderer)mr).material.SetVector(item.propertyName, item.vectorValue); break; case 2: ((Renderer)mr).material.SetFloat(item.propertyName, item.floatValue); break; case 3: ((Renderer)mr).material.SetFloat(item.propertyName, item.floatValue); break; case 5: ((Renderer)mr).material.SetInt(item.propertyName, item.intValue); break; } } } } } [Serializable] public class MaterialPropertyOverrides { public List<MaterialPropertyOverride> overrides = new List<MaterialPropertyOverride>(); } [Serializable] public class MaterialPropertyOverride { public string propertyName; public int propertyType; public Color colorValue; public float floatValue; public int intValue; public Vector4 vectorValue; public List<int> targetStructures = new List<int>(); } public enum StructureType { Disc, Pillar, Ball, Cube, Wall, SmallRock, LargeRock } public static class PersistentSettings { public static SettingsDataV1 data; public static readonly string path = Path.Combine(MelonEnvironment.UserDataDirectory, "AdvancedStructureSkins", "Persistence.txt"); public static void LoadSettings() { Dictionary<string, string> dictionary = LoadSettingsDictFromFile(); int num = int.Parse(dictionary["version"]); int num2 = num; if (num2 == 1) { data = LoadSettingsV1(dictionary); } else { AdvancedStructureSkins.Warn("Persistent Settings failed to load or does not exist."); } } public static void SaveSettings() { SaveSettingsV1(); } public static Dictionary<string, string> LoadSettingsDictFromFile() { if (!Directory.Exists(Path.GetDirectoryName(path))) { Directory.CreateDirectory(Path.GetDirectoryName(path)); } if (!File.Exists(path)) { return new Dictionary<string, string> { ["version"] = 1.ToString() }; } string[] array = File.ReadAllText(path).Split(Environment.NewLine); Array.Resize(ref array, array.Length - 1); Dictionary<string, string> dictionary = new Dictionary<string, string>(); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(": "); dictionary.Add(array3[0], array3[1]); } return dictionary; } public static SettingsDataV1 LoadSettingsV1(Dictionary<string, string> settings) { SettingsDataV1 result = new SettingsDataV1(); Type typeFromHandle = typeof(SettingsDataV1); FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { if (settings.TryGetValue(fieldInfo.Name, out var value)) { object value2 = Convert.ChangeType(value, fieldInfo.FieldType); fieldInfo.SetValueDirect(__makeref(result), value2); } } return result; } public static void SaveSettingsV1() { string text = ""; FieldInfo[] fields = typeof(SettingsDataV1).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { text += $"{fieldInfo.Name}: {fieldInfo.GetValue(data)}{Environment.NewLine}"; } File.WriteAllText(path, text); } } public struct SettingsDataV1 { public int version; public bool shownGraphicsNotification; public string lastLoadedVersion; public bool useGlobalSkin; public string globalSkinPath; public string discSkinPath; public string pillarSkinPath; public string ballSkinPath; public string cubeSkinPath; public string wallSkinPath; public string smallRockSkinPath; public string boulderSkinPath; public SettingsDataV1() { version = 1; shownGraphicsNotification = false; lastLoadedVersion = "1.1.0"; useGlobalSkin = true; globalSkinPath = "default"; discSkinPath = "default"; pillarSkinPath = "default"; ballSkinPath = "default"; cubeSkinPath = "default"; wallSkinPath = "default"; smallRockSkinPath = "default"; boulderSkinPath = "default"; } public void ApplyFromModUISettings(Dictionary<string, ModSetting> settings) { useGlobalSkin = (bool)settings["GlobalSkinEnabled"].SavedValue; globalSkinPath = (string)settings["GlobalSkinPath"].SavedValue; discSkinPath = (string)settings["DiscSkinPath"].SavedValue; pillarSkinPath = (string)settings["PillarSkinPath"].SavedValue; ballSkinPath = (string)settings["BallSkinPath"].SavedValue; cubeSkinPath = (string)settings["RockCubeSkinPath"].SavedValue; wallSkinPath = (string)settings["WallSkinPath"].SavedValue; smallRockSkinPath = (string)settings["SmallRockSkinPath"].SavedValue; boulderSkinPath = (string)settings["LargeRockSkinPath"].SavedValue; } public Dictionary<string, string> GetModSettings() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); dictionary.Add("Use Global Skin", useGlobalSkin.ToString()); dictionary.Add("Global Skin Path", globalSkinPath); dictionary.Add("Disc Skin Path", discSkinPath); dictionary.Add("Pillar Skin Path", pillarSkinPath); dictionary.Add("Ball Skin Path", ballSkinPath); dictionary.Add("Cube Skin Path", cubeSkinPath); dictionary.Add("Wall Skin Path", wallSkinPath); dictionary.Add("SmallRock Skin Path", smallRockSkinPath); dictionary.Add("Boulder Skin Path", boulderSkinPath); return dictionary; } } public class SkinTextures { public string Name; private Texture2D[][] _textures = new Texture2D[4][]; private static Random _random = new Random(); private readonly string[] _texTypes = new string[4] { "Normal", "Main", "Mat", "Grounded" }; public SkinTextures(string folderPath) { Name = Path.GetFileName(folderPath); _textures = LoadTexturesFromPath(folderPath); } private Texture2D[][] LoadTexturesFromPath(string folderPath) { Texture2D[][] array = new Texture2D[4][]; for (int i = 0; i < array.Length; i++) { string path = Path.Combine(folderPath, _texTypes[i] + ".png"); if (File.Exists(path)) { array[i] = (Texture2D[])(object)new Texture2D[1]; array[i][0] = LoadTexture(path, i); continue; } string path2 = Path.Combine(folderPath, _texTypes[i]); if (Directory.Exists(path2)) { string[] files = Directory.GetFiles(path2); array[i] = (Texture2D[])(object)new Texture2D[files.Length]; for (int j = 0; j < files.Length; j++) { array[i][j] = LoadTexture(files[j], i); } } } return array; } private Texture2D LoadTexture(string path, int textureType) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_008e: 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) if (!File.Exists(path)) { return null; } Texture2D val = new Texture2D(2, 2); byte[] array = File.ReadAllBytes(path); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)); ((Object)val).hideFlags = (HideFlags)61; if (textureType == 0) { Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, val.format, true, true); Color[] array2 = Il2CppArrayBase<Color>.op_Implicit((Il2CppArrayBase<Color>)(object)val.GetPixels()); Color[] array3 = (Color[])(object)new Color[array2.Length]; for (int i = 0; i < array2.Length; i++) { array3[i] = ((Color)(ref array2[i])).linear; } val2.SetPixels(Il2CppStructArray<Color>.op_Implicit(array3)); ((Object)val2).hideFlags = (HideFlags)61; val2.Apply(); if ((Object)(object)val2 != (Object)null) { return val2; } } return val; } public Texture2D GetTexture(int textureType) { if (_textures[textureType] == null) { AdvancedStructureSkins.Error("Requested SkinTexture type is null."); return null; } if (_textures[textureType].Length == 0) { AdvancedStructureSkins.Error("Requested SkinTexture type is empty."); return null; } int num = _random.Next(_textures[textureType].Length); if ((Object)(object)_textures[textureType][num] == (Object)null) { AdvancedStructureSkins.Error("Requested SkinTexture image is null"); return null; } return _textures[textureType][num]; } public bool HasTextureFor(int textureType) { if (_textures[textureType] == null) { return false; } return _textures[textureType].Length != 0; } }