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.0.6
Mods/AdvancedStructureSkins.dll
Decompiled 2 months 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.MoveSystem; 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.0.6", "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.0.6"; 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; public override void OnLateInitializeMelon() { ((MelonBase)this).OnLateInitializeMelon(); Skins.Init(); UIInit(); Log("Advanced Structure Skins Initialized!"); } 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.0.6"; 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); }; } 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 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 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); 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]); } } } return array; } private Texture2D LoadTexture(string path) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown 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; return val; } public Texture2D GetTexture(int textureType) { if (_textures[textureType] == null) { return null; } if (_textures[textureType].Length == 0) { return null; } int num = _random.Next(_textures[textureType].Length); if ((Object)(object)_textures[textureType][num] == (Object)null) { return null; } return _textures[textureType][num]; } public bool HasTextureFor(int textureType) { if (_textures[textureType] == null) { return false; } return _textures[textureType].Length != 0; } }