Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TrollHideRug v1.0.4
TrollHideRug.dll
Decompiled 2 weeks agousing 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; } } } }