Decompiled source of PrideTerrain v1.0.0

BepInEx/plugins/PrideTerrain/PrideTerrain.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("coruscnium")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Replaces terrain textures with randomly assigned pride flags")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0")]
[assembly: AssemblyProduct("PrideTerrain")]
[assembly: AssemblyTitle("PrideTerrain")]
[assembly: AssemblyVersion("1.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;
		}
	}
}
namespace PrideTerrain
{
	internal static class FlagLibrary
	{
		private static readonly string[] SupportedExtensions = new string[3] { ".png", ".jpg", ".jpeg" };

		private static string[] _paths = new string[0];

		private static Texture2D[] _textures = (Texture2D[])(object)new Texture2D[0];

		public static int Count => _paths.Length;

		private static string FlagFolder
		{
			get
			{
				string location = Assembly.GetExecutingAssembly().Location;
				if (!string.IsNullOrEmpty(location))
				{
					return Path.Combine(Path.GetDirectoryName(location), "flags");
				}
				return null;
			}
		}

		public static void Scan()
		{
			string flagFolder = FlagFolder;
			List<string> list = new List<string>();
			try
			{
				if (Directory.Exists(flagFolder))
				{
					string[] files = Directory.GetFiles(flagFolder);
					foreach (string text in files)
					{
						if (Array.IndexOf(SupportedExtensions, Path.GetExtension(text).ToLowerInvariant()) >= 0)
						{
							list.Add(text);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Could not read '" + flagFolder + "': " + ex.Message));
			}
			list.Sort(StringComparer.OrdinalIgnoreCase);
			_paths = list.ToArray();
			_textures = (Texture2D[])(object)new Texture2D[_paths.Length];
			if (_paths.Length == 0)
			{
				Plugin.Logger.LogWarning((object)("No flag images found in '" + flagFolder + "' — the terrain is left alone."));
			}
		}

		public static int IndexFor(int key)
		{
			if (_paths.Length == 0)
			{
				return -1;
			}
			return (int)((uint)(key * -1640531535) % (uint)_paths.Length);
		}

		public static string NameAt(int index)
		{
			if (index >= 0 && index < _paths.Length)
			{
				return Path.GetFileNameWithoutExtension(_paths[index]);
			}
			return "?";
		}

		public static Texture2D Get(int index)
		{
			if (index < 0 || index >= _paths.Length)
			{
				return null;
			}
			Texture2D val = _textures[index];
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			_textures[index] = Load(_paths[index]);
			return _textures[index];
		}

		private static Texture2D Load(string path)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			try
			{
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
				if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
				{
					Plugin.Logger.LogWarning((object)("Could not decode '" + Path.GetFileName(path) + "' as an image."));
					Object.Destroy((Object)(object)val);
					return null;
				}
				((Texture)val).wrapMode = (TextureWrapMode)0;
				((Texture)val).filterMode = (FilterMode)1;
				((Object)val).hideFlags = (HideFlags)61;
				((Object)val).name = "PrideTerrain:" + Path.GetFileNameWithoutExtension(path);
				return val;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Could not load '" + path + "': " + ex.Message));
				return null;
			}
		}
	}
	[MycoMod(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("coruscnium.prideterrain", "PrideTerrain", "1.0.0.0")]
	[BepInProcess("Mycopunk.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "coruscnium.prideterrain";

		public const string PluginName = "PrideTerrain";

		public const string PluginVersion = "1.0.0.0";

		internal static ManualLogSource Logger;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			FlagLibrary.Scan();
			_harmony = new Harmony("coruscnium.prideterrain");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			Logger.LogInfo((object)string.Format("{0} loaded with {1} flag(s).", "PrideTerrain", FlagLibrary.Count));
		}

		private void OnDestroy()
		{
			TerrainPainter.ReleaseCreated();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(TerrainGenerator), "OnTextureBundleLoaded")]
	internal static class TerrainTextureBundlePatch
	{
		[HarmonyPostfix]
		private static void Postfix(TerrainGenerator __instance)
		{
			TerrainPainter.Paint(__instance);
		}
	}
	internal static class TerrainPainter
	{
		private struct TextureParams
		{
			public float TintR;

			public float TintG;

			public float TintB;

			public float SpecR;

			public float SpecG;

			public float SpecB;

			public float SpecA;

			public float ShadowTint;

			public float Smoothness;

			public float Tiling;

			public float HeightX;

			public float HeightY;

			public float HeightZ;

			public float BlendX;

			public float BlendY;

			public float BlendZ;
		}

		private const int LayerSize = 512;

		private const byte SpecularAlpha = 0;

		private const int ParamSlots = 8;

		private static readonly FieldInfo TextureParamBufferField = AccessTools.Field(typeof(TerrainGenerator), "textureParamBuffer");

		private static readonly FieldInfo CurrentSeedField = AccessTools.Field(typeof(TerrainGenerator), "currentSeed");

		private static readonly MethodInfo GetTextureSetMethod = AccessTools.Method(typeof(TerrainGenerator), "GetTextureSet", (Type[])null, (Type[])null);

		private static readonly List<Texture2DArray> Created = new List<Texture2DArray>();

		private static bool _loggedPaintError;

		public static void Paint(TerrainGenerator generator)
		{
			try
			{
				Material val = default(Material);
				if ((Object)(object)generator == (Object)null || FlagLibrary.Count == 0 || !generator.HasMaterialInstance(ref val) || (Object)(object)val == (Object)null)
				{
					return;
				}
				Texture texture = val.GetTexture("_BaseTextures");
				Texture2DArray val2 = (Texture2DArray)(object)((texture is Texture2DArray) ? texture : null);
				int num = (((Object)(object)val2 != (Object)null) ? val2.depth : 8);
				if (num > 0)
				{
					uint seed = ((CurrentSeedField != null) ? ((uint)CurrentSeedField.GetValue(null)) : 0u);
					string chosen;
					Texture2DArray val3 = BuildArray(num, seed, out chosen);
					if (!((Object)(object)val3 == (Object)null))
					{
						val.SetTexture("_BaseTextures", (Texture)(object)val3);
						Created.Add(val3);
						NeutraliseTints(generator, val);
						Plugin.Logger.LogInfo((object)$"[terrain] Repainted {num} layer(s) with: {chosen}");
					}
				}
			}
			catch (Exception arg)
			{
				if (!_loggedPaintError)
				{
					_loggedPaintError = true;
					Plugin.Logger.LogError((object)$"Failed to repaint the terrain: {arg}");
				}
			}
		}

		private static Texture2DArray BuildArray(int layers, uint seed, out string chosen)
		{
			//IL_001a: 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_0026: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			Random random = new Random((int)seed);
			StringBuilder stringBuilder = new StringBuilder();
			Texture2DArray val = new Texture2DArray(512, 512, layers, (TextureFormat)4, true)
			{
				wrapMode = (TextureWrapMode)0,
				filterMode = (FilterMode)1,
				hideFlags = (HideFlags)61,
				name = "PrideTerrain:BaseTextures"
			};
			for (int i = 0; i < layers; i++)
			{
				int index = random.Next(FlagLibrary.Count);
				Texture2D val2 = FlagLibrary.Get(index);
				if ((Object)(object)val2 == (Object)null)
				{
					Object.Destroy((Object)(object)val);
					chosen = null;
					return null;
				}
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(FlagLibrary.NameAt(index));
				val.SetPixels32(Resample(val2), i);
			}
			val.Apply(true, true);
			chosen = stringBuilder.ToString();
			return val;
		}

		private static Color32[] Resample(Texture2D source)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			Color32[] pixels = source.GetPixels32();
			int width = ((Texture)source).width;
			int height = ((Texture)source).height;
			Color32[] array = (Color32[])(object)new Color32[262144];
			for (int i = 0; i < 512; i++)
			{
				float num = ((float)i + 0.5f) / 512f * (float)height - 0.5f;
				int num2 = Mathf.Clamp(Mathf.FloorToInt(num), 0, height - 1);
				int num3 = Mathf.Min(num2 + 1, height - 1);
				float fy = Mathf.Clamp01(num - (float)num2);
				for (int j = 0; j < 512; j++)
				{
					float num4 = ((float)j + 0.5f) / 512f * (float)width - 0.5f;
					int num5 = Mathf.Clamp(Mathf.FloorToInt(num4), 0, width - 1);
					int num6 = Mathf.Min(num5 + 1, width - 1);
					float fx = Mathf.Clamp01(num4 - (float)num5);
					Color32 val = pixels[num2 * width + num5];
					Color32 val2 = pixels[num2 * width + num6];
					Color32 val3 = pixels[num3 * width + num5];
					Color32 val4 = pixels[num3 * width + num6];
					array[i * 512 + j] = new Color32(Lerp2(val.r, val2.r, val3.r, val4.r, fx, fy), Lerp2(val.g, val2.g, val3.g, val4.g, fx, fy), Lerp2(val.b, val2.b, val3.b, val4.b, fx, fy), (byte)0);
				}
			}
			return array;
		}

		private static byte Lerp2(byte a, byte b, byte c, byte d, float fx, float fy)
		{
			float num = (float)(int)a + (float)(b - a) * fx;
			float num2 = (float)(int)c + (float)(d - c) * fx;
			return (byte)Mathf.Clamp(num + (num2 - num) * fy + 0.5f, 0f, 255f);
		}

		private static void NeutraliseTints(TerrainGenerator generator, Material material)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (TextureParamBufferField == null || GetTextureSetMethod == null)
			{
				return;
			}
			object? value = TextureParamBufferField.GetValue(generator);
			GraphicsBuffer val = (GraphicsBuffer)((value is GraphicsBuffer) ? value : null);
			if (val == null || !val.IsValid() || !(GetTextureSetMethod.Invoke(generator, null) is TerrainTextureSet val2))
			{
				return;
			}
			TerrainTexture[] textures = val2.Textures;
			if (textures == null || textures.Length == 0)
			{
				return;
			}
			TextureParams[] array = new TextureParams[8];
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < 8; i++)
			{
				TerrainTexture val3 = textures[Mathf.Min(i, textures.Length - 1)];
				if (i < textures.Length)
				{
					if (i > 0)
					{
						stringBuilder.Append(", ");
					}
					stringBuilder.Append($"{val3.Tint.r:0.00}/{val3.Tint.g:0.00}/{val3.Tint.b:0.00}");
				}
				array[i] = new TextureParams
				{
					TintR = 1f,
					TintG = 1f,
					TintB = 1f,
					SpecR = val3.SpecularColor.r,
					SpecG = val3.SpecularColor.g,
					SpecB = val3.SpecularColor.b,
					SpecA = val3.SpecularColor.a,
					ShadowTint = val3.ShadowColor,
					Smoothness = val3.Smoothness,
					Tiling = val3.Tile,
					HeightX = val3.HeightAdjust.x,
					HeightY = val3.HeightAdjust.y,
					HeightZ = val3.HeightAdjust.z,
					BlendX = val3.Blending.x,
					BlendY = val3.Blending.y,
					BlendZ = val3.Blending.z
				};
			}
			val.SetData((Array)array);
			material.SetBuffer("_TextureParamBuffer", val);
			Plugin.Logger.LogInfo((object)$"[terrain] Tints neutralised. Originals were: {stringBuilder}");
		}

		public static void ReleaseCreated()
		{
			foreach (Texture2DArray item in Created)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
			Created.Clear();
		}
	}
}