Decompiled source of HighlightBoxPlaces v1.0.0

HighlightBoxPlaces.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HighlightPlus;
using Microsoft.CodeAnalysis;
using Mirror;
using StarterAssets;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("SMT.DevSandbox")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HighlightBoxPlaces")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9296540545de439a0d6d0e6ad4aee895f7ecb89b")]
[assembly: AssemblyProduct("Highlightes all places where the product currently will be stored")]
[assembly: AssemblyTitle("HighlightBoxPlaces")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 HighlightBoxPlaces
{
	[BepInPlugin("HighlightBoxPlaces", "HighlightBoxPlaces", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class OwnedHighlight
		{
			internal Transform Target;

			internal HighlightEffect Effect;

			internal Outline UiEffect;

			internal int RendererHash;

			internal Color Color;
		}

		private readonly Dictionary<int, OwnedHighlight> owned = new Dictionary<int, OwnedHighlight>();

		private readonly Dictionary<int, Color> wanted = new Dictionary<int, Color>();

		private readonly Dictionary<int, Transform> targets = new Dictionary<int, Transform>();

		private readonly List<Data_Container> shelves = new List<Data_Container>();

		private readonly List<Data_Container> storage = new List<Data_Container>();

		private readonly List<int> obsolete = new List<int>();

		private ConfigEntry<bool> featureEnabled;

		private ConfigEntry<bool> showStorage;

		private ConfigEntry<bool> throughWalls;

		private ConfigEntry<float> refreshInterval;

		private ConfigEntry<Color> emptyColor;

		private ConfigEntry<Color> partialColor;

		private ConfigEntry<Color> fullColor;

		private ConfigEntry<Color> storageColor;

		private int product = -1;

		private float nextRefresh;

		private float nextIndex;

		internal int OwnedSignCount
		{
			get
			{
				int num = 0;
				foreach (OwnedHighlight value in owned.Values)
				{
					if (Object.op_Implicit((Object)(object)value.UiEffect))
					{
						num++;
					}
				}
				return num;
			}
		}

		private void Awake()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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)
			featureEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show matching locations for the box in your hands.");
			showStorage = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Storage", true, "Show matching storage boxes and reserved storage slots.");
			throughWalls = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Through Walls", true, "Show outlines through walls and other shelves.");
			refreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Refresh Interval", 0.25f, new ConfigDescription("Seconds between stock and outline updates.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
			emptyColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Empty", new Color(1f, 0.25f, 0.2f), "An assigned shelf row has no stock.");
			partialColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Needs Stock", new Color(1f, 0.75f, 0.15f), "A matching shelf row has room for more stock.");
			fullColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Full", new Color(0.2f, 0.9f, 0.4f), "Matching shelf rows are full.");
			storageColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Storage", new Color(0.15f, 0.65f, 1f), "A storage box or reserved storage slot matches.");
			SceneManager.sceneLoaded += SceneLoaded;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"HighlightBoxPlaces loaded. Outlines use this player's held product and local stock data.");
		}

		private void Update()
		{
			PlayerNetwork val = (Object.op_Implicit((Object)(object)NetworkClient.localPlayer) ? ((Component)NetworkClient.localPlayer).GetComponent<PlayerNetwork>() : null);
			if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)FirstPersonController.Instance))
			{
				val = ((Component)FirstPersonController.Instance).GetComponent<PlayerNetwork>();
			}
			bool flag = Object.op_Implicit((Object)(object)FirstPersonController.Instance) && FirstPersonController.Instance.allowPlayerInput;
			int num = ((featureEnabled.Value && flag && Object.op_Implicit((Object)(object)val) && ((NetworkBehaviour)val).isLocalPlayer && val.equippedItem == 1) ? val.extraParameter1 : (-1));
			if (!Object.op_Implicit((Object)(object)ProductListing.Instance) || num < 0 || num >= ProductListing.Instance.productsData.Length)
			{
				num = -1;
			}
			if (num != product)
			{
				Clear();
				product = num;
				nextRefresh = 0f;
			}
			if (product >= 0 && !(Time.unscaledTime < nextRefresh))
			{
				nextRefresh = Time.unscaledTime + refreshInterval.Value;
				RefreshForProduct(product);
			}
		}

		internal void RefreshForProduct(int productId)
		{
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ProductListing.Instance) || productId < 0 || productId >= ProductListing.Instance.productsData.Length)
			{
				Clear();
				return;
			}
			if (Time.unscaledTime >= nextIndex)
			{
				nextIndex = Time.unscaledTime + 1f;
				Reindex(shelves, "Level_SupermarketProps/Shelves");
				Reindex(storage, "Level_SupermarketProps/StorageShelves");
			}
			wanted.Clear();
			targets.Clear();
			ProductData val = ProductListing.Instance.productsData[productId];
			foreach (Data_Container shelf in shelves)
			{
				if (!Object.op_Implicit((Object)(object)shelf) || !((Component)shelf).gameObject.activeInHierarchy || shelf.productInfoArray == null)
				{
					continue;
				}
				int num = StockRules.Capacity(shelf.shelfLength, shelf.shelfWidth, shelf.shelfHeight, val.colliderSize.x, val.colliderSize.y, val.colliderSize.z, val.isStackable);
				if (num <= 0 || shelf.containerClass != val.productContainerClass || (shelf.isVolumeRestricted && val.colliderSize.x * val.colliderSize.y * val.colliderSize.z < shelf.productVolumeLimit))
				{
					continue;
				}
				Transform val2 = ((Component)shelf).transform.Find("Labels");
				int num2 = 0;
				int num3 = 0;
				bool flag = false;
				for (int i = 0; i + 1 < shelf.productInfoArray.Length; i += 2)
				{
					if (shelf.productInfoArray[i] == productId)
					{
						int num4 = Mathf.Max(0, shelf.productInfoArray[i + 1]);
						num2++;
						num3 += num4;
						flag = flag || num4 < num;
						if (Object.op_Implicit((Object)(object)val2) && i / 2 < val2.childCount)
						{
							Want(val2.GetChild(i / 2), ColorFor(StockRules.State(num4, num)));
						}
					}
				}
				if (num2 > 0)
				{
					Want(((Component)shelf).transform, ColorFor((num3 != 0) ? (flag ? FillState.Partial : FillState.Full) : FillState.Empty));
				}
			}
			if (showStorage.Value)
			{
				foreach (Data_Container item in storage)
				{
					if (!Object.op_Implicit((Object)(object)item) || !((Component)item).gameObject.activeInHierarchy || item.productInfoArray == null)
					{
						continue;
					}
					Transform val3 = ((Component)item).transform.Find("BoxContainer");
					Transform val4 = ((Component)item).transform.Find("CanvasSigns");
					bool flag2 = false;
					for (int j = 0; j + 1 < item.productInfoArray.Length; j += 2)
					{
						if (item.productInfoArray[j] == productId)
						{
							flag2 = true;
							int num5 = j / 2;
							if (Object.op_Implicit((Object)(object)val3) && num5 < val3.childCount)
							{
								Want(val3.GetChild(num5), storageColor.Value);
							}
							if (Object.op_Implicit((Object)(object)val4) && num5 < val4.childCount && ((Component)val4.GetChild(num5)).gameObject.activeInHierarchy)
							{
								Want(val4.GetChild(num5), storageColor.Value);
							}
						}
					}
					if (flag2)
					{
						Want(((Component)item).transform, storageColor.Value);
					}
				}
			}
			Apply();
		}

		private static void Reindex(List<Data_Container> destination, string path)
		{
			destination.Clear();
			GameObject val = GameObject.Find(path);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			for (int i = 0; i < val.transform.childCount; i++)
			{
				Data_Container component = ((Component)val.transform.GetChild(i)).GetComponent<Data_Container>();
				if (Object.op_Implicit((Object)(object)component))
				{
					destination.Add(component);
				}
			}
		}

		private Color ColorFor(FillState state)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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)
			return (Color)(state switch
			{
				FillState.Full => fullColor.Value, 
				FillState.Empty => emptyColor.Value, 
				_ => partialColor.Value, 
			});
		}

		private void Want(Transform target, Color color)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)target))
			{
				int instanceID = ((Object)target).GetInstanceID();
				targets[instanceID] = target;
				wanted[instanceID] = color;
			}
		}

		private void Apply()
		{
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: 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_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			obsolete.Clear();
			foreach (KeyValuePair<int, OwnedHighlight> item in owned)
			{
				if (!wanted.ContainsKey(item.Key) || !Object.op_Implicit((Object)(object)item.Value.Target) || (!Object.op_Implicit((Object)(object)item.Value.Effect) && !Object.op_Implicit((Object)(object)item.Value.UiEffect)))
				{
					obsolete.Add(item.Key);
				}
			}
			foreach (int item2 in obsolete)
			{
				Remove(item2);
			}
			foreach (KeyValuePair<int, Color> item3 in wanted)
			{
				Transform val = targets[item3.Key];
				Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>();
				if (componentsInChildren.Length == 0)
				{
					if (Object.op_Implicit((Object)(object)((Component)val).GetComponent<Graphic>()))
					{
						if (!owned.TryGetValue(item3.Key, out var value))
						{
							value = new OwnedHighlight
							{
								Target = val,
								UiEffect = ((Component)val).gameObject.AddComponent<Outline>()
							};
							((Shadow)value.UiEffect).effectDistance = new Vector2(2f, -2f);
							owned.Add(item3.Key, value);
						}
						((Shadow)value.UiEffect).effectColor = item3.Value;
					}
					else if (owned.ContainsKey(item3.Key))
					{
						Remove(item3.Key);
					}
					continue;
				}
				int num = 17;
				Renderer[] array = componentsInChildren;
				foreach (Renderer val2 in array)
				{
					num = num * 31 + ((Object)val2).GetInstanceID();
				}
				bool flag = false;
				if (!owned.TryGetValue(item3.Key, out var value2))
				{
					GameObject val3 = new GameObject("HighlightBoxPlaces Outline");
					val3.transform.SetParent(((Component)this).transform, false);
					HighlightEffect val4 = val3.AddComponent<HighlightEffect>();
					val4.fadeInDuration = 0f;
					val4.fadeOutDuration = 0f;
					val4.outline = 1f;
					val4.glow = 0f;
					val4.outlineIndependent = true;
					val4.outlineQuality = (QualityLevel)3;
					value2 = new OwnedHighlight
					{
						Target = val,
						Effect = val4
					};
					owned.Add(item3.Key, value2);
					flag = true;
				}
				Visibility val5 = (Visibility)(throughWalls.Value ? 1 : 0);
				bool flag2 = flag || value2.Color != item3.Value || value2.Effect.outlineVisibility != val5;
				if (flag || value2.RendererHash != num)
				{
					value2.Effect.SetTargets(val, componentsInChildren);
					value2.RendererHash = num;
					flag2 = true;
				}
				if (flag2)
				{
					value2.Color = item3.Value;
					value2.Effect.outlineColor = item3.Value;
					value2.Effect.outlineVisibility = val5;
					value2.Effect.UpdateMaterialProperties();
				}
				value2.Effect.highlighted = true;
			}
		}

		private void Remove(int id)
		{
			OwnedHighlight ownedHighlight = owned[id];
			if (Object.op_Implicit((Object)(object)ownedHighlight.Effect))
			{
				ownedHighlight.Effect.highlighted = false;
				((Behaviour)ownedHighlight.Effect).enabled = false;
				Object.Destroy((Object)(object)((Component)ownedHighlight.Effect).gameObject);
			}
			if (Object.op_Implicit((Object)(object)ownedHighlight.UiEffect))
			{
				((Behaviour)ownedHighlight.UiEffect).enabled = false;
				Object.Destroy((Object)(object)ownedHighlight.UiEffect);
			}
			owned.Remove(id);
		}

		internal void Clear()
		{
			obsolete.Clear();
			obsolete.AddRange(owned.Keys);
			foreach (int item in obsolete)
			{
				Remove(item);
			}
		}

		private void SceneLoaded(Scene scene, LoadSceneMode mode)
		{
			Clear();
			shelves.Clear();
			storage.Clear();
			nextIndex = (nextRefresh = 0f);
			product = -1;
		}

		private void OnDisable()
		{
			Clear();
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= SceneLoaded;
			Clear();
		}
	}
	internal enum FillState
	{
		Empty,
		Partial,
		Full
	}
	internal static class StockRules
	{
		internal static int Capacity(float length, float width, float height, float x, float y, float z, bool stackable)
		{
			if (!Valid(length) || !Valid(width) || !Valid(height) || !Valid(x) || !Valid(y) || !Valid(z))
			{
				return 0;
			}
			return Axis(length, x) * Axis(width, z) * ((!stackable) ? 1 : Axis(height, y));
		}

		private static bool Valid(float value)
		{
			if (value > 0f && !float.IsInfinity(value))
			{
				return !float.IsNaN(value);
			}
			return false;
		}

		private static int Axis(float size, float product)
		{
			return Math.Max(1, Math.Min(100, (int)Math.Floor(size / (product * 1.1f))));
		}

		internal static FillState State(int quantity, int capacity)
		{
			if (quantity > 0)
			{
				if (quantity < capacity)
				{
					return FillState.Partial;
				}
				return FillState.Full;
			}
			return FillState.Empty;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "HighlightBoxPlaces";

		public const string PLUGIN_NAME = "Highlightes all places where the product currently will be stored";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}