Decompiled source of TrollHideRug v1.0.4

TrollHideRug.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[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;
		}
	}
}
namespace TrollHideRug
{
	[BepInPlugin("com.shrimptec.trollhiderug", "Troll Hide Rug", "1.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.shrimptec.trollhiderug";

		public const string PluginName = "Troll Hide Rug";

		public const string PluginVersion = "1.0.4";

		private ConfigEntry<string> basePrefabConfig;

		private ConfigEntry<bool> fillRugConfig;

		private ConfigEntry<bool> crispEdgesConfig;

		private ConfigEntry<bool> shapeFromIconConfig;

		private ConfigEntry<int> costConfig;

		private static readonly Color HideTint = new Color(0.36f, 0.5f, 0.58f);

		private void Awake()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			basePrefabConfig = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BasePrefab", "rug_fur", "Name of the vanilla rug prefab to clone for the Troll Hide Rug (see the 'Vanilla rug prefabs' line in LogOutput.log for options).");
			fillRugConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FillRugWithHide", true, "Stretch the troll hide's outline to fill the whole rug area. If false, the hide keeps its original (smaller) size on the rug.");
			crispEdgesConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CrispEdges", true, "Keep the hide's sharp pixel-edged outline (spike, notches) instead of smoothing it. Set to false to get the previous softer look.");
			shapeFromIconConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShapeFromIcon", true, "Use the outline of the Troll Hide's inventory icon as the rug's shape. Set to false to use the shape cut into the hide texture itself.");
			costConfig = ((BaseUnityPlugin)this).Config.Bind<int>("General", "TrollHideCost", 6, new ConfigDescription("How many Troll Hide the rug costs to build.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			PrefabManager.OnVanillaPrefabsAvailable += AddRug;
		}

		private static Texture2D ReadableCopy(Texture src, int size, bool point)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_006d: Expected O, but got Unknown
			RenderTexture temporary = RenderTexture.GetTemporary(size, size, 0, (RenderTextureFormat)0);
			FilterMode filterMode = src.filterMode;
			if (point)
			{
				src.filterMode = (FilterMode)0;
			}
			Graphics.Blit(src, temporary);
			src.filterMode = filterMode;
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, true);
			val.ReadPixels(new Rect(0f, 0f, (float)size, (float)size), 0, 0);
			val.Apply(true);
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			return val;
		}

		private static Color32[] ReadSpritePixels(Sprite sprite, out int w, out int h)
		{
			//IL_0008: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			Texture2D texture = sprite.texture;
			Rect textureRect = sprite.textureRect;
			w = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			h = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
			FilterMode filterMode = ((Texture)texture).filterMode;
			((Texture)texture).filterMode = (FilterMode)0;
			Graphics.Blit((Texture)(object)texture, temporary);
			((Texture)texture).filterMode = filterMode;
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(w, h, (TextureFormat)4, false);
			val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)w, (float)h), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color32[] pixels = val.GetPixels32();
			Object.Destroy((Object)val);
			return pixels;
		}

		private void ApplyIconShape(Color32[] px, int size, Sprite icon)
		{
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0566: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			int w;
			int h;
			Color32[] array = ReadSpritePixels(icon, out w, out h);
			int num = w;
			int num2 = -1;
			int num3 = h;
			int num4 = -1;
			for (int i = 0; i < h; i++)
			{
				for (int j = 0; j < w; j++)
				{
					if (array[i * w + j].a > 128)
					{
						if (j < num)
						{
							num = j;
						}
						if (j > num2)
						{
							num2 = j;
						}
						if (i < num3)
						{
							num3 = i;
						}
						if (i > num4)
						{
							num4 = i;
						}
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Icon '{((Object)icon).name}' is {w}x{h}px; outline x {num}-{num2}, y {num3}-{num4}");
			bool flag = false;
			for (int k = 0; k < array.Length; k++)
			{
				if (array[k].a < 128)
				{
					flag = true;
					break;
				}
			}
			if (num2 < 0 || !flag)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Icon has no usable transparent outline; keeping the texture's own shape.");
				return;
			}
			int num5 = size * size;
			int[] array2 = new int[4] { 1, -1, 0, 0 };
			int[] array3 = new int[4] { 0, 0, 1, -1 };
			Queue<int> queue = new Queue<int>();
			int[] array4 = new int[num5];
			for (int l = 0; l < num5; l++)
			{
				int num6 = l % size;
				int num7 = l / size;
				bool flag2 = num6 == 0 || num7 == 0 || num6 == size - 1 || num7 == size - 1;
				if (px[l].a < 128 || flag2)
				{
					array4[l] = 0;
					queue.Enqueue(l);
				}
				else
				{
					array4[l] = -1;
				}
			}
			while (queue.Count > 0)
			{
				int num8 = queue.Dequeue();
				int num9 = num8 % size;
				int num10 = num8 / size;
				for (int m = 0; m < 4; m++)
				{
					int num11 = num9 + array2[m];
					int num12 = num10 + array3[m];
					if (num11 >= 0 && num12 >= 0 && num11 < size && num12 < size)
					{
						int num13 = num12 * size + num11;
						if (array4[num13] == -1)
						{
							array4[num13] = array4[num8] + 1;
							queue.Enqueue(num13);
						}
					}
				}
			}
			Color32[] array5 = (Color32[])(object)new Color32[num5];
			bool[] array6 = new bool[num5];
			bool[] array7 = new bool[num5];
			int[] array8 = new int[num5];
			int num14 = 0;
			for (int n = 0; n < num5; n++)
			{
				if (array4[n] > 10)
				{
					array6[n] = true;
					array7[n] = true;
					array8[n] = n;
					array5[n] = px[n];
					queue.Enqueue(n);
					num14++;
				}
			}
			if (num14 == 0)
			{
				for (int num15 = 0; num15 < num5; num15++)
				{
					if (px[num15].a >= 128)
					{
						array6[num15] = true;
						array7[num15] = true;
						array8[num15] = num15;
						array5[num15] = px[num15];
						queue.Enqueue(num15);
						num14++;
					}
				}
			}
			if (num14 == 0)
			{
				for (int num16 = 0; num16 < num5; num16++)
				{
					array5[num16] = new Color32((byte)60, (byte)110, (byte)190, byte.MaxValue);
				}
			}
			while (queue.Count > 0)
			{
				int num17 = queue.Dequeue();
				int num18 = num17 % size;
				int num19 = num17 / size;
				for (int num20 = 0; num20 < 4; num20++)
				{
					int num21 = num18 + array2[num20];
					int num22 = num19 + array3[num20];
					if (num21 >= 0 && num22 >= 0 && num21 < size && num22 < size)
					{
						int num23 = num22 * size + num21;
						if (!array6[num23])
						{
							array6[num23] = true;
							array5[num23] = array5[num17];
							array8[num23] = array8[num17];
							queue.Enqueue(num23);
						}
					}
				}
			}
			float[] array9 = new float[3] { 1f, 0.5f, 0.25f };
			for (int num24 = 0; num24 < num5; num24++)
			{
				if (array7[num24])
				{
					continue;
				}
				int num25 = array8[num24];
				int num26 = num25 % size;
				int num27 = num25 / size;
				int num28 = num24 % size;
				int num29 = num24 / size;
				float[] array10 = array9;
				foreach (float num31 in array10)
				{
					int num32 = Mathf.RoundToInt((float)num26 + (float)(num26 - num28) * num31);
					int num33 = Mathf.RoundToInt((float)num27 + (float)(num27 - num29) * num31);
					if (num32 >= 0 && num33 >= 0 && num32 < size && num33 < size)
					{
						int num34 = num33 * size + num32;
						if (array7[num34])
						{
							array5[num24] = px[num34];
							break;
						}
					}
				}
			}
			for (int num35 = 0; num35 < size; num35++)
			{
				for (int num36 = 0; num36 < size; num36++)
				{
					float num37 = ((float)num36 + 0.5f) / (float)size;
					float num38 = ((float)num35 + 0.5f) / (float)size;
					int num39 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Lerp((float)num, (float)(num2 + 1), num37)), 0, w - 1);
					int num40 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Lerp((float)num3, (float)(num4 + 1), num38)), 0, h - 1);
					bool flag3 = array[num40 * w + num39].a > 128;
					int num41 = num35 * size + num36;
					px[num41] = new Color32(array5[num41].r, array5[num41].g, array5[num41].b, (byte)(flag3 ? 255u : 0u));
				}
			}
		}

		private Texture2D MakeFilledHide(Texture src, Sprite shapeIcon)
		{
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			bool value = crispEdgesConfig.Value;
			Texture2D val = ReadableCopy(src, 512, value);
			Color32[] pixels = val.GetPixels32();
			int num = 512;
			int num2 = -1;
			int num3 = 512;
			int num4 = -1;
			for (int i = 0; i < 512; i++)
			{
				for (int j = 0; j < 512; j++)
				{
					if (pixels[i * 512 + j].a > 128)
					{
						if (j < num)
						{
							num = j;
						}
						if (j > num2)
						{
							num2 = j;
						}
						if (i < num3)
						{
							num3 = i;
						}
						if (i > num4)
						{
							num4 = i;
						}
					}
				}
			}
			if (num2 < 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Hide texture has no opaque pixels; leaving it unchanged.");
				return val;
			}
			float num5 = (float)num / 512f;
			float num6 = (float)(num2 + 1) / 512f;
			float num7 = (float)num3 / 512f;
			float num8 = (float)(num4 + 1) / 512f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)($"Hide outline in texture: x {num}-{num2}, y {num3}-{num4} " + $"(width {num2 - num + 1}px, height {num4 - num3 + 1}px of {512}px)"));
			Color32[] array = (Color32[])(object)new Color32[262144];
			for (int k = 0; k < 512; k++)
			{
				for (int l = 0; l < 512; l++)
				{
					float num9 = ((float)l + 0.5f) / 512f;
					float num10 = ((float)k + 0.5f) / 512f;
					if (value)
					{
						int num11 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Lerp((float)num, (float)(num2 + 1), num9)), 0, 511);
						int num12 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Lerp((float)num3, (float)(num4 + 1), num10)), 0, 511);
						array[k * 512 + l] = pixels[num12 * 512 + num11];
					}
					else
					{
						array[k * 512 + l] = Color32.op_Implicit(val.GetPixelBilinear(Mathf.Lerp(num5, num6, num9), Mathf.Lerp(num7, num8, num10)));
					}
				}
			}
			if ((Object)(object)shapeIcon != (Object)null)
			{
				ApplyIconShape(array, 512, shapeIcon);
			}
			Texture2D val2 = new Texture2D(512, 512, (TextureFormat)4, !value);
			if (value)
			{
				((Texture)val2).filterMode = (FilterMode)0;
				((Texture)val2).wrapMode = (TextureWrapMode)1;
			}
			val2.SetPixels32(array);
			val2.Apply(!value);
			((Object)val2).name = "trollhide_filled";
			Object.Destroy((Object)(object)val);
			return val2;
		}

		private void AddRug()
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			PrefabManager.OnVanillaPrefabsAvailable -= AddRug;
			IOrderedEnumerable<string> values = from n in Cache.GetPrefabs(typeof(GameObject)).Keys
				where n.ToLower().Contains("rug")
				orderby n
				select n;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Vanilla rug prefabs: " + string.Join(", ", values)));
			string value = basePrefabConfig.Value;
			if ((Object)(object)PrefabManager.Instance.GetPrefab(value) == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Base prefab '" + value + "' not found. Pick the right name from the list above and update BasePrefab."));
				return;
			}
			PieceConfig val = new PieceConfig();
			val.Name = "Troll Hide Rug";
			val.Description = "A heavy rug stitched from troll hide.";
			val.PieceTable = PieceTables.Hammer;
			val.Category = PieceCategories.Furniture;
			val.CraftingStation = CraftingStations.Workbench;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig("TrollHide", costConfig.Value, 0, true)
			};
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece("piece_trollhide_rug", value, val2);
			PieceManager.Instance.AddPiece(val3);
			GameObject prefab = PrefabManager.Instance.GetPrefab("TrollHide");
			ItemDrop val4 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null);
			Sprite[] array = (((Object)(object)val4 != (Object)null) ? val4.m_itemData.m_shared.m_icons : null);
			if (array != null && array.Length != 0)
			{
				val3.Piece.m_icon = array[0];
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find the Troll Hide icon; the rug keeps the lox rug icon.");
			}
			Renderer[] componentsInChildren = val3.PiecePrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren)
			{
				Mesh val6 = null;
				SkinnedMeshRenderer val7 = (SkinnedMeshRenderer)(object)((val5 is SkinnedMeshRenderer) ? val5 : null);
				if (val7 != null)
				{
					val6 = val7.sharedMesh;
				}
				else
				{
					MeshFilter component = ((Component)val5).GetComponent<MeshFilter>();
					if ((Object)(object)component != (Object)null)
					{
						val6 = component.sharedMesh;
					}
				}
				ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
				string[] obj = new string[8]
				{
					"[rug dump] renderer '",
					((Object)((Component)val5).gameObject).name,
					"' mesh='",
					((Object)(object)val6 != (Object)null) ? ((Object)val6).name : "none",
					"' bounds=",
					null,
					null,
					null
				};
				object obj2;
				if (!((Object)(object)val6 != (Object)null))
				{
					obj2 = "n/a";
				}
				else
				{
					Bounds bounds = val6.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					obj2 = ((Vector3)(ref size)).ToString("F2");
				}
				obj[5] = (string)obj2;
				obj[6] = " ";
				obj[7] = string.Format("material='{0}' enabled={1}", ((Object)(object)val5.sharedMaterial != (Object)null) ? ((Object)val5.sharedMaterial).name : "none", val5.enabled);
				logger.LogInfo((object)string.Concat(obj));
			}
			Texture hideTex = null;
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("TrollHide");
			if ((Object)(object)prefab2 != (Object)null)
			{
				MeshRenderer[] componentsInChildren2 = prefab2.GetComponentsInChildren<MeshRenderer>(true);
				for (int num = 0; num < componentsInChildren2.Length; num++)
				{
					Material sharedMaterial = ((Renderer)componentsInChildren2[num]).sharedMaterial;
					if ((Object)(object)hideTex == (Object)null && (Object)(object)sharedMaterial != (Object)null && (Object)(object)sharedMaterial.mainTexture != (Object)null)
					{
						hideTex = sharedMaterial.mainTexture;
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Troll hide texture: " + (((Object)(object)hideTex != (Object)null) ? ((Object)hideTex).name : "NOT FOUND (using flat colour)")));
			if ((Object)(object)hideTex != (Object)null && fillRugConfig.Value)
			{
				hideTex = (Texture)(object)MakeFilledHide(hideTex, (shapeFromIconConfig.Value && array != null && array.Length != 0) ? array[0] : null);
			}
			componentsInChildren = val3.PiecePrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val8 in componentsInChildren)
			{
				if (val8.sharedMaterials.Any((Material m) => (Object)(object)m != (Object)null && ((Object)m).name.Contains("_l2")))
				{
					val8.enabled = false;
					continue;
				}
				Material[] sharedMaterials = ((IEnumerable<Material>)val8.sharedMaterials).Select((Func<Material, Material>)delegate(Material m)
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0012: Expected O, but got Unknown
					//IL_003e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0037: Unknown result type (might be due to invalid IL or missing references)
					if ((Object)(object)m == (Object)null)
					{
						return (Material)null;
					}
					Material val9 = new Material(m);
					val9.SetTexture("_MainTex", hideTex);
					val9.SetColor("_Color", ((Object)(object)hideTex != (Object)null) ? Color.white : HideTint);
					string[] array2 = new string[5] { "_BumpMap", "_NormalMap", "_MetallicGlossMap", "_ParallaxMap", "_HeightMap" };
					foreach (string text in array2)
					{
						if (val9.HasProperty(text))
						{
							val9.SetTexture(text, (Texture)null);
						}
					}
					return val9;
				}).ToArray();
				val8.sharedMaterials = sharedMaterials;
			}
		}
	}
}