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 list = new List(); 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 Created = new List(); 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(); } } }