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";
}
}