Decompiled source of ChestLootSigns v0.1.0

plugins/ChestLootSigns/ChestLootSigns.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Blackforge.Hot;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 Blackforge
{
	public static class Chests
	{
		private struct Face
		{
			public Vector3 center;

			public Vector3 normal;

			public float width;

			public float height;
		}

		private class Entry
		{
			public Container chest;

			public Action changed;

			public Face[] faces;

			public GameObject sign;

			public string shown = "";
		}

		private const string Sign = "bf_loot";

		private const string Wagon = "bf_wagon";

		private const string Measured = "bf_chests_measured";

		private static readonly string[] Built = new string[4] { "piece_chest_wood", "piece_chest", "piece_chest_blackmetal", "piece_chest_private" };

		private static readonly Face[] WagonFaces = WagonWalls();

		private static HotHost host;

		private static readonly List<Entry> entries = new List<Entry>();

		private static readonly Dictionary<string, Face[]> layouts = new Dictionary<string, Face[]>();

		private static bool failed;

		private const float SignHeight = 0.6f;

		private const float SignMiddle = 0.42f;

		private const float Fill = 0.9f;

		private const float Off = 0.01f;

		public static void Load(HotHost from)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			host = from;
			host.Harmony.Patch((MethodBase)AccessTools.Method(typeof(Container), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Chests), "Seen", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				Seen(array[i]);
			}
		}

		public static void Unload()
		{
			foreach (Entry entry in entries)
			{
				if ((Object)(object)entry.chest != (Object)null && entry.chest.GetInventory() != null)
				{
					Inventory inventory = entry.chest.GetInventory();
					inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, entry.changed);
				}
				if ((Object)(object)entry.sign != (Object)null)
				{
					Object.Destroy((Object)(object)entry.sign);
				}
			}
			entries.Clear();
			layouts.Clear();
			failed = false;
			host = null;
		}

		private static void Seen(Container __instance)
		{
			if (host == null || (Object)(object)__instance == (Object)null || __instance.GetInventory() == null)
			{
				return;
			}
			string text = ((Object)((Component)__instance).gameObject).name.Split('(')[0].Trim();
			if (text != "bf_wagon" && !Built.Contains(text))
			{
				return;
			}
			entries.RemoveAll((Entry old) => (Object)(object)old.chest == (Object)null);
			if (entries.Any((Entry old) => (Object)(object)old.chest == (Object)(object)__instance))
			{
				return;
			}
			try
			{
				if (!layouts.TryGetValue(text, out var value))
				{
					value = ((text == "bf_wagon") ? WagonFaces : Fit(__instance, text));
					layouts[text] = value;
				}
				if (value.Length != 0)
				{
					Entry entry = new Entry
					{
						chest = __instance,
						faces = value
					};
					entry.changed = delegate
					{
						Draw(entry);
					};
					Inventory inventory = __instance.GetInventory();
					inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, entry.changed);
					entries.Add(entry);
					Draw(entry);
				}
			}
			catch (Exception error)
			{
				Warn(error);
			}
		}

		private static void Draw(Entry entry)
		{
			//IL_0185: 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_0196: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			if (host == null || (Object)(object)entry.chest == (Object)null)
			{
				return;
			}
			try
			{
				List<ItemData> list = (from val5 in entry.chest.GetInventory().GetAllItems()
					where val5.m_shared.m_icons != null && val5.m_shared.m_icons.Length != 0
					group val5 by val5.m_shared.m_name into @group
					orderby @group.Count() descending, @group.Key
					select @group.First()).ToList();
				string text = string.Join("|", list.Select((ItemData val5) => $"{val5.m_shared.m_name}:{val5.m_variant}"));
				if (text == entry.shown && ((Object)(object)entry.sign != (Object)null || list.Count == 0))
				{
					return;
				}
				entry.shown = text;
				if ((Object)(object)entry.sign != (Object)null)
				{
					Object.Destroy((Object)(object)entry.sign);
					entry.sign = null;
				}
				if (list.Count == 0)
				{
					return;
				}
				int layer = ((Component)entry.chest).gameObject.layer;
				entry.sign = new GameObject("bf_loot")
				{
					layer = layer
				};
				entry.sign.transform.SetParent(((Component)entry.chest).transform, false);
				Face[] faces = entry.faces;
				Vector3 val2 = default(Vector3);
				for (int num = 0; num < faces.Length; num++)
				{
					Face face = faces[num];
					GameObject val = new GameObject("face")
					{
						layer = layer
					};
					val.transform.SetParent(entry.sign.transform, false);
					val.transform.localPosition = face.center;
					val.transform.localRotation = Quaternion.LookRotation(-face.normal, Vector3.up);
					(int columns, int rows, float cell) tuple = Grid(list.Count, face.width, face.height);
					int item = tuple.columns;
					int item2 = tuple.rows;
					float item3 = tuple.cell;
					for (int num2 = 0; num2 < list.Count; num2++)
					{
						Sprite icon = list[num2].GetIcon();
						if (!((Object)(object)icon == (Object)null))
						{
							Bounds bounds = icon.bounds;
							Vector3 size = ((Bounds)(ref bounds)).size;
							float num3 = item3 * 0.92f / Mathf.Max(new float[3] { size.x, size.y, 0.001f });
							((Vector3)(ref val2))..ctor(((float)(num2 % item) - (float)(item - 1) / 2f) * item3, ((float)(item2 - 1) / 2f - (float)(num2 / item)) * item3, 0f);
							GameObject val3 = new GameObject("icon")
							{
								layer = layer
							};
							val3.transform.SetParent(val.transform, false);
							Transform transform = val3.transform;
							Vector3 val4 = val2;
							bounds = icon.bounds;
							transform.localPosition = val4 - ((Bounds)(ref bounds)).center * num3;
							val3.transform.localScale = new Vector3(num3, num3, 1f);
							val3.AddComponent<SpriteRenderer>().sprite = icon;
						}
					}
				}
			}
			catch (Exception error)
			{
				Warn(error);
			}
		}

		private static (int columns, int rows, float cell) Grid(int count, float width, float height)
		{
			(int, int, float) result = (1, count, 0f);
			for (int i = 1; i <= count; i++)
			{
				int num = (count + i - 1) / i;
				float num2 = Mathf.Min(width / (float)i, height / (float)num);
				if (num2 > result.Item3)
				{
					result = (i, num, num2);
				}
			}
			return result;
		}

		private static Face[] Fit(Container chest, string prefab)
		{
			//IL_0022: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: 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)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			Bounds box;
			string parts;
			bool flag = Measure(chest, out box, out parts);
			Tell($"{prefab} at {((Component)chest).transform.position}, scale {((Component)chest).transform.lossyScale}, box {((Bounds)(ref box)).size}, parts: {parts}");
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			Container val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<Container>(true) : null);
			if ((Object)(object)val2 != (Object)null && Measure(val2, out var box2, out var parts2))
			{
				Tell($"{prefab} as the game has it, box {((Bounds)(ref box2)).size}, parts: {parts2}");
				box = box2;
				flag = true;
			}
			if (!flag || ((Bounds)(ref box)).size.y < 0.05f)
			{
				host.Log.LogWarning((object)("chests: " + prefab + " has no model to measure, it gets no loot sign"));
				return new Face[0];
			}
			float height = ((Bounds)(ref box)).size.y * 0.6f;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(((Bounds)(ref box)).center.x, ((Bounds)(ref box)).min.y + ((Bounds)(ref box)).size.y * 0.42f, ((Bounds)(ref box)).center.z);
			host.Log.LogInfo((object)$"chests: the loot sign of {prefab} hangs on a box of {((Bounds)(ref box)).size.x:0.00} by {((Bounds)(ref box)).size.z:0.00} by {((Bounds)(ref box)).size.y:0.00} m");
			return new Face[2]
			{
				new Face
				{
					center = val3 + Vector3.right * (((Bounds)(ref box)).extents.x + 0.01f),
					normal = Vector3.right,
					width = ((Bounds)(ref box)).size.z * 0.9f,
					height = height
				},
				new Face
				{
					center = val3 + Vector3.left * (((Bounds)(ref box)).extents.x + 0.01f),
					normal = Vector3.left,
					width = ((Bounds)(ref box)).size.z * 0.9f,
					height = height
				}
			};
		}

		private static bool Measure(Container chest, out Bounds box, out string parts)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: 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)
			Transform transform = ((Component)chest).transform;
			box = default(Bounds);
			bool flag = false;
			List<string> list = new List<string>();
			MeshFilter[] componentsInChildren = ((Component)transform).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				string text = (((Object)(object)val.sharedMesh == (Object)null) ? "no mesh" : (((Object)(object)((Component)val).GetComponent<MeshRenderer>() == (Object)null) ? "no renderer" : (((Object)val).name.Contains("snow") ? "snow" : (((Object)(object)chest.m_open != (Object)null && ((Component)val).transform.IsChildOf(chest.m_open.transform)) ? "open lid" : null))));
				Bounds val2 = default(Bounds);
				if ((Object)(object)val.sharedMesh != (Object)null)
				{
					Matrix4x4 val3 = transform.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
					Bounds bounds = val.sharedMesh.bounds;
					for (int j = 0; j < 8; j++)
					{
						Vector3 val4 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f)));
						if (j == 0)
						{
							((Bounds)(ref val2))..ctor(val4, Vector3.zero);
						}
						((Bounds)(ref val2)).Encapsulate(val4);
						if (text == null)
						{
							if (!flag)
							{
								box = new Bounds(val4, Vector3.zero);
								flag = true;
							}
							((Bounds)(ref box)).Encapsulate(val4);
						}
					}
				}
				list.Add(string.Format("{0}/{1} {2} {3}", ((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Object)((Component)val).transform.parent).name : "", ((Object)val).name, ((Bounds)(ref val2)).size, text ?? "counted"));
			}
			parts = string.Join("; ", list);
			return flag;
		}

		private static void Tell(string text)
		{
			host.Log.LogInfo((object)("chests: measured " + text));
		}

		private static Face[] WagonWalls()
		{
			//IL_003a: 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_0046: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			List<Face> list = new List<Face>();
			int[] array = new int[2] { -1, 1 };
			foreach (int num in array)
			{
				list.Add(new Face
				{
					center = new Vector3((float)num * 0.935f, 1.66f, 1.1f),
					normal = Vector3.right * (float)num,
					width = 0.62f,
					height = 0.68f
				});
			}
			return list.ToArray();
		}

		private static void Warn(Exception error)
		{
			if (!failed && host != null)
			{
				failed = true;
				host.Log.LogWarning((object)$"chests: a loot sign failed, said only once: {error}");
			}
		}
	}
	[BepInPlugin("vladasz.chestlootsigns", "Chest Loot Signs", "0.1.0")]
	public class ChestLootSignsPlugin : BaseUnityPlugin
	{
		public const string Id = "vladasz.chestlootsigns";

		public const string Number = "0.1.0";

		private void Awake()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			HotHost hotHost = new HotHost(((BaseUnityPlugin)this).Logger, new Harmony("vladasz.chestlootsigns"), "0.1.0");
			if (!hotHost.IsDedicatedServer)
			{
				Chests.Load(hotHost);
			}
		}
	}
}
namespace Blackforge.Hot
{
	public sealed class HotHost
	{
		public ManualLogSource Log { get; }

		public Harmony Harmony { get; }

		public string Version { get; }

		public bool IsDedicatedServer => (int)SystemInfo.graphicsDeviceType == 4;

		internal HotHost(ManualLogSource log, Harmony harmony, string version)
		{
			Log = log;
			Harmony = harmony;
			Version = version;
		}

		public byte[] ReadAsset(string relative)
		{
			return File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(typeof(HotHost).Assembly.Location), relative));
		}

		public void UnregisterRpc(IEnumerable<string> names)
		{
			if (ZRoutedRpc.instance == null)
			{
				return;
			}
			foreach (string name in names)
			{
				ZRoutedRpc.instance.m_functions.Remove(StringExtensionMethods.GetStableHashCode(name));
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}