Decompiled source of Lanach Admin v1.0.0

BepInEx/plugins/ValheimHDTerrain.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using ValheimHDTerrain.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("FindObjectTexture")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FindObjectTexture")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("26565f84-978a-4666-88ca-4465f43cb131")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ValheimHDTerrain
{
	internal class Config
	{
		private ConfigFile cf = new ConfigFile(Mod.ConfigFile, true);

		public ConfigEntry<bool> EnableExtendedDebug;

		public ConfigEntry<bool> DeveloperMode;

		public ConfigEntry<KeyCode> ReloadTextureKey;

		public ConfigEntry<KeyCode> ReloadShaderKey;

		public ConfigEntry<float> GrassDrawDistance;

		public ConfigEntry<float> GrassAmountModifier;

		public ConfigEntry<float> WaterCausticsEnabled;

		public Config()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			EnableExtendedDebug = cf.Bind<bool>("Mod", "EnableExtendedDebug", false, "Enable Extended Debug Information");
			DeveloperMode = cf.Bind<bool>("Mod", "EnableDeveloperMode", false, "Enable Developer Mode");
			ReloadTextureKey = cf.Bind<KeyCode>("Keybinds", "ReloadTexturesKey", (KeyCode)287, "Key to hot reload textures");
			ReloadShaderKey = cf.Bind<KeyCode>("Keybinds", "ReloadShaderKey", (KeyCode)289, "Key to reload shader");
			GrassDrawDistance = cf.Bind<float>("Clutter", "GrassDrawDistance", 40f, "Grass Draw Distance");
			GrassAmountModifier = cf.Bind<float>("Clutter", "GrassAmountModifier", 1f, "Modifier for grass amount");
			WaterCausticsEnabled = cf.Bind<float>("Shader Effects", "WaterCausticsEnabled", 1f, "Enable/Disable Water Caustics");
		}
	}
	internal class HarmonyPatches
	{
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		private class Terminal_InitTerminal
		{
			private static void Postfix()
			{
				Mod.AddConsoleCommands();
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		private class Player_Update
		{
			private static void Prefix()
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				if (Input.GetKeyDown(Mod.Config.ReloadShaderKey.Value) && Mod.Config.DeveloperMode.Value)
				{
					bLog.Log("Reloading Shader");
					Mod.LoadShader();
					Mod.ApplyShader();
				}
				if (!Input.GetKeyDown(Mod.Config.ReloadTextureKey.Value) || !Mod.Config.DeveloperMode.Value)
				{
					return;
				}
				Mod.CreateTerrainArrays();
				Mod.LoadAdditionalTextures();
				foreach (Heightmap allHeightmap in Heightmap.GetAllHeightmaps())
				{
					if ((Object)(object)allHeightmap.m_materialInstance != (Object)null)
					{
						bLog.Log("Replacing heightmap shader");
						if (!allHeightmap.m_isDistantLod)
						{
							allHeightmap.m_materialInstance.SetTexture("_DiffuseArrayTex", (Texture)(object)Mod.DiffuseArray);
							allHeightmap.m_materialInstance.SetTexture("_NormalArrayTex", (Texture)(object)Mod.NormalArray);
							allHeightmap.m_materialInstance.SetTexture("_WaterCaustics", (Texture)(object)Mod.WaterCaustics);
						}
						else if (allHeightmap.m_isDistantLod)
						{
							allHeightmap.m_materialInstance.SetTexture("_DiffuseArrayTex", (Texture)(object)Mod.DiffuseArrayLod);
							allHeightmap.m_materialInstance.SetTexture("_NormalArrayTex", (Texture)(object)Mod.NormalArrayLod);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(Heightmap), "Awake")]
		private class HeightMap_Awake
		{
			private static void Prefix(Heightmap __instance)
			{
				if ((Object)(object)Mod.TerrainShader != (Object)null && Mod.UseShader)
				{
					bLog.Log($"Is Distant Lod: {__instance.m_isDistantLod}");
					if ((Object)(object)__instance.m_material != (Object)null)
					{
						bLog.Log("Replacing Terrain Shader");
						__instance.m_material.shader = Mod.TerrainShader;
					}
					else
					{
						bLog.Log("heightmap does not have material");
					}
				}
				else
				{
					bLog.Log("Terrain shader is null, will not replace.");
				}
			}
		}

		[HarmonyPatch(typeof(Heightmap), "Initialize")]
		private class Heightmap_Initialize
		{
			private static void Postfix(Heightmap __instance)
			{
				if (Mod.ReplaceTextures)
				{
					if (!__instance.m_isDistantLod)
					{
						__instance.m_material.SetTexture("_DiffuseArrayTex", (Texture)(object)Mod.DiffuseArray);
						__instance.m_material.SetTexture("_NormalArrayTex", (Texture)(object)Mod.NormalArray);
						__instance.m_material.SetTexture("_WaterCaustics", (Texture)(object)Mod.WaterCaustics);
					}
					else if (__instance.m_isDistantLod)
					{
						__instance.m_material.SetTexture("_DiffuseArrayTex", (Texture)(object)Mod.DiffuseArrayLod);
						__instance.m_material.SetTexture("_NormalArrayTex", (Texture)(object)Mod.NormalArrayLod);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Heightmap), "RebuildCollisionMesh")]
		private class Heightmap_RebuildCollisionMesh
		{
			private static bool Prefix(Heightmap __instance)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Expected O, but got Unknown
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance.m_collisionMesh == (Object)null)
				{
					__instance.m_collisionMesh = new Mesh();
					((Object)__instance.m_collisionMesh).name = "___Heightmap m_collisionMesh";
				}
				int num = __instance.m_width + 1;
				Heightmap.s_tempVertices.Clear();
				Heightmap.s_tempIndices.Clear();
				for (int i = 0; i < num; i++)
				{
					for (int j = 0; j < num; j++)
					{
						Heightmap.s_tempVertices.Add(__instance.CalcVertex(j, i));
						if (i != 0 && j != 0)
						{
							Heightmap.s_tempIndices.Add(num * (i - 1) + j - 1);
							Heightmap.s_tempIndices.Add(num * i + j - 1);
							Heightmap.s_tempIndices.Add(num * (i - 1) + j);
							Heightmap.s_tempIndices.Add(num * i + j - 1);
							Heightmap.s_tempIndices.Add(num * i + j);
							Heightmap.s_tempIndices.Add(num * (i - 1) + j);
						}
					}
				}
				__instance.m_collisionMesh.SetVertices(Heightmap.s_tempVertices);
				__instance.m_collisionMesh.SetIndices(Heightmap.s_tempIndices.ToArray(), (MeshTopology)0, 0);
				if (Object.op_Implicit((Object)(object)__instance.m_collider))
				{
					__instance.m_collider.sharedMesh = __instance.m_collisionMesh;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(ClutterSystem), "Awake")]
		private class ClutterSystem_AwakePatch
		{
			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Postfix(ClutterSystem __instance)
			{
				if (Mod.TweaksInstalled)
				{
					return;
				}
				for (int i = 0; i < __instance.m_clutter.Count; i++)
				{
					if (__instance.m_clutter[i].m_instanced)
					{
						__instance.m_clutter[i].m_prefab.GetComponent<InstanceRenderer>().m_useLod = false;
						__instance.m_clutter[i].m_prefab.GetComponent<InstanceRenderer>().m_useXZLodDistance = false;
					}
				}
				__instance.m_distance = Mod.Config.GrassDrawDistance.Value;
				__instance.m_amountScale = Mod.Config.GrassAmountModifier.Value;
			}
		}

		[HarmonyPatch(typeof(ClutterSystem), "LateUpdate")]
		private class ClutterSysten_LateUpdatePatch
		{
			[HarmonyPrefix]
			private static void Prefix(ClutterSystem __instance)
			{
				if (!Mod.TweaksInstalled)
				{
					__instance.m_distance = Mod.Config.GrassDrawDistance.Value;
					if (Mod.ForceUpdateClutter)
					{
						__instance.m_amountScale = Mod.Config.GrassAmountModifier.Value;
						Mod.ForceUpdateClutter = false;
						__instance.ClearAll();
						bLog.Log("Rebuilding Grass");
					}
				}
			}
		}

		private Harmony harmony = new Harmony("Badgers.ValheimHDTerrain");

		public HarmonyPatches()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony.PatchAll();
		}
	}
	[DataContract]
	internal class TerrainConfig
	{
		[DataMember]
		public float cliffLowThreshold = 0.8f;

		[DataMember]
		public float cliffHighThreshold = 0.9f;

		[DataMember]
		public float rockLowThreshold = 0.7f;

		[DataMember]
		public float rockHighThreshold = 0.86f;

		[DataMember]
		public float cliffLowThresholdForest = 0.7f;

		[DataMember]
		public float cliffHighThresholdForest = 0.95f;

		[DataMember]
		public float rockLowThresholdForest = 0.65f;

		[DataMember]
		public float rockHighThresholdForest = 0.8f;

		[DataMember]
		public float cliffLowThresholdMountain = 0.6f;

		[DataMember]
		public float cliffHighThresholdMountain = 0.8f;

		[DataMember]
		public float rockLowThresholdMountain = 0.4f;

		[DataMember]
		public float rockHighThresholdMountain = 0.6f;

		[DataMember]
		public float cliffLowThresholdPlains = 0.7f;

		[DataMember]
		public float cliffHighThresholdPlains = 1f;

		[DataMember]
		public float rockLowThresholdPlains = 0.55f;

		[DataMember]
		public float rockHighThresholdPlains = 0.7f;

		[DataMember]
		public int tilingAmount = 8;

		public static TerrainConfig Load(string Path)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			TerrainConfig result = new TerrainConfig();
			using (FileStream fileStream = new FileStream(Path, FileMode.Open))
			{
				DataContractJsonSerializer val = new DataContractJsonSerializer(typeof(TerrainConfig));
				result = (TerrainConfig)((XmlObjectSerializer)val).ReadObject((Stream)fileStream);
			}
			return result;
		}

		public void Save(string FileName)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			using FileStream fileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write);
			DataContractJsonSerializer val = new DataContractJsonSerializer(typeof(TerrainConfig));
			((XmlObjectSerializer)val).WriteObject((Stream)fileStream, (object)this);
		}
	}
	[BepInPlugin("Badgers.ValheimHDTerrain", "ValheimHDTerrain", "0.1.0")]
	[BepInProcess("valheim.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class HDTerrain : BaseUnityPlugin
	{
		private HarmonyPatches DefaultPatches;

		private void Awake()
		{
			DefaultPatches = new HarmonyPatches();
			if (HasConflictingMods())
			{
				Mod.TweaksInstalled = true;
			}
			Mod.Init();
		}

		private bool HasConflictingMods()
		{
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if (pluginInfo.Value.Metadata.GUID == "Badgers.ValheimTweaksLite")
				{
					bLog.Log("Valheim Tweaks mod is loaded, clutter changes will not be enabled.", extendedlog: true);
					return true;
				}
			}
			return false;
		}
	}
	internal static class Mod
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__33_0;

			public static ConsoleEvent <>9__33_1;

			public static ConsoleEvent <>9__33_2;

			public static ConsoleEvent <>9__33_3;

			public static ConsoleEvent <>9__33_4;

			public static ConsoleEvent <>9__33_5;

			public static ConsoleEvent <>9__33_6;

			public static ConsoleEvent <>9__33_7;

			public static ConsoleEvent <>9__33_8;

			internal void <AddConsoleCommands>b__33_0(ConsoleEventArgs args)
			{
				if (args.Length == 2)
				{
					string text = args[1].ToString();
					string text2 = text.ToLower();
					string text3 = text2;
					if (!(text3 == "enabled"))
					{
						if (text3 == "disabled")
						{
							Config.WaterCausticsEnabled.Value = 0f;
							Shader.SetGlobalFloat("_WaterCausticsEnabled", Config.WaterCausticsEnabled.Value);
						}
					}
					else
					{
						Config.WaterCausticsEnabled.Value = 1f;
						Shader.SetGlobalFloat("_WaterCausticsEnabled", Config.WaterCausticsEnabled.Value);
					}
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set water caustics");
				}
			}

			internal void <AddConsoleCommands>b__33_1(ConsoleEventArgs args)
			{
				if (args.Length == 2)
				{
					Config.GrassDrawDistance.Value = float.Parse(args[1], CultureInfo.InvariantCulture);
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set grass draw distance");
				}
			}

			internal void <AddConsoleCommands>b__33_2(ConsoleEventArgs args)
			{
				if (args.Length == 2)
				{
					Config.GrassAmountModifier.Value = float.Parse(args[1], CultureInfo.InvariantCulture);
					ForceUpdateClutter = true;
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set grass amount");
				}
			}

			internal void <AddConsoleCommands>b__33_3(ConsoleEventArgs args)
			{
				if (args.Length == 3)
				{
					switch (Convert.ToString(args[1]))
					{
					case "meadows":
						TerrainConfig.rockLowThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockLowThreshold", TerrainConfig.rockLowThreshold);
						break;
					case "forest":
						TerrainConfig.rockLowThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockLowThresholdForest", TerrainConfig.rockLowThresholdForest);
						break;
					case "mountains":
						TerrainConfig.rockLowThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockLowThresholdMountain", TerrainConfig.rockLowThresholdMountain);
						break;
					case "plains":
						TerrainConfig.rockLowThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockLowThresholdPlains", TerrainConfig.rockLowThresholdPlains);
						break;
					}
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set threshold");
				}
			}

			internal void <AddConsoleCommands>b__33_4(ConsoleEventArgs args)
			{
				if (args.Length == 3)
				{
					switch (Convert.ToString(args[1]))
					{
					case "meadows":
						TerrainConfig.rockHighThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockHighThreshold", TerrainConfig.rockHighThreshold);
						break;
					case "forest":
						TerrainConfig.rockHighThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockHighThresholdForest", TerrainConfig.rockHighThresholdForest);
						break;
					case "mountains":
						TerrainConfig.rockHighThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockHighThresholdMountain", TerrainConfig.rockHighThresholdMountain);
						break;
					case "plains":
						TerrainConfig.rockHighThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_RockHighThresholdPlains", TerrainConfig.rockHighThresholdPlains);
						break;
					}
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set threshold");
				}
			}

			internal void <AddConsoleCommands>b__33_5(ConsoleEventArgs args)
			{
				if (args.Length == 3)
				{
					switch (Convert.ToString(args[1]))
					{
					case "meadows":
						TerrainConfig.cliffLowThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffLowThreshold", TerrainConfig.cliffLowThreshold);
						break;
					case "forest":
						TerrainConfig.cliffLowThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffLowThresholdForest", TerrainConfig.cliffLowThresholdForest);
						break;
					case "mountains":
						TerrainConfig.cliffLowThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffLowThresholdMountain", TerrainConfig.cliffLowThresholdMountain);
						break;
					case "plains":
						TerrainConfig.cliffLowThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffLowThresholdPlains", TerrainConfig.cliffLowThresholdPlains);
						break;
					}
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set threshold");
				}
			}

			internal void <AddConsoleCommands>b__33_6(ConsoleEventArgs args)
			{
				if (args.Length == 3)
				{
					switch (Convert.ToString(args[1]))
					{
					case "meadows":
						TerrainConfig.cliffHighThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffHighThreshold", TerrainConfig.cliffHighThreshold);
						break;
					case "forest":
						TerrainConfig.cliffHighThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffHighThresholdForest", TerrainConfig.cliffHighThresholdForest);
						break;
					case "mountains":
						TerrainConfig.cliffHighThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffHighThresholdMountain", TerrainConfig.cliffHighThresholdMountain);
						break;
					case "plains":
						TerrainConfig.cliffHighThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
						Shader.SetGlobalFloat("_CliffHighThresholdPlains", TerrainConfig.cliffHighThresholdPlains);
						break;
					}
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set threshold");
				}
			}

			internal void <AddConsoleCommands>b__33_7(ConsoleEventArgs args)
			{
				if (args.Length == 1)
				{
					TerrainConfig.Save(TerrainConfigFile);
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set threshold");
				}
			}

			internal void <AddConsoleCommands>b__33_8(ConsoleEventArgs args)
			{
				if (args.Length == 2)
				{
					TerrainConfig.tilingAmount = int.Parse(args[1]);
					Shader.SetGlobalFloat("_TileAmount", (float)TerrainConfig.tilingAmount);
				}
				else
				{
					MonoBehaviour.print((object)"Not enough arguments to set threshold");
				}
			}
		}

		public static string ConfigPath = Paths.ConfigPath;

		public static string PluginPath = Paths.PluginPath;

		public static string ConfigFile = Path.Combine(ConfigPath, "ValheimHDTerrain.cfg");

		public static string DataPath = Path.Combine(PluginPath, "HDTerrainData");

		public static string TerrainTiles = Path.Combine(DataPath, "Terrain");

		public static string TerrainTilesLod = Path.Combine(DataPath, "TerrainLod");

		public static string AssetBundleFile = Path.Combine(DataPath, "hdterrain");

		public static string TerrainConfigFile = Path.Combine(DataPath, "TerrainConfig.json");

		public static Config Config = new Config();

		public static bool isMaterialChanged = false;

		public static Shader TerrainShader;

		public static bool IsOriginalShaderSaved = false;

		public static bool UseShader = true;

		public static bool ReplaceTextures = true;

		private static bool consoleCommandsAdded = false;

		public static Texture2DArray DiffuseArray = null;

		public static Texture2DArray NormalArray = null;

		public static Texture2DArray DiffuseArrayLod = null;

		public static Texture2DArray NormalArrayLod = null;

		public static Texture2D WaterCaustics = null;

		public static TerrainConfig TerrainConfig = null;

		public static bool ForceUpdateClutter = false;

		public static bool TweaksInstalled = false;

		private static int ArraySize = 17;

		public static void Init()
		{
			LoadConfig();
			LoadShader();
			LoadAdditionalTextures();
			CreateTerrainArrays();
		}

		private static void LoadConfig()
		{
			if (File.Exists(TerrainConfigFile))
			{
				bLog.Log("Loading Terrain Config", extendedlog: true);
				TerrainConfig = TerrainConfig.Load(TerrainConfigFile);
			}
			else
			{
				bLog.Log("Creating Default Config", extendedlog: true);
				TerrainConfig = new TerrainConfig();
			}
		}

		public static void LoadAdditionalTextures()
		{
			WaterCaustics = LoadTexture(Path.Combine(TerrainTiles, "WaterCaustics.png"), linear: false, mipMaps: true);
			WaterCaustics.Apply();
		}

		public static void CreateTerrainArrays()
		{
			bLog.Log("Creating HD Terrain texture arrays");
			for (int i = 0; i < ArraySize; i++)
			{
				Texture2D val = LoadTexture(Path.Combine(TerrainTiles, $"terraintile{i}.png"), linear: false, mipMaps: true);
				Texture2D val2 = LoadTexture(Path.Combine(TerrainTiles, $"terraintilen{i}.png"), linear: true, mipMaps: true);
				Texture2D val3 = null;
				Texture2D val4 = null;
				if (i <= 15)
				{
					val3 = LoadTexture(Path.Combine(TerrainTilesLod, $"terraintile{i}.png"), linear: false, mipMaps: false);
					val4 = LoadTexture(Path.Combine(TerrainTilesLod, $"terraintilen{i}.png"), linear: true, mipMaps: false);
				}
				if (i == 0)
				{
					bLog.Log($"Creating diffuse terrain array with image size {((Texture)val).width}x{((Texture)val).height}", extendedlog: true);
					bLog.Log($"Creating normal terrain array with image size {((Texture)val2).width}x{((Texture)val2).height}", extendedlog: true);
					bLog.Log($"Creating diffuse terrain lod array with image size {((Texture)val3).width}x{((Texture)val3).height}", extendedlog: true);
					bLog.Log($"Creating normal terrain lod array with image size {((Texture)val4).width}x{((Texture)val4).height}", extendedlog: true);
					DiffuseArray = CreateTextureArray(((Texture)val).width, ArraySize, linear: false, mipMaps: true);
					NormalArray = CreateTextureArray(((Texture)val2).width, ArraySize, linear: true, mipMaps: true);
					DiffuseArrayLod = CreateTextureArray(((Texture)val3).width, ArraySize, linear: false, mipMaps: false);
					NormalArrayLod = CreateTextureArray(((Texture)val4).width, ArraySize, linear: true, mipMaps: false);
				}
				if ((Object)(object)DiffuseArray != (Object)null && (Object)(object)NormalArray != (Object)null)
				{
					for (int j = 0; j < ((Texture)val).mipmapCount; j++)
					{
						bLog.Log($"Adding diffuse tile {i} mipmap level {j} image to diffuse terrain array", extendedlog: true);
						Graphics.CopyTexture((Texture)(object)val, 0, j, (Texture)(object)DiffuseArray, i, j);
						bLog.Log($"Adding normal tile {i} mipmap level {j} image to normal terrain array", extendedlog: true);
						Graphics.CopyTexture((Texture)(object)val2, 0, j, (Texture)(object)NormalArray, i, j);
						if (j == 0 && (Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
						{
							bLog.Log($"Adding terrain lod tile {i} to terrain lod array", extendedlog: true);
							Graphics.CopyTexture((Texture)(object)val3, 0, 0, (Texture)(object)DiffuseArrayLod, i, 0);
							bLog.Log($"Adding normal lod tile {i} to normal lod array", extendedlog: true);
							Graphics.CopyTexture((Texture)(object)val4, 0, 0, (Texture)(object)NormalArrayLod, i, 0);
						}
					}
					Object.DestroyImmediate((Object)(object)val);
					Object.DestroyImmediate((Object)(object)val2);
					Object.DestroyImmediate((Object)(object)val3);
					Object.DestroyImmediate((Object)(object)val4);
					continue;
				}
				bLog.Log("Problem creating terrain arrays, HD Terrain will be disabled", extendedlog: true);
				Object.DestroyImmediate((Object)(object)val);
				Object.DestroyImmediate((Object)(object)val2);
				Object.DestroyImmediate((Object)(object)val3);
				Object.DestroyImmediate((Object)(object)val4);
				ReplaceTextures = false;
				return;
			}
			Graphics.CopyTexture((Texture)(object)DiffuseArrayLod, 4, (Texture)(object)DiffuseArrayLod, 2);
			DiffuseArray.Apply(false, true);
			NormalArray.Apply(false, true);
			DiffuseArrayLod.Apply(false, true);
			NormalArrayLod.Apply(false, true);
		}

		private static Texture2D LoadTexture(string path, bool linear, bool mipMaps)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			bLog.Log("Loading texture " + Path.GetFileName(path), extendedlog: true);
			Texture2D val = new Texture2D(4, 4, (TextureFormat)5, mipMaps, linear);
			((Texture)val).filterMode = (FilterMode)2;
			((Texture)val).anisoLevel = 16;
			ImageConversion.LoadImage(val, File.ReadAllBytes(path));
			val.Compress(true);
			return val;
		}

		private static Texture2DArray CreateTextureArray(int imagesize, int arraySize, bool linear, bool mipMaps)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			Texture2DArray val = new Texture2DArray(imagesize, imagesize, arraySize, (TextureFormat)12, mipMaps, linear);
			((Texture)val).wrapMode = (TextureWrapMode)0;
			((Texture)val).filterMode = (FilterMode)2;
			((Texture)val).anisoLevel = 16;
			return val;
		}

		public static void LoadShader()
		{
			if (UseShader)
			{
				AssetBundle val = AssetBundle.LoadFromFile(AssetBundleFile);
				TerrainShader = val.LoadAsset<Shader>("HDTerrain");
				val.Unload(false);
				if ((Object)(object)TerrainShader != (Object)null)
				{
					bLog.Log("Loaded Terrain Shader", extendedlog: true);
				}
				UpdateTerrainShaderValues();
			}
		}

		public static void UpdateTerrainShaderValues()
		{
			Shader.SetGlobalFloat("_RockLowThreshold", TerrainConfig.rockLowThreshold);
			Shader.SetGlobalFloat("_RockHighThreshold", TerrainConfig.rockHighThreshold);
			Shader.SetGlobalFloat("_CliffLowThreshold", TerrainConfig.cliffLowThreshold);
			Shader.SetGlobalFloat("_CliffHighThreshold", TerrainConfig.cliffHighThreshold);
			Shader.SetGlobalFloat("_RockLowThresholdForest", TerrainConfig.rockLowThresholdForest);
			Shader.SetGlobalFloat("_RockHighThresholdForest", TerrainConfig.rockHighThresholdForest);
			Shader.SetGlobalFloat("_CliffLowThresholdForest", TerrainConfig.cliffLowThresholdForest);
			Shader.SetGlobalFloat("_CliffHighThresholdForest", TerrainConfig.cliffHighThresholdForest);
			Shader.SetGlobalFloat("_RockLowThresholdMountain", TerrainConfig.rockLowThresholdMountain);
			Shader.SetGlobalFloat("_RockHighThresholdMountain", TerrainConfig.rockHighThresholdMountain);
			Shader.SetGlobalFloat("_CliffLowThresholdMountain", TerrainConfig.cliffLowThresholdMountain);
			Shader.SetGlobalFloat("_CliffHighThresholdMountain", TerrainConfig.cliffHighThresholdMountain);
			Shader.SetGlobalFloat("_RockLowThresholdPlains", TerrainConfig.rockLowThresholdPlains);
			Shader.SetGlobalFloat("_RockHighThresholdPlains", TerrainConfig.rockHighThresholdPlains);
			Shader.SetGlobalFloat("_CliffLowThresholdPlains", TerrainConfig.cliffLowThresholdPlains);
			Shader.SetGlobalFloat("_CliffHighThresholdPlains", TerrainConfig.cliffHighThresholdPlains);
			Shader.SetGlobalFloat("_TileAmount", (float)TerrainConfig.tilingAmount);
			Shader.SetGlobalFloat("_WaterCausticsEnabled", Config.WaterCausticsEnabled.Value);
		}

		public static void ApplyShader()
		{
			foreach (Heightmap allHeightmap in Heightmap.GetAllHeightmaps())
			{
				if (!allHeightmap.IsDistantLod && (Object)(object)allHeightmap.m_materialInstance != (Object)null)
				{
					bLog.Log("Replacing heightmap shader");
					allHeightmap.m_materialInstance.shader = TerrainShader;
					allHeightmap.Regenerate();
				}
			}
		}

		public static void AddConsoleCommands()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0078: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Expected O, but got Unknown
			object obj = <>c.<>9__33_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 2)
					{
						string text = args[1].ToString();
						string text2 = text.ToLower();
						string text3 = text2;
						if (!(text3 == "enabled"))
						{
							if (text3 == "disabled")
							{
								Config.WaterCausticsEnabled.Value = 0f;
								Shader.SetGlobalFloat("_WaterCausticsEnabled", Config.WaterCausticsEnabled.Value);
							}
						}
						else
						{
							Config.WaterCausticsEnabled.Value = 1f;
							Shader.SetGlobalFloat("_WaterCausticsEnabled", Config.WaterCausticsEnabled.Value);
						}
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set water caustics");
					}
				};
				<>c.<>9__33_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("watercaustics", "Enable / Disable water caustics", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			if (!TweaksInstalled)
			{
				object obj2 = <>c.<>9__33_1;
				if (obj2 == null)
				{
					ConsoleEvent val2 = delegate(ConsoleEventArgs args)
					{
						if (args.Length == 2)
						{
							Config.GrassDrawDistance.Value = float.Parse(args[1], CultureInfo.InvariantCulture);
						}
						else
						{
							MonoBehaviour.print((object)"Not enough arguments to set grass draw distance");
						}
					};
					<>c.<>9__33_1 = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("grassdrawdistance", "Set grass draw distance", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj3 = <>c.<>9__33_2;
				if (obj3 == null)
				{
					ConsoleEvent val3 = delegate(ConsoleEventArgs args)
					{
						if (args.Length == 2)
						{
							Config.GrassAmountModifier.Value = float.Parse(args[1], CultureInfo.InvariantCulture);
							ForceUpdateClutter = true;
						}
						else
						{
							MonoBehaviour.print((object)"Not enough arguments to set grass amount");
						}
					};
					<>c.<>9__33_2 = val3;
					obj3 = (object)val3;
				}
				new ConsoleCommand("grassamount", "Set grass amount", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			}
			if (consoleCommandsAdded || !Config.DeveloperMode.Value)
			{
				return;
			}
			bLog.Log("Adding console commands");
			object obj4 = <>c.<>9__33_3;
			if (obj4 == null)
			{
				ConsoleEvent val4 = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 3)
					{
						switch (Convert.ToString(args[1]))
						{
						case "meadows":
							TerrainConfig.rockLowThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockLowThreshold", TerrainConfig.rockLowThreshold);
							break;
						case "forest":
							TerrainConfig.rockLowThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockLowThresholdForest", TerrainConfig.rockLowThresholdForest);
							break;
						case "mountains":
							TerrainConfig.rockLowThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockLowThresholdMountain", TerrainConfig.rockLowThresholdMountain);
							break;
						case "plains":
							TerrainConfig.rockLowThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockLowThresholdPlains", TerrainConfig.rockLowThresholdPlains);
							break;
						}
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set threshold");
					}
				};
				<>c.<>9__33_3 = val4;
				obj4 = (object)val4;
			}
			new ConsoleCommand("setrocklow", "Set low transition threshold for rock", (ConsoleEvent)obj4, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj5 = <>c.<>9__33_4;
			if (obj5 == null)
			{
				ConsoleEvent val5 = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 3)
					{
						switch (Convert.ToString(args[1]))
						{
						case "meadows":
							TerrainConfig.rockHighThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockHighThreshold", TerrainConfig.rockHighThreshold);
							break;
						case "forest":
							TerrainConfig.rockHighThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockHighThresholdForest", TerrainConfig.rockHighThresholdForest);
							break;
						case "mountains":
							TerrainConfig.rockHighThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockHighThresholdMountain", TerrainConfig.rockHighThresholdMountain);
							break;
						case "plains":
							TerrainConfig.rockHighThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_RockHighThresholdPlains", TerrainConfig.rockHighThresholdPlains);
							break;
						}
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set threshold");
					}
				};
				<>c.<>9__33_4 = val5;
				obj5 = (object)val5;
			}
			new ConsoleCommand("setrockhigh", "Set high transition threshold for rock", (ConsoleEvent)obj5, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj6 = <>c.<>9__33_5;
			if (obj6 == null)
			{
				ConsoleEvent val6 = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 3)
					{
						switch (Convert.ToString(args[1]))
						{
						case "meadows":
							TerrainConfig.cliffLowThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffLowThreshold", TerrainConfig.cliffLowThreshold);
							break;
						case "forest":
							TerrainConfig.cliffLowThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffLowThresholdForest", TerrainConfig.cliffLowThresholdForest);
							break;
						case "mountains":
							TerrainConfig.cliffLowThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffLowThresholdMountain", TerrainConfig.cliffLowThresholdMountain);
							break;
						case "plains":
							TerrainConfig.cliffLowThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffLowThresholdPlains", TerrainConfig.cliffLowThresholdPlains);
							break;
						}
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set threshold");
					}
				};
				<>c.<>9__33_5 = val6;
				obj6 = (object)val6;
			}
			new ConsoleCommand("setclifflow", "Set low transition threshold for cliff", (ConsoleEvent)obj6, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj7 = <>c.<>9__33_6;
			if (obj7 == null)
			{
				ConsoleEvent val7 = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 3)
					{
						switch (Convert.ToString(args[1]))
						{
						case "meadows":
							TerrainConfig.cliffHighThreshold = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffHighThreshold", TerrainConfig.cliffHighThreshold);
							break;
						case "forest":
							TerrainConfig.cliffHighThresholdForest = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffHighThresholdForest", TerrainConfig.cliffHighThresholdForest);
							break;
						case "mountains":
							TerrainConfig.cliffHighThresholdMountain = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffHighThresholdMountain", TerrainConfig.cliffHighThresholdMountain);
							break;
						case "plains":
							TerrainConfig.cliffHighThresholdPlains = float.Parse(args[2], CultureInfo.InvariantCulture);
							Shader.SetGlobalFloat("_CliffHighThresholdPlains", TerrainConfig.cliffHighThresholdPlains);
							break;
						}
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set threshold");
					}
				};
				<>c.<>9__33_6 = val7;
				obj7 = (object)val7;
			}
			new ConsoleCommand("setcliffhigh", "Set high transition threshold for cliff", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj8 = <>c.<>9__33_7;
			if (obj8 == null)
			{
				ConsoleEvent val8 = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 1)
					{
						TerrainConfig.Save(TerrainConfigFile);
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set threshold");
					}
				};
				<>c.<>9__33_7 = val8;
				obj8 = (object)val8;
			}
			new ConsoleCommand("saveterrainconfig", "Save the current terrain config", (ConsoleEvent)obj8, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj9 = <>c.<>9__33_8;
			if (obj9 == null)
			{
				ConsoleEvent val9 = delegate(ConsoleEventArgs args)
				{
					if (args.Length == 2)
					{
						TerrainConfig.tilingAmount = int.Parse(args[1]);
						Shader.SetGlobalFloat("_TileAmount", (float)TerrainConfig.tilingAmount);
					}
					else
					{
						MonoBehaviour.print((object)"Not enough arguments to set threshold");
					}
				};
				<>c.<>9__33_8 = val9;
				obj9 = (object)val9;
			}
			new ConsoleCommand("settilingamount", "Set amount of times each texture tiles in a terrain chunk", (ConsoleEvent)obj9, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
}
namespace ValheimHDTerrain.Logging
{
	internal class bLog
	{
		private static bool extendedDebugEnabled = false;

		private static string logLabel = "HD Terrain";

		public static void Log(string LogMessage, bool extendedlog = false)
		{
			if (extendedlog || extendedDebugEnabled)
			{
				Debug.Log((object)(logLabel + ": " + LogMessage));
			}
		}
	}
}