Decompiled source of Better Plant Textures v0.1.0

CustomTextures.dll

Decompiled 2 days 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.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class TextureScale
{
	public class ThreadData
	{
		public int start;

		public int end;

		public ThreadData(int s, int e)
		{
			start = s;
			end = e;
		}
	}

	private static Color[] texColors;

	private static Color[] newColors;

	private static int w;

	private static float ratioX;

	private static float ratioY;

	private static int w2;

	private static int finishCount;

	private static Mutex mutex;

	public static void Point(Texture2D tex, int newWidth, int newHeight)
	{
		ThreadedScale(tex, newWidth, newHeight, useBilinear: false);
	}

	public static void Bilinear(Texture2D tex, int newWidth, int newHeight)
	{
		ThreadedScale(tex, newWidth, newHeight, useBilinear: true);
	}

	private static void ThreadedScale(Texture2D tex, int newWidth, int newHeight, bool useBilinear)
	{
		texColors = tex.GetPixels();
		newColors = (Color[])(object)new Color[newWidth * newHeight];
		if (useBilinear)
		{
			ratioX = 1f / ((float)newWidth / (float)(((Texture)tex).width - 1));
			ratioY = 1f / ((float)newHeight / (float)(((Texture)tex).height - 1));
		}
		else
		{
			ratioX = (float)((Texture)tex).width / (float)newWidth;
			ratioY = (float)((Texture)tex).height / (float)newHeight;
		}
		w = ((Texture)tex).width;
		w2 = newWidth;
		int num = Mathf.Min(SystemInfo.processorCount, newHeight);
		int num2 = newHeight / num;
		finishCount = 0;
		if (mutex == null)
		{
			mutex = new Mutex(initiallyOwned: false);
		}
		if (num > 1)
		{
			int num3 = 0;
			ThreadData parameter;
			for (num3 = 0; num3 < num - 1; num3++)
			{
				parameter = new ThreadData(num2 * num3, num2 * (num3 + 1));
				ParameterizedThreadStart start = (useBilinear ? new ParameterizedThreadStart(BilinearScale) : new ParameterizedThreadStart(PointScale));
				Thread thread = new Thread(start);
				thread.Start(parameter);
			}
			parameter = new ThreadData(num2 * num3, newHeight);
			if (useBilinear)
			{
				BilinearScale(parameter);
			}
			else
			{
				PointScale(parameter);
			}
			while (finishCount < num)
			{
				Thread.Sleep(1);
			}
		}
		else
		{
			ThreadData obj = new ThreadData(0, newHeight);
			if (useBilinear)
			{
				BilinearScale(obj);
			}
			else
			{
				PointScale(obj);
			}
		}
		tex.Resize(newWidth, newHeight);
		tex.SetPixels(newColors);
		tex.Apply();
		texColors = null;
		newColors = null;
	}

	public static void BilinearScale(object obj)
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00ca: 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)
		ThreadData threadData = (ThreadData)obj;
		for (int i = threadData.start; i < threadData.end; i++)
		{
			int num = (int)Mathf.Floor((float)i * ratioY);
			int num2 = num * w;
			int num3 = (num + 1) * w;
			int num4 = i * w2;
			for (int j = 0; j < w2; j++)
			{
				int num5 = (int)Mathf.Floor((float)j * ratioX);
				float value = (float)j * ratioX - (float)num5;
				newColors[num4 + j] = ColorLerpUnclamped(ColorLerpUnclamped(texColors[num2 + num5], texColors[num2 + num5 + 1], value), ColorLerpUnclamped(texColors[num3 + num5], texColors[num3 + num5 + 1], value), (float)i * ratioY - (float)num);
			}
		}
		mutex.WaitOne();
		finishCount++;
		mutex.ReleaseMutex();
	}

	public static void PointScale(object obj)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		ThreadData threadData = (ThreadData)obj;
		for (int i = threadData.start; i < threadData.end; i++)
		{
			int num = (int)(ratioY * (float)i) * w;
			int num2 = i * w2;
			for (int j = 0; j < w2; j++)
			{
				newColors[num2 + j] = texColors[(int)((float)num + ratioX * (float)j)];
			}
		}
		mutex.WaitOne();
		finishCount++;
		mutex.ReleaseMutex();
	}

	private static Color ColorLerpUnclamped(Color c1, Color c2, float value)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_0023: 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_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		return new Color(c1.r + (c2.r - c1.r) * value, c1.g + (c2.g - c1.g) * value, c1.b + (c2.b - c1.b) * value, c1.a + (c2.a - c1.a) * value);
	}
}
namespace CustomTextures
{
	[BepInPlugin("cjayride.CustomTextures", "Custom Textures", "3.5.3")]
	public class BepInExPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Terminal), "InputText")]
		private static class InputText_Patch
		{
			private static bool Prefix(Terminal __instance)
			{
				if (!modEnabled.Value)
				{
					return true;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "SetupObjectDB")]
		private static class FejdStartup_SetupObjectDB_Patch
		{
			private static void Postfix()
			{
				if (modEnabled.Value)
				{
					stopwatch.Restart();
					outputDump.Clear();
					Dbgl("SetupObjectDB postfix");
					ReplaceObjectDBTextures();
					LogStopwatch("SetupObjectDB");
				}
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "Awake")]
		private static class ZoneSystem_Awake_Patch
		{
			private static void Prefix(ZoneSystem __instance)
			{
				outputDump.Clear();
				ReplaceZoneSystemTextures(__instance);
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetScene_Awake_Patch
		{
			private static void Postfix(ZNetScene __instance, Dictionary<int, GameObject> ___m_namedPrefabs)
			{
				Dbgl("ZNetScene awake");
				stopwatch.Restart();
				ReplaceZNetSceneTextures();
				LogStopwatch("ZNetScene");
				ReplaceEnvironmentTextures();
			}
		}

		private static class Player_Start_Patch
		{
			private static void Prefix(Player __instance)
			{
				if (modEnabled.Value && !((Object)(object)Player.m_localPlayer != (Object)(object)__instance))
				{
					Dbgl("Player Awake");
					ReloadTextures(replaceLocationTextures.Value);
				}
			}
		}

		[HarmonyPatch(typeof(ClutterSystem), "Awake")]
		private static class ClutterSystem_Awake_Patch
		{
			private static void Postfix(ClutterSystem __instance)
			{
				Dbgl("Clutter system awake");
				stopwatch.Restart();
				logDump.Clear();
				Dbgl($"Checking {__instance.m_clutter.Count} clutters");
				foreach (Clutter item in __instance.m_clutter)
				{
					if (!((Object)(object)item?.m_prefab == (Object)null))
					{
						ReplaceOneGameObjectTextures(item.m_prefab, ((Object)item.m_prefab).name, "object");
					}
				}
				if (logDump.Any())
				{
					Dbgl("\n" + string.Join("\n", logDump));
				}
				LogStopwatch("Clutter System");
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "Start")]
		private static class ZoneSystem_Start_Patch
		{
			private static void Prefix()
			{
				if (replaceLocationTextures.Value)
				{
					Dbgl("Starting ZoneSystem Location prefab replacement");
					stopwatch.Restart();
					ReplaceLocationTextures();
					LogStopwatch("ZoneSystem Locations");
				}
			}
		}

		[HarmonyPatch(typeof(VisEquipment), "Awake")]
		private static class VisEquipment_Awake_Patch
		{
			private static void Postfix(VisEquipment __instance)
			{
				if (__instance.m_models == null)
				{
					return;
				}
				for (int i = 0; i < __instance.m_models.Length; i++)
				{
					if (__instance.m_models[i] == null || (Object)(object)__instance.m_models[i].m_baseMaterial == (Object)null)
					{
						continue;
					}
					string[] texturePropertyNames = __instance.m_models[i].m_baseMaterial.GetTexturePropertyNames();
					foreach (string text in texturePropertyNames)
					{
						if (ShouldLoadCustomTexture($"player_model_{i}{text}"))
						{
							__instance.m_models[i].m_baseMaterial.SetTexture(text, (Texture)(object)LoadTexture($"player_model_{i}{text}", __instance.m_models[i].m_baseMaterial.GetTexture(text), isBump: false));
							Dbgl($"set player_model_{i}_texture custom texture.");
						}
						else if (text == "_MainTex" && ShouldLoadCustomTexture($"player_model_{i}_texture"))
						{
							__instance.m_models[i].m_baseMaterial.SetTexture(text, (Texture)(object)LoadTexture($"player_model_{i}_texture", __instance.m_models[i].m_baseMaterial.GetTexture(text), isBump: false));
						}
						else if (text == "_SkinBumpMap" && ShouldLoadCustomTexture($"player_model_{i}_bump"))
						{
							__instance.m_models[i].m_baseMaterial.SetTexture(text, (Texture)(object)LoadTexture($"player_model_{i}_bump", __instance.m_models[i].m_baseMaterial.GetTexture(text), isBump: true));
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")]
		private static class Humanoid_SetupVisEquipment_Patch
		{
			private static void Postfix(Humanoid __instance)
			{
				if (!modEnabled.Value)
				{
					return;
				}
				try
				{
					SetupVisEquipment(__instance);
				}
				catch (Exception arg)
				{
					Dbgl($"SetupVisEquipment patch error: {arg}");
				}
			}
		}

		public static ConfigEntry<bool> modEnabled;

		public static ConfigEntry<bool> isDebug;

		public static ConfigEntry<bool> dumpSceneTextures;

		public static ConfigEntry<bool> replaceLocationTextures;

		public static ConfigEntry<bool> reloadLocationTextures;

		public static ConfigEntry<string> hotKey;

		private static BepInExPlugin context;

		private static Stopwatch stopwatch = new Stopwatch();

		public static Dictionary<string, string> customTextures = new Dictionary<string, string>();

		public static Dictionary<string, DateTime> fileWriteTimes = new Dictionary<string, DateTime>();

		public static List<string> texturesToLoad = new List<string>();

		public static List<string> layersToLoad = new List<string>();

		public static Dictionary<string, Texture2D> cachedTextures = new Dictionary<string, Texture2D>();

		public static List<string> outputDump = new List<string>();

		public static List<string> logDump = new List<string>();

		public static List<int> reloadedObjects = new List<int>();

		public static void Dbgl(string str = "", bool pref = true)
		{
			if (isDebug.Value)
			{
				Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
			}
		}

		private void Awake()
		{
			context = this;
			modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
			isDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IsDebug", false, "Enable debug");
			hotKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HotKey", "page down", "Key to reload textures");
			replaceLocationTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceLocationTextures", true, "Replace textures for special locations (can take a long time)");
			reloadLocationTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReloadLocationTextures", false, "Reload textures for special locations on manual reload (can take a long time)");
			dumpSceneTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DumpSceneTextures", false, "Dump scene textures to BepInEx/plugins/CustomTextures/scene_dump.txt");
			if (modEnabled.Value)
			{
				LoadCustomTextures();
				Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			}
		}

		private void Update()
		{
			if ((Object)(object)ZNetScene.instance != (Object)null && CheckKeyDown(hotKey.Value))
			{
				Dbgl("Pressed reload key.");
				ReloadTextures(reloadLocationTextures.Value && replaceLocationTextures.Value);
			}
		}

		private static bool CheckKeyDown(string value)
		{
			try
			{
				return Input.GetKeyDown(value.ToLower());
			}
			catch
			{
				return false;
			}
		}

		private static void LogStopwatch(string str)
		{
			stopwatch.Stop();
			TimeSpan elapsed = stopwatch.Elapsed;
			string text = $"{elapsed.Hours:00}:{elapsed.Minutes:00}:{elapsed.Seconds:00}.{elapsed.Milliseconds / 10:00}";
			Dbgl(str + " RunTime " + text);
		}

		private static bool HasCustomTexture(string id)
		{
			return customTextures.ContainsKey(id) || customTextures.Keys.ToList().Exists((string p) => p.StartsWith(id));
		}

		private static bool ShouldLoadCustomTexture(string id)
		{
			return texturesToLoad.Contains(id) || layersToLoad.Contains(id);
		}

		private static void ReplaceObjectDBTextures()
		{
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			logDump.Clear();
			ObjectDB instance = ObjectDB.instance;
			Texture2D vanilla = null;
			foreach (GameObject item in instance.m_items)
			{
				if (item != null && item.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons.Length > 0)
				{
					vanilla = item.GetComponent<ItemDrop>().m_itemData.m_shared.m_icons[0].texture;
					Dbgl("got atlas at item: " + ((Object)item).name);
					break;
				}
			}
			Texture2D val = LoadTexture("atlas_item_icons", (Texture)(object)vanilla, isBump: false, point: true, needCustom: true);
			Dbgl($"Replacing textures for {instance.m_items.Count} objects");
			foreach (GameObject item2 in instance.m_items)
			{
				ItemDrop component = item2.GetComponent<ItemDrop>();
				ReplaceOneGameObjectTextures(item2, ((Object)item2).name, "object");
				if ((Object)(object)val != (Object)null)
				{
					for (int i = 0; i < component.m_itemData.m_shared.m_icons.Length; i++)
					{
						Sprite val2 = component.m_itemData.m_shared.m_icons[i];
						float num = (float)((Texture)val).width / (float)((Texture)val2.texture).width;
						float num2 = (float)((Texture)val).height / (float)((Texture)val2.texture).height;
						float num3 = (num + num2) / 2f;
						Rect textureRect = val2.textureRect;
						float num4 = ((Rect)(ref textureRect)).x * num;
						textureRect = val2.textureRect;
						float num5 = ((Rect)(ref textureRect)).y * num2;
						textureRect = val2.textureRect;
						float num6 = ((Rect)(ref textureRect)).width * num;
						textureRect = val2.textureRect;
						val2 = Sprite.Create(val, new Rect(num4, num5, num6, ((Rect)(ref textureRect)).height * num2), Vector2.zero, val2.pixelsPerUnit * num3);
						component.m_itemData.m_shared.m_icons[i] = val2;
					}
				}
			}
			Traverse.Create((object)instance).Method("UpdateRegisters", Array.Empty<object>()).GetValue();
			if (logDump.Any())
			{
				Dbgl("\n" + string.Join("\n", logDump));
			}
		}

		private static void ReplaceZNetSceneTextures()
		{
			logDump.Clear();
			List<GameObject> list = new List<GameObject>();
			if ((Object)(object)ClutterSystem.instance != (Object)null)
			{
				foreach (Clutter item in ClutterSystem.instance.m_clutter)
				{
					if ((Object)(object)item?.m_prefab != (Object)null && !list.Contains(item.m_prefab))
					{
						list.Add(item.m_prefab);
					}
				}
			}
			Dictionary<int, GameObject>.ValueCollection values = ((Dictionary<int, GameObject>)AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs").GetValue(ZNetScene.instance)).Values;
			foreach (GameObject item2 in values)
			{
				if ((Object)(object)item2 != (Object)null && !list.Contains(item2))
				{
					list.Add(item2);
				}
			}
			Dbgl($"Checking {list.Count} prefabs");
			foreach (GameObject item3 in list)
			{
				if (!((Object)(object)item3 == (Object)null) && !(((Object)item3).name == "_NetSceneRoot"))
				{
					ReplaceOneGameObjectTextures(item3, ((Object)item3).name, "object");
				}
			}
			ReplaceSkyBoxTexture();
			if (logDump.Any())
			{
				Dbgl("\n" + string.Join("\n", logDump));
			}
		}

		private static void ReplaceSceneObjects()
		{
			SkinnedMeshRenderer[] array = Object.FindObjectsOfType<SkinnedMeshRenderer>();
			MeshRenderer[] array2 = Object.FindObjectsOfType<MeshRenderer>();
			ParticleSystemRenderer[] array3 = Object.FindObjectsOfType<ParticleSystemRenderer>();
			InstanceRenderer[] collection = Object.FindObjectsOfType<InstanceRenderer>();
			LineRenderer[] array4 = Object.FindObjectsOfType<LineRenderer>();
			ItemDrop[] array5 = Object.FindObjectsOfType<ItemDrop>();
			Dbgl($"smrs {array.Length}, mrs {array2.Length}, psrs {array3.Length}, lrs {array4.Length}, ids {array5.Length}");
			List<Component> list = new List<Component>();
			list.AddRange((IEnumerable<Component>)(object)array);
			list.AddRange((IEnumerable<Component>)(object)array2);
			list.AddRange((IEnumerable<Component>)(object)array3);
			list.AddRange((IEnumerable<Component>)(object)collection);
			list.AddRange((IEnumerable<Component>)(object)array4);
			list.AddRange((IEnumerable<Component>)(object)array5);
			foreach (Component item in list)
			{
				Transform val = item.transform;
				GameObject gameObject = item.gameObject;
				while ((Object)(object)val.parent != (Object)null)
				{
					if ((Object)(object)((Component)val).GetComponent<MeshRenderer>() != (Object)null || (Object)(object)((Component)val).GetComponent<SkinnedMeshRenderer>() != (Object)null || (Object)(object)((Component)val).GetComponent<InstanceRenderer>() != (Object)null || (Object)(object)((Component)val).GetComponent<LineRenderer>() != (Object)null || (Object)(object)((Component)val).GetComponent<ParticleSystemRenderer>() != (Object)null || (Object)(object)((Component)val).GetComponent<ItemDrop>() != (Object)null)
					{
						gameObject = ((Component)val).gameObject;
					}
					val = val.parent;
				}
				ReplaceOneGameObjectTextures(gameObject, ((Object)gameObject).name, "object");
			}
		}

		private static void ReplaceSkyBoxTexture()
		{
			//IL_0081: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			if (customTextures.ContainsKey("skybox_StarFieldTex"))
			{
				Texture texture = RenderSettings.skybox.GetTexture("_StarFieldTex");
				Cubemap val = (Cubemap)(object)((texture is Cubemap) ? texture : null);
				Dbgl(string.Format("original skybox {0}x{1} {2} {3}", RenderSettings.skybox.GetTexture("_StarFieldTex").width, RenderSettings.skybox.GetTexture("_StarFieldTex").height, RenderSettings.skybox.GetTexture("_StarFieldTex").graphicsFormat, RenderSettings.skybox.GetTexture("_StarFieldTex").filterMode));
				Cubemap val2 = new Cubemap(((Texture)val).width, (TextureFormat)3, false);
				Texture2D val3 = LoadTexture("skybox_StarFieldTex", null, isBump: false);
				Color[] pixels = val3.GetPixels();
				for (int i = 0; i < 6; i++)
				{
					val2.SetPixels(pixels, (CubemapFace)i);
					val2.Apply();
				}
				RenderSettings.skybox.SetTexture("_StarFieldTex", (Texture)(object)val2);
				Dbgl("set skybox texture");
			}
			if (customTextures.ContainsKey("skybox_MoonTex"))
			{
				Texture2D val4 = LoadTexture("skybox_MoonTex", null, isBump: false);
				Color[] pixels2 = val4.GetPixels();
				RenderSettings.skybox.SetTexture("_MoonTex", (Texture)(object)val4);
				Dbgl("set moon texture");
			}
		}

		private static void ReplaceZoneSystemTextures(ZoneSystem __instance)
		{
			Dbgl("Reloading ZoneSystem textures " + ((Object)__instance).name + " " + ((Object)__instance.m_zonePrefab).name);
			ReplaceOneZoneTextures(((Object)__instance).name, __instance.m_zonePrefab);
		}

		private static void ReplaceOneZoneTextures(string zoneSystem, GameObject prefab)
		{
			ReplaceOneGameObjectTextures(prefab, zoneSystem, "zone");
			Transform obj = prefab.transform.Find("Terrain");
			Heightmap val = ((obj != null) ? ((Component)obj).GetComponent<Heightmap>() : null);
			Material val2 = val?.m_material;
			if ((Object)(object)val2 != (Object)null && AccessTools.Field(typeof(Heightmap), "m_meshRenderer").GetValue(val) != null)
			{
				outputDump.Add("terrain " + zoneSystem + ", prefab " + ((Object)prefab).name);
				ReplaceMaterialTextures(((Object)prefab).name, val2, zoneSystem, "terrain", "Terrain", ((Object)prefab).name, dumpSceneTextures.Value);
				val.Regenerate();
			}
		}

		private static void ReplaceLocationTextures()
		{
			if (!dumpSceneTextures.Value)
			{
				try
				{
					customTextures.First((KeyValuePair<string, string> k) => k.Key.StartsWith("location"));
				}
				catch
				{
					return;
				}
			}
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				if (!(((Object)val).name == "_Locations"))
				{
					continue;
				}
				Location[] componentsInChildren = val.GetComponentsInChildren<Location>(true);
				Dbgl($"Checking {componentsInChildren.Length} locations");
				Location[] array3 = componentsInChildren;
				foreach (Location location in array3)
				{
					if (!dumpSceneTextures.Value)
					{
						try
						{
							customTextures.First((KeyValuePair<string, string> k) => k.Key.StartsWith("location_") && k.Key.Contains(((Object)((Component)location).gameObject).name));
						}
						catch
						{
							continue;
						}
					}
					ReplaceOneGameObjectTextures(((Component)location).gameObject, ((Object)((Component)location).gameObject).name, "location");
				}
				break;
			}
		}

		private static void ReplaceHeightmapTextures()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			Dbgl($"Reloading Heightmap textures for {Heightmap.GetAllHeightmaps().Count} heightmaps");
			ZoneSystem val = (ZoneSystem)typeof(ZoneSystem).GetField("m_instance", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
			logDump.Clear();
			Heightmap val2 = (Heightmap)typeof(EnvMan).GetField("m_cachedHeightmap", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(EnvMan.instance);
			if ((Object)(object)val2 != (Object)null)
			{
				Material material = val2.m_material;
				if ((Object)(object)material != (Object)null)
				{
					outputDump.Add($"terrain {((Object)val).name}, prefab {val.m_zonePrefab}");
					ReplaceMaterialTextures(((Object)val.m_zonePrefab).name, material, ((Object)val).name, "terrain", "Terrain", ((Object)val.m_zonePrefab).name, dumpSceneTextures.Value);
					val2.Regenerate();
				}
			}
			foreach (Heightmap allHeightmap in Heightmap.GetAllHeightmaps())
			{
				Material material2 = allHeightmap.m_material;
				if ((Object)(object)material2 != (Object)null)
				{
					outputDump.Add($"terrain {((Object)val).name}, prefab {val.m_zonePrefab}");
					ReplaceMaterialTextures(((Object)val.m_zonePrefab).name, material2, ((Object)val).name, "terrain", "Terrain", ((Object)val.m_zonePrefab).name, dumpSceneTextures.Value);
				}
			}
			if (logDump.Any())
			{
				Dbgl("\n" + string.Join("\n", logDump));
			}
		}

		private static void ReplaceEnvironmentTextures()
		{
			Dbgl("Reloading Environment textures");
			GameObject val = GameObject.Find("_GameMain/_Environment");
			if ((Object)(object)val != (Object)null)
			{
				int childCount = val.transform.childCount;
				Dbgl($"Reloading {childCount} Environment textures");
				logDump.Clear();
				for (int i = 0; i < childCount; i++)
				{
					GameObject gameObject = ((Component)val.transform.GetChild(i)).gameObject;
					ReplaceOneGameObjectTextures(gameObject, ((Object)gameObject).name, "environment");
				}
				if (logDump.Any())
				{
					Dbgl("\n" + string.Join("\n", logDump));
				}
			}
		}

		private static void SetEquipmentTexture(string itemName, GameObject item)
		{
			if ((Object)(object)item != (Object)null && itemName != null && itemName.Length > 0)
			{
				ReplaceOneGameObjectTextures(item.gameObject, itemName, "object");
			}
		}

		private static void SetEquipmentListTexture(string itemName, List<GameObject> items)
		{
			if (items == null || !items.Any() || itemName == null || itemName.Length <= 0)
			{
				return;
			}
			for (int i = 0; i < items.Count; i++)
			{
				if (!((Object)(object)items[i] == (Object)null))
				{
					SetEquipmentTexture(itemName, items[i]);
				}
			}
		}

		private static void SetBodyEquipmentTexture(VisEquipment instance, string itemName, SkinnedMeshRenderer smr, List<GameObject> itemInstances)
		{
			if ((Object)(object)smr != (Object)null)
			{
				ReplaceOneGameObjectTextures(((Component)smr).gameObject, itemName, "object");
			}
			if (itemInstances == null)
			{
				return;
			}
			foreach (GameObject itemInstance in itemInstances)
			{
				ReplaceOneGameObjectTextures(itemInstance, itemName, "object");
			}
		}

		private static void ReplaceOneGameObjectTextures(GameObject gameObject, string thingName, string prefix)
		{
			if ((Object)(object)gameObject == (Object)null || reloadedObjects.Contains(((Object)gameObject).GetInstanceID()))
			{
				return;
			}
			reloadedObjects.Add(((Object)gameObject).GetInstanceID());
			if (thingName.Contains("_frac"))
			{
				if (dumpSceneTextures.Value)
				{
					outputDump.Add("skipping _frac " + thingName);
				}
				return;
			}
			bool flag = dumpSceneTextures.Value;
			if (flag && thingName.EndsWith("(Clone)"))
			{
				flag = false;
			}
			MeshRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<MeshRenderer>(true);
			SkinnedMeshRenderer[] componentsInChildren2 = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			InstanceRenderer[] componentsInChildren3 = gameObject.GetComponentsInChildren<InstanceRenderer>(true);
			ParticleSystemRenderer[] componentsInChildren4 = gameObject.GetComponentsInChildren<ParticleSystemRenderer>(true);
			LineRenderer[] componentsInChildren5 = gameObject.GetComponentsInChildren<LineRenderer>(true);
			if (componentsInChildren.Length != 0)
			{
				if (flag)
				{
					outputDump.Add($"{prefix} {thingName} has {componentsInChildren.Length} MeshRenderers:");
				}
				MeshRenderer[] array = componentsInChildren;
				foreach (MeshRenderer val in array)
				{
					if ((Object)(object)val == (Object)null)
					{
						if (flag)
						{
							outputDump.Add("\tnull");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add("\tMeshRenderer name: " + ((Object)val).name);
					}
					if (((Renderer)val).materials == null || !((Renderer)val).materials.Any())
					{
						if (flag)
						{
							outputDump.Add("\t\trenderer " + ((Object)val).name + " has no materials");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add($"\t\trenderer {((Object)val).name} has {((Renderer)val).materials.Length} materials");
					}
					Material[] materials = ((Renderer)val).materials;
					foreach (Material val2 in materials)
					{
						if ((Object)(object)val2 == (Object)null)
						{
							continue;
						}
						try
						{
							if (flag)
							{
								outputDump.Add("\t\t\t" + ((Object)val2).name + ":");
							}
							ReplaceMaterialTextures(((Object)gameObject).name, val2, thingName, prefix, "MeshRenderer", ((Object)val).name, flag);
						}
						catch (Exception arg)
						{
							logDump.Add($"\t\t\tError loading {((Object)val).name}:\r\n\r\n\t\t\t{arg}");
						}
					}
				}
			}
			if (componentsInChildren2.Length != 0)
			{
				if (flag)
				{
					outputDump.Add($"{prefix} {thingName} has {componentsInChildren2.Length} SkinnedMeshRenderers:");
				}
				SkinnedMeshRenderer[] array2 = componentsInChildren2;
				foreach (SkinnedMeshRenderer val3 in array2)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						if (flag)
						{
							outputDump.Add("\tnull");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add("\tSkinnedMeshRenderer name: " + ((Object)val3).name);
					}
					if (((Renderer)val3).materials == null || !((Renderer)val3).materials.Any())
					{
						if (flag)
						{
							outputDump.Add("\t\tsmr " + ((Object)val3).name + " has no materials");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add($"\t\tsmr {((Object)val3).name} has {((Renderer)val3).materials.Length} materials");
					}
					Material[] materials2 = ((Renderer)val3).materials;
					foreach (Material val4 in materials2)
					{
						if ((Object)(object)val4 == (Object)null)
						{
							continue;
						}
						try
						{
							if (flag)
							{
								outputDump.Add("\t\t\t" + ((Object)val4).name + ":");
							}
							ReplaceMaterialTextures(((Object)gameObject).name, val4, thingName, prefix, "SkinnedMeshRenderer", ((Object)val3).name, flag);
						}
						catch (Exception arg2)
						{
							logDump.Add($"\t\t\tError loading {((Object)val3).name}:\r\n\r\n\t\t\t{arg2}");
						}
					}
				}
			}
			if (componentsInChildren3.Length != 0)
			{
				if (flag)
				{
					outputDump.Add($"{prefix} {thingName} has {componentsInChildren3.Length} InstanceRenderer:");
				}
				InstanceRenderer[] array3 = componentsInChildren3;
				foreach (InstanceRenderer val5 in array3)
				{
					if ((Object)(object)val5 == (Object)null)
					{
						if (flag)
						{
							outputDump.Add("\tnull");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add("\tInstanceRenderer name: " + ((Object)val5).name);
					}
					if ((Object)(object)val5.m_material == (Object)null)
					{
						if (flag)
						{
							outputDump.Add("\t\tir " + ((Object)val5).name + " has no material");
						}
						continue;
					}
					try
					{
						if (flag)
						{
							outputDump.Add("\t\t\t" + ((Object)val5.m_material).name + ":");
						}
						ReplaceMaterialTextures(((Object)gameObject).name, val5.m_material, thingName, prefix, "InstanceRenderer", ((Object)val5).name, flag);
					}
					catch (Exception arg3)
					{
						logDump.Add($"\t\t\tError loading {((Object)val5).name}:\r\n\r\n\t\t\t{arg3}");
					}
				}
			}
			if (componentsInChildren4.Length != 0)
			{
				if (flag)
				{
					outputDump.Add($"{prefix} {thingName} has {componentsInChildren4.Length} ParticleSystemRenderers:");
				}
				ParticleSystemRenderer[] array4 = componentsInChildren4;
				foreach (ParticleSystemRenderer val6 in array4)
				{
					if ((Object)(object)val6 == (Object)null)
					{
						if (flag)
						{
							outputDump.Add("\tnull");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add("\tParticleSystemRenderer name: " + ((Object)val6).name);
					}
					Material[] materials3 = ((Renderer)val6).materials;
					foreach (Material val7 in materials3)
					{
						if ((Object)(object)val7 == (Object)null)
						{
							continue;
						}
						try
						{
							if (flag)
							{
								outputDump.Add("\t\t\t" + ((Object)val7).name + ":");
							}
							ReplaceMaterialTextures(((Object)gameObject).name, val7, thingName, prefix, "ParticleSystemRenderer", ((Object)val6).name, flag);
						}
						catch (Exception arg4)
						{
							logDump.Add($"\t\t\tError loading {((Object)val6).name}:\r\n\r\n\t\t\t{arg4}");
						}
					}
				}
			}
			if (componentsInChildren5.Length != 0)
			{
				if (flag)
				{
					outputDump.Add($"{prefix} {thingName} has {componentsInChildren5.Length} LineRenderers:");
				}
				LineRenderer[] array5 = componentsInChildren5;
				foreach (LineRenderer val8 in array5)
				{
					if ((Object)(object)val8 == (Object)null)
					{
						if (flag)
						{
							outputDump.Add("\tnull");
						}
						continue;
					}
					if (flag)
					{
						outputDump.Add("\tLineRenderers name: " + ((Object)val8).name);
					}
					Material[] materials4 = ((Renderer)val8).materials;
					foreach (Material val9 in materials4)
					{
						if ((Object)(object)val9 == (Object)null)
						{
							continue;
						}
						try
						{
							if (flag)
							{
								outputDump.Add("\t\t\t" + ((Object)val9).name + ":");
							}
							ReplaceMaterialTextures(((Object)gameObject).name, val9, thingName, prefix, "LineRenderer", ((Object)val8).name, flag);
						}
						catch (Exception arg5)
						{
							logDump.Add($"\t\t\tError loading {((Object)val8).name}:\r\n\r\n\t\t\t{arg5}");
						}
					}
				}
			}
			ItemDrop[] componentsInChildren6 = gameObject.GetComponentsInChildren<ItemDrop>();
			ItemDrop[] array6 = componentsInChildren6;
			foreach (ItemDrop val10 in array6)
			{
				if ((Object)(object)val10?.m_itemData?.m_shared?.m_armorMaterial != (Object)null)
				{
					if (flag)
					{
						outputDump.Add("armor " + thingName + " has Material:");
					}
					Material armorMaterial = val10.m_itemData.m_shared.m_armorMaterial;
					if (flag)
					{
						outputDump.Add("\tArmor name: " + ((Object)armorMaterial).name);
					}
					ReplaceMaterialTextures(((Object)gameObject).name, armorMaterial, thingName, "armor", "Armor", ((Object)gameObject).name, flag);
				}
			}
		}

		private static void ReplaceMaterialTextures(string goName, Material m, string thingName, string prefix, string rendererType, string rendererName, bool dump)
		{
			if ((Object)(object)m == (Object)null)
			{
				return;
			}
			if (dumpSceneTextures.Value)
			{
				outputDump.Add("\t\t\t\tproperties:");
			}
			if (prefix == "item")
			{
				prefix = "object";
			}
			string[] texturePropertyNames = m.GetTexturePropertyNames();
			foreach (string text in texturePropertyNames)
			{
				if (dumpSceneTextures.Value)
				{
					List<string> list = outputDump;
					Texture texture = m.GetTexture(text);
					list.Add("\t\t\t\t\t" + text + " " + ((texture != null) ? ((Object)texture).name : null));
				}
				int num = Shader.PropertyToID(text);
				Texture texture2 = m.GetTexture(num);
				string text2 = ((texture2 != null) ? ((Object)texture2).name : null);
				if (text2 == null)
				{
					text2 = thingName;
				}
				CheckSetMatTextures(goName, m, prefix, thingName, rendererType, rendererName, text2, text);
			}
		}

		private static void CheckSetMatTextures(string goName, Material m, string prefix, string thingName, string rendererType, string rendererName, string name, string property)
		{
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			string[] array = MakePrefixStrings(prefix, thingName, rendererName, ((Object)m).name, name);
			foreach (string text in array)
			{
				if (!ShouldLoadCustomTexture(text + property))
				{
					continue;
				}
				int num = Shader.PropertyToID(property);
				if (!m.HasProperty(num))
				{
					continue;
				}
				Dbgl(prefix + " " + thingName + ", " + rendererType + " " + rendererName + ", material " + ((Object)m).name + ", texture " + name + ", using " + text + property + " for " + property + ".");
				Texture texture = m.GetTexture(num);
				Texture2D val = null;
				bool isBump = property.Contains("Bump") || property.Contains("Normal");
				if (ShouldLoadCustomTexture(text + property))
				{
					val = LoadTexture(text + property, texture, isBump);
				}
				else if (property == "_MainTex" && ShouldLoadCustomTexture(text + "_texture"))
				{
					val = LoadTexture(text + "_texture", texture, isBump);
				}
				else if (property == "_BumpMap" && ShouldLoadCustomTexture(text + "_bump"))
				{
					val = LoadTexture(text + "_bump", texture, isBump);
				}
				else if (property == "_StyleTex" && ShouldLoadCustomTexture(text + "_style"))
				{
					val = LoadTexture(text + "_style", texture, isBump);
				}
				if (!((Object)(object)val == (Object)null))
				{
					((Object)val).name = name;
					m.SetTexture(num, (Texture)(object)val);
					if ((Object)(object)val != (Object)null && property == "_MainTex")
					{
						m.SetColor(num, Color.white);
					}
					break;
				}
			}
		}

		private static string[] MakePrefixStrings(string prefix, string thingName, string rendererName, string matName, string name)
		{
			string[] array = new string[10]
			{
				prefix + "_" + thingName,
				prefix + "mesh_" + thingName + "_" + rendererName,
				prefix + "renderer_" + thingName + "_" + rendererName,
				prefix + "mat_" + thingName + "_" + matName,
				prefix + "renderermat_" + thingName + "_" + rendererName + "_" + matName,
				prefix + "texture_" + thingName + "_" + name,
				"mesh_" + rendererName,
				"renderer_" + rendererName,
				"mat_" + matName,
				"texture_" + name
			};
			if (!thingName.EndsWith("(Clone)"))
			{
				return array;
			}
			List<string> list = new List<string>(array);
			thingName = thingName.Substring(0, thingName.Length - "(Clone)".Length);
			list.AddRange(new string[10]
			{
				prefix + "_" + thingName,
				prefix + "mesh_" + thingName + "_" + rendererName,
				prefix + "renderer_" + thingName + "_" + rendererName,
				prefix + "mat_" + thingName + "_" + matName,
				prefix + "renderermat_" + thingName + "_" + rendererName + "_" + matName,
				prefix + "texture_" + thingName + "_" + name,
				"mesh_" + rendererName,
				"renderer_" + rendererName,
				"mat_" + matName,
				"texture_" + name
			});
			return list.ToArray();
		}

		private static Texture2D LoadTexture(string id, Texture vanilla, bool isBump, bool point = true, bool needCustom = false, bool isSprite = false)
		{
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Expected O, but got Unknown
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Expected O, but got Unknown
			//IL_06d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0713: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0707: Unknown result type (might be due to invalid IL or missing references)
			//IL_072e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0733: Unknown result type (might be due to invalid IL or missing references)
			//IL_0735: Unknown result type (might be due to invalid IL or missing references)
			//IL_0737: Unknown result type (might be due to invalid IL or missing references)
			//IL_0739: Unknown result type (might be due to invalid IL or missing references)
			//IL_0746: Unknown result type (might be due to invalid IL or missing references)
			//IL_074b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0752: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val;
			if (cachedTextures.ContainsKey(id))
			{
				logDump.Add("loading cached texture for " + id);
				val = cachedTextures[id];
				if (customTextures.ContainsKey(id))
				{
					if (customTextures[id].Contains("bilinear"))
					{
						((Texture)val).filterMode = (FilterMode)1;
					}
					else if (customTextures[id].Contains("trilinear"))
					{
						((Texture)val).filterMode = (FilterMode)2;
					}
					else if (customTextures[id].Contains($"{Path.DirectorySeparatorChar}point{Path.DirectorySeparatorChar}"))
					{
						((Texture)val).filterMode = (FilterMode)2;
					}
					else if (point)
					{
						((Texture)val).filterMode = (FilterMode)0;
					}
				}
				return val;
			}
			IEnumerable<KeyValuePair<string, string>> source = customTextures.Where((KeyValuePair<string, string> p) => p.Key.StartsWith(id + "_"));
			if (!customTextures.ContainsKey(id) && source.Count() == 0)
			{
				if (needCustom)
				{
					return null;
				}
				return (Texture2D)vanilla;
			}
			logDump.Add($"loading custom texture for {id} {source.Count()} layers");
			if ((Object)(object)vanilla == (Object)null)
			{
				val = new Texture2D(2, 2, (TextureFormat)4, true, isBump);
				if (!customTextures.ContainsKey(id))
				{
					byte[] array = File.ReadAllBytes(source.First().Value);
					ImageConversion.LoadImage(val, array);
				}
			}
			else
			{
				val = new Texture2D(vanilla.width, vanilla.height, (TextureFormat)4, true, isBump);
			}
			if (customTextures.ContainsKey(id))
			{
				if (customTextures[id].Contains($"{Path.DirectorySeparatorChar}bilinear{Path.DirectorySeparatorChar}"))
				{
					((Texture)val).filterMode = (FilterMode)1;
				}
				else if (customTextures[id].Contains($"{Path.DirectorySeparatorChar}trilinear{Path.DirectorySeparatorChar}"))
				{
					((Texture)val).filterMode = (FilterMode)2;
				}
				else if (customTextures[id].Contains($"{Path.DirectorySeparatorChar}point{Path.DirectorySeparatorChar}"))
				{
					((Texture)val).filterMode = (FilterMode)2;
				}
				else if (point)
				{
					((Texture)val).filterMode = (FilterMode)0;
				}
			}
			else if (point)
			{
				((Texture)val).filterMode = (FilterMode)0;
			}
			if (customTextures.ContainsKey(id))
			{
				logDump.Add("loading custom texture file for " + id);
				byte[] array2 = File.ReadAllBytes(customTextures[id]);
				ImageConversion.LoadImage(val, array2);
			}
			else if ((Object)(object)vanilla != (Object)null)
			{
				Dbgl("texture " + id + " has no custom texture, using vanilla");
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)val).width, ((Texture)val).height, 0, (RenderTextureFormat)7, (RenderTextureReadWrite)(isBump ? 1 : 0));
				Graphics.Blit(vanilla, temporary);
				RenderTexture active = RenderTexture.active;
				RenderTexture.active = temporary;
				Texture2D val2 = new Texture2D(vanilla.width, vanilla.height, (TextureFormat)4, true, isBump);
				val2.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0);
				val2.Apply();
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				val.SetPixels(val2.GetPixels());
				val.Apply();
			}
			if (source.Count() > 0)
			{
				Dbgl($"texture {id} has {source.Count()} layers");
				foreach (KeyValuePair<string, string> item in source.Skip(((Object)(object)vanilla == (Object)null && !customTextures.ContainsKey(id)) ? 1 : 0))
				{
					Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, true, isBump);
					((Texture)val3).filterMode = (FilterMode)(isSprite ? 1 : 0);
					byte[] array3 = File.ReadAllBytes(item.Value);
					ImageConversion.LoadImage(val3, array3);
					int result = 0;
					int result2 = 0;
					int result3 = ((Texture)val3).width;
					int result4 = ((Texture)val3).height;
					if (isSprite)
					{
						string[] array4 = item.Key.Substring(id.Length + 1).Split('_');
						if (array4.Length != 4 || !int.TryParse(array4[0], out result) || !int.TryParse(array4[1], out result2) || !int.TryParse(array4[2], out result3) || !int.TryParse(array4[3], out result4))
						{
							continue;
						}
					}
					float num = (float)((Texture)val).width / (float)result3;
					float num2 = (float)((Texture)val).height / (float)result4;
					if (num != num2)
					{
						continue;
					}
					logDump.Add($"adding layer {item.Key} to {id}, scale diff {num}");
					int num3 = 0;
					int num4 = 0;
					int num5 = ((Texture)val3).width;
					int num6 = ((Texture)val3).height;
					if (isSprite)
					{
						num3 = result;
						num4 = result2;
						num5 = result + ((Texture)val3).width;
						num6 = result2 + ((Texture)val3).height;
					}
					if (num < 1f)
					{
						TextureScale.Bilinear(val, (int)((float)((Texture)val).width / num), (int)((float)((Texture)val).height / num));
					}
					else if (num > 1f)
					{
						TextureScale.Bilinear(val3, (int)((float)((Texture)val3).width * num), (int)((float)((Texture)val3).height * num));
						num3 = (int)((float)result * num);
						num4 = (int)((float)result2 * num);
						num5 = (int)((float)(result + ((Texture)val3).width) * num);
						num6 = (int)((float)(result2 + ((Texture)val3).height) * num);
					}
					List<string> list = new List<string>();
					for (int num7 = num3; num7 < num5; num7++)
					{
						for (int num8 = num4; num8 < num6; num8++)
						{
							int num9 = num7 - num3;
							int num10 = num8 - num4;
							Color pixel = val3.GetPixel(num9, num10);
							if (isSprite)
							{
								pixel = val3.GetPixel(num9, ((Texture)val3).height - num10);
								val.SetPixel(num7, ((Texture)val).height - num8, pixel);
							}
							else if (pixel.a != 0f)
							{
								Color pixel2 = val.GetPixel(num7, num8);
								Color val4 = Color.Lerp(pixel2, pixel, pixel.a / 1f);
								val.SetPixel(num7, num8, val4);
							}
						}
					}
					val.Apply();
				}
				bool flag = false;
			}
			cachedTextures[id] = val;
			return val;
		}

		private static void LoadCustomTextures()
		{
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "CustomTextures");
			if (!Directory.Exists(text))
			{
				Dbgl("Directory " + text + " does not exist! Creating.");
				Directory.CreateDirectory(text);
				return;
			}
			texturesToLoad.Clear();
			string[] files = Directory.GetFiles(text, "*.*", SearchOption.AllDirectories);
			foreach (string text2 in files)
			{
				string fileName = Path.GetFileName(text2);
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
				if (!fileWriteTimes.ContainsKey(fileNameWithoutExtension) || (cachedTextures.ContainsKey(fileNameWithoutExtension) && !DateTime.Equals(File.GetLastWriteTimeUtc(text2), fileWriteTimes[fileNameWithoutExtension])))
				{
					cachedTextures.Remove(fileNameWithoutExtension);
					texturesToLoad.Add(fileNameWithoutExtension);
					layersToLoad.Add(Regex.Replace(fileNameWithoutExtension, "_[^_]+\\.", "."));
					fileWriteTimes[fileNameWithoutExtension] = File.GetLastWriteTimeUtc(text2);
				}
				customTextures[fileNameWithoutExtension] = text2;
			}
		}

		private static void ReloadTextures(bool locations)
		{
			//IL_0054: 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)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			reloadedObjects.Clear();
			outputDump.Clear();
			logDump.Clear();
			LoadCustomTextures();
			ReplaceObjectDBTextures();
			ReplaceSceneObjects();
			Dbgl($"Replaced textures for {reloadedObjects.Count()} found unique objects");
			Scene activeScene = SceneManager.GetActiveScene();
			IEnumerable<GameObject> enumerable = from go in ((Scene)(ref activeScene)).GetRootGameObjects()
				where ((Object)go).name.StartsWith("_Zone")
				select go;
			Dbgl($"Replacing textures for {enumerable.Count()} zones");
			foreach (GameObject item in enumerable)
			{
				ReplaceOneZoneTextures("_GameMain", item);
			}
			ReplaceZoneSystemTextures((ZoneSystem)typeof(ZoneSystem).GetField("m_instance", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null));
			ReplaceHeightmapTextures();
			ReplaceEnvironmentTextures();
			ReplaceZNetSceneTextures();
			if (locations)
			{
				Dbgl("Starting ZoneSystem Location prefab replacement");
				stopwatch.Restart();
				ReplaceLocationTextures();
				LogStopwatch("ZoneSystem Locations");
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				SetupVisEquipment((Humanoid)(object)allPlayer);
			}
			if (logDump.Any())
			{
				Dbgl("\n" + string.Join("\n", logDump));
			}
			Dbgl($"Checked {reloadedObjects.Count} objects total");
			reloadedObjects.Clear();
			if (dumpSceneTextures.Value)
			{
				string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "CustomTextures", "scene_dump.txt");
				Dbgl("Writing " + text);
				File.WriteAllLines(text, outputDump);
				dumpSceneTextures.Value = false;
			}
		}

		private static void SetupVisEquipment(Humanoid humanoid)
		{
			try
			{
				object? obj = AccessTools.Field(typeof(Humanoid), "m_visEquipment")?.GetValue(humanoid);
				VisEquipment val = (VisEquipment)((obj is VisEquipment) ? obj : null);
				if (!((Object)(object)val == (Object)null))
				{
					SetEquipmentTexture(GetVisItemName(val, "m_leftItem"), GetVisGameObject(val, "m_leftItemInstance"));
					SetEquipmentTexture(GetVisItemName(val, "m_rightItem"), GetVisGameObject(val, "m_rightItemInstance"));
					SetEquipmentTexture(GetVisItemName(val, "m_helmetItem"), GetVisGameObject(val, "m_helmetItemInstance"));
					SetEquipmentTexture(GetVisItemName(val, "m_leftBackItem"), GetVisGameObject(val, "m_leftBackItemInstance"));
					SetEquipmentTexture(GetVisItemName(val, "m_rightBackItem"), GetVisGameObject(val, "m_rightBackItemInstance"));
					SetEquipmentListTexture(GetVisItemName(val, "m_shoulderItem"), GetVisGameObjectList(val, "m_shoulderItemInstances"));
					SetEquipmentListTexture(GetVisItemName(val, "m_utilityItem"), GetVisGameObjectList(val, "m_utilityItemInstances"));
					SetEquipmentListTexture(GetVisItemName(val, "m_trinketItem"), GetVisGameObjectList(val, "m_trinketItemInstances"));
					SetBodyEquipmentTexture(val, GetVisItemName(val, "m_legItem"), val.m_bodyModel, GetVisGameObjectList(val, "m_legItemInstances"));
					SetBodyEquipmentTexture(val, GetVisItemName(val, "m_chestItem"), val.m_bodyModel, GetVisGameObjectList(val, "m_chestItemInstances"));
				}
			}
			catch (Exception arg)
			{
				Dbgl($"SetupVisEquipment error: {arg}");
			}
		}

		private static object GetVisField(VisEquipment ve, string fieldName)
		{
			return AccessTools.Field(typeof(VisEquipment), fieldName)?.GetValue(ve);
		}

		private static string GetVisItemName(VisEquipment ve, string fieldName)
		{
			object visField = GetVisField(ve, fieldName);
			if (visField is string text)
			{
				return string.IsNullOrEmpty(text) ? null : text;
			}
			if (visField is int num && num != 0 && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(num);
				return ((Object)(object)prefab != (Object)null) ? ((Object)prefab).name : null;
			}
			return null;
		}

		private static GameObject GetVisGameObject(VisEquipment ve, string fieldName)
		{
			object visField = GetVisField(ve, fieldName);
			return (GameObject)((visField is GameObject) ? visField : null);
		}

		private static List<GameObject> GetVisGameObjectList(VisEquipment ve, string fieldName)
		{
			object visField = GetVisField(ve, fieldName);
			if (visField is List<GameObject> result)
			{
				return result;
			}
			if (visField is GameObject[] source)
			{
				return source.ToList();
			}
			return null;
		}
	}
}