Decompiled source of AdvancedStructureSkins v1.0.6

Mods/AdvancedStructureSkins.dll

Decompiled 2 months ago
using 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;
	}
}