Decompiled source of LynxShredder v1.0.1

plugins/LynxShredder.dll

Decompiled 25 minutes ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace LynxShredder;

internal static class Access
{
	internal static readonly Func<Container, long, bool> ContainerCheckAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null), (object)null, true);

	internal static readonly Func<PrivateArea, bool> WardEnabled = AccessTools.MethodDelegate<Func<PrivateArea, bool>>(AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null), (object)null, true);

	internal static readonly Func<PrivateArea, Vector3, float, bool> WardInside = AccessTools.MethodDelegate<Func<PrivateArea, Vector3, float, bool>>(AccessTools.Method(typeof(PrivateArea), "IsInside", new Type[2]
	{
		typeof(Vector3),
		typeof(float)
	}, (Type[])null), (object)null, true);

	internal static readonly Func<PrivateArea, long, bool> WardPermitted = AccessTools.MethodDelegate<Func<PrivateArea, long, bool>>(AccessTools.Method(typeof(PrivateArea), "IsPermitted", new Type[1] { typeof(long) }, (Type[])null), (object)null, true);

	private static readonly FieldInfo AllAreasField = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

	internal static List<PrivateArea> AllWards()
	{
		return AllAreasField?.GetValue(null) as List<PrivateArea>;
	}
}
internal static class Cfg
{
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class NewConnectionPatch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			if (!__instance.IsServer())
			{
				peer.m_rpc.Register<ZPackage>("LynxShredder_Config", (Action<ZRpc, ZPackage>)RPC_Config);
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	private static class PeerInfoPatch
	{
		private static void Postfix(ZNet __instance, ZRpc rpc)
		{
			if (!__instance.IsServer() || rpc == null)
			{
				return;
			}
			try
			{
				rpc.Invoke("LynxShredder_Config", new object[1] { Pack() });
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not send config to peer: " + ex.Message));
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	private static class ShutdownPatch
	{
		private static void Postfix()
		{
			_server = null;
			_hadServerValues = false;
		}
	}

	private const string RpcName = "LynxShredder_Config";

	private static ConfigEntry<string> _buildCost;

	private static ConfigEntry<string> _station;

	private static ConfigEntry<string> _category;

	private static ConfigEntry<float> _interval;

	private static ConfigEntry<float> _defaultRadius;

	private static ConfigEntry<float> _maxRadius;

	private static ConfigEntry<float> _standaloneShare;

	private static ConfigEntry<string> _biomeOverrides;

	private static ConfigEntry<bool> _verbose;

	private static ConfigEntry<float> _iconPitch;

	private static ConfigEntry<float> _iconYaw;

	private static Dictionary<string, string> _server;

	private static bool _hadServerValues;

	internal static string BuildCost => Get((ConfigEntryBase)(object)_buildCost);

	internal static string Station => Get((ConfigEntryBase)(object)_station);

	internal static string Category => Get((ConfigEntryBase)(object)_category);

	internal static float Interval => Math.Max(1f, GetF((ConfigEntryBase)(object)_interval, 5f));

	internal static float MaxRadius => Math.Max(2f, GetF((ConfigEntryBase)(object)_maxRadius, 20f));

	internal static float DefaultRadius => Math.Min(MaxRadius, Math.Max(2f, GetF((ConfigEntryBase)(object)_defaultRadius, 10f)));

	internal static float StandaloneShare => Math.Max(0f, Math.Min(1f, GetF((ConfigEntryBase)(object)_standaloneShare, 0.4f)));

	internal static string BiomeOverrides => Get((ConfigEntryBase)(object)_biomeOverrides);

	internal static bool Verbose => _verbose.Value;

	internal static float IconPitch => _iconPitch.Value;

	internal static float IconYaw => _iconYaw.Value;

	internal static bool FromServer => _server != null;

	internal static event Action Changed;

	internal static void Bind(ConfigFile c)
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Expected O, but got Unknown
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Expected O, but got Unknown
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Expected O, but got Unknown
		_buildCost = c.Bind<string>("Piece", "BuildCost", "FineWood:10,Iron:6,SurtlingCore:1", "Build cost as PrefabName:Amount pairs, comma separated. Server-enforced.");
		_station = c.Bind<string>("Piece", "CraftingStation", "forge", "Prefab name of the station needed nearby to build it (empty = none). Server-enforced.");
		_category = c.Bind<string>("Piece", "BuildTab", "LynxStations", "Hammer tab. Any name makes (or joins) a custom tab via Jotunn, e.g. LynxStations; a vanilla category name (Misc, Crafting, Furniture, ...) uses that one. Server-enforced.");
		_interval = c.Bind<float>("Work", "SecondsPerItem", 5f, new ConfigDescription("Seconds between shredded items.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
		_defaultRadius = c.Bind<float>("Work", "DefaultRadius", 10f, new ConfigDescription("Work radius of a newly built Shredder (m).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
		_maxRadius = c.Bind<float>("Work", "MaxRadius", 20f, new ConfigDescription("Largest radius players can pick in the settings window (m).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
		_standaloneShare = c.Bind<float>("Salvage", "ReturnShareWithoutPoV", 0.4f, new ConfigDescription("Share of materials returned when Path of Valheiman is NOT installed (0.4 = 40%). With PoV installed, PoV's own salvage share and the stamped player's bonuses are used instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		_biomeOverrides = c.Bind<string>("Salvage", "BiomeOverrides", "", "Extra biome assignments, comma separated: Name=Biome. Name is an item prefab (e.g. SwordBronze) or a material prefab (e.g. SomeModIngot). Biome: Meadows, BlackForest, Swamp, Mountain, Plains, Mistlands, Ashlands, DeepNorth, Ocean (counts as Swamp), or Never (never shred). Item entries beat material entries.");
		_verbose = c.Bind<bool>("Debug", "VerboseLog", false, "Log every container/item decision (local only).");
		_iconPitch = c.Bind<float>("Icon", "Pitch", 25f, "Build-menu icon: how far the camera looks down on the Shredder (degrees). Local only; restart to apply.");
		_iconYaw = c.Bind<float>("Icon", "Yaw", 30f, "Build-menu icon: which side the camera looks from (degrees). Local only; restart to apply. The console command lynxshredder_icon saves renders every 45 degrees to compare.");
		c.SettingChanged += delegate
		{
			Cfg.Changed?.Invoke();
		};
	}

	private static string Get(ConfigEntryBase e)
	{
		if (_server != null && _server.TryGetValue(e.Definition.Key, out var value))
		{
			return value;
		}
		return e.GetSerializedValue();
	}

	private static float GetF(ConfigEntryBase e, float fallback)
	{
		if (!float.TryParse(Get(e), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return fallback;
		}
		return result;
	}

	private static IEnumerable<ConfigEntryBase> Synced()
	{
		yield return (ConfigEntryBase)(object)_buildCost;
		yield return (ConfigEntryBase)(object)_station;
		yield return (ConfigEntryBase)(object)_category;
		yield return (ConfigEntryBase)(object)_interval;
		yield return (ConfigEntryBase)(object)_defaultRadius;
		yield return (ConfigEntryBase)(object)_maxRadius;
		yield return (ConfigEntryBase)(object)_standaloneShare;
		yield return (ConfigEntryBase)(object)_biomeOverrides;
	}

	private static ZPackage Pack()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		ZPackage val = new ZPackage();
		List<ConfigEntryBase> list = new List<ConfigEntryBase>(Synced());
		val.Write(list.Count);
		foreach (ConfigEntryBase item in list)
		{
			val.Write(item.Definition.Key);
			val.Write(item.GetSerializedValue());
		}
		return val;
	}

	internal static int PushToPeers()
	{
		Cfg.Changed?.Invoke();
		ZNet instance = ZNet.instance;
		if ((Object)(object)instance == (Object)null || !instance.IsServer())
		{
			return -1;
		}
		int num = 0;
		foreach (ZNetPeer peer in instance.GetPeers())
		{
			if (peer?.m_rpc != null)
			{
				try
				{
					peer.m_rpc.Invoke("LynxShredder_Config", new object[1] { Pack() });
					num++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Could not send config to a player: " + ex.Message));
				}
			}
		}
		return num;
	}

	private static void RPC_Config(ZRpc rpc, ZPackage p)
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer())
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			int num = p.ReadInt();
			for (int i = 0; i < num; i++)
			{
				dictionary[p.ReadString()] = p.ReadString();
			}
			_server = dictionary;
			Plugin.Log.LogInfo((object)$"Using the server's LynxShredder settings ({num} values)");
			if ((Object)(object)Player.m_localPlayer != (Object)null && _hadServerValues)
			{
				((Character)Player.m_localPlayer).Message((MessageType)1, "Shredder settings updated by the server", 0, (Sprite)null, false);
			}
			_hadServerValues = true;
			Cfg.Changed?.Invoke();
		}
	}
}
internal static class Compat
{
	internal const string PovGuid = "treextr.pathofvalheiman";

	internal const string KvistGuid = "com.ryan.greydwarfsorter";

	internal const string DrawersGuid = "com.rossdwest.itemdrawers";

	private static MethodInfo _tunableOf;

	private static MethodInfo _classOf;

	private static MethodInfo _returnChance;

	private static FieldInfo _classes;

	private static MethodInfo _rarityOf;

	private static MethodInfo _sockets;

	private static MethodInfo _isIdentified;

	private static PropertyInfo _socketSigil;

	private static Type _sorterStation;

	private static MethodInfo _chestIndexChanged;

	private static Type _drawerComponent;

	internal static readonly int KvistLabel = StringExtensionMethods.GetStableHashCode("gs_label");

	internal const string KvistSortMe = "sort_me";

	private static readonly HashSet<string> _warned = new HashSet<string>();

	internal static bool Pov { get; private set; }

	internal static bool Kvist { get; private set; }

	internal static bool Drawers { get; private set; }

	internal static bool PovProtectionBroken
	{
		get
		{
			if (Pov)
			{
				if (!(_rarityOf == null) && !(_sockets == null) && !(_socketSigil == null))
				{
					return _isIdentified == null;
				}
				return true;
			}
			return false;
		}
	}

	internal static void Detect()
	{
		Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
		Pov = pluginInfos.ContainsKey("treextr.pathofvalheiman");
		Kvist = pluginInfos.ContainsKey("com.ryan.greydwarfsorter");
		Drawers = pluginInfos.ContainsKey("com.rossdwest.itemdrawers");
		if (Pov)
		{
			SetupPov(((object)pluginInfos["treextr.pathofvalheiman"].Instance)?.GetType().Assembly);
		}
		if (Kvist)
		{
			SetupKvist(((object)pluginInfos["com.ryan.greydwarfsorter"].Instance)?.GetType().Assembly);
		}
		if (Drawers)
		{
			_drawerComponent = (((object)pluginInfos["com.rossdwest.itemdrawers"].Instance)?.GetType().Assembly)?.GetType("ItemDrawers.Game.DrawerComponent");
			Plugin.Log.LogInfo((object)((_drawerComponent != null) ? "ItemDrawers found: drawers are never shredded from" : "ItemDrawers found but DrawerComponent not located (not applied); drawers are still skipped by name"));
		}
		Plugin.Log.LogInfo((object)("Optional mods: PoV=" + (Pov ? "yes" : "no") + ", Kvist=" + (Kvist ? "yes" : "no") + ", ItemDrawers=" + (Drawers ? "yes" : "no")));
	}

	private static void SetupPov(Assembly asm)
	{
		if (asm == null)
		{
			Plugin.Log.LogWarning((object)"PoV assembly not found (PoV features not applied)");
			Pov = false;
			return;
		}
		Type? type = asm.GetType("PassiveTree.Tunables");
		Type type2 = asm.GetType("PassiveTree.CraftSalvage");
		Type type3 = asm.GetType("Valheiman.Api.Items");
		Type type4 = asm.GetType("Valheiman.Api.SocketInfo");
		_tunableOf = type?.GetMethod("Of", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
		_classOf = type2?.GetMethod("ClassOf", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
		_returnChance = type2?.GetMethod("ReturnChance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
		_classes = type2?.GetField("classes", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		_rarityOf = type3?.GetMethod("RarityOf", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
		_sockets = type3?.GetMethod("Sockets", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
		_isIdentified = type3?.GetMethod("IsIdentified", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
		_socketSigil = type4?.GetProperty("Sigil");
		Report("PoV salvage share (Tunables.Of)", _tunableOf);
		Report("PoV salvage bonus (CraftSalvage.ReturnChance/ClassOf)", (_returnChance != null && _classOf != null && _classes != null) ? ((object)1) : null);
		Report("PoV rarity protection (Api.Items.RarityOf)", _rarityOf);
		Report("PoV socket protection (Api.Items.Sockets)", (_sockets != null && _socketSigil != null) ? ((object)1) : null);
		Report("PoV identify protection (Api.Items.IsIdentified)", _isIdentified);
	}

	private static void Report(string what, object found)
	{
		if (found != null)
		{
			Plugin.Log.LogInfo((object)(what + ": applied"));
		}
		else
		{
			Plugin.Log.LogWarning((object)(what + ": NOT applied (PoV changed?) - using safe fallback"));
		}
	}

	private static void SetupKvist(Assembly asm)
	{
		_sorterStation = asm?.GetType("GreydwarfSorter.SorterStation") ?? asm?.GetType("GreydwarfSorter.Pieces.SorterStation");
		if (_sorterStation == null && asm != null)
		{
			foreach (Type item in SafeTypes(asm))
			{
				if (item.Name == "SorterStation")
				{
					_sorterStation = item;
					break;
				}
			}
		}
		_chestIndexChanged = (asm?.GetType("GreydwarfSorter.Chests.ChestIndex"))?.GetMethod("Changed", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
		Plugin.Log.LogInfo((object)("Kvist found: nest detection " + ((_sorterStation != null) ? "applied" : "NOT applied") + ", auto 'sort me' label " + ((_chestIndexChanged != null) ? "applied" : "applied (no index refresh)")));
	}

	private static IEnumerable<Type> SafeTypes(Assembly asm)
	{
		try
		{
			return asm.GetTypes();
		}
		catch (ReflectionTypeLoadException ex)
		{
			return Array.FindAll(ex.Types, (Type t) => t != null);
		}
	}

	internal static float Share()
	{
		if (!Pov)
		{
			return Cfg.StandaloneShare;
		}
		if (_tunableOf != null)
		{
			try
			{
				return Mathf.Clamp01((float)_tunableOf.Invoke(null, new object[1] { "salvage.share" }));
			}
			catch (Exception ex)
			{
				WarnOnce("share", "PoV salvage share lookup failed (using 0.2): " + ex.Message);
			}
		}
		return 0.2f;
	}

	internal static int MaterialClass(string materialPrefab)
	{
		if (!Pov || _classOf == null)
		{
			return 0;
		}
		try
		{
			return Convert.ToInt32(_classOf.Invoke(null, new object[1] { materialPrefab }));
		}
		catch
		{
			return 0;
		}
	}

	internal static float[] LocalBonusChances()
	{
		float[] array = new float[5];
		if (!Pov || _returnChance == null || _classes == null)
		{
			return array;
		}
		try
		{
			if (!(_classes.GetValue(null) is IDictionary dictionary))
			{
				return array;
			}
			foreach (DictionaryEntry item in dictionary)
			{
				int num = Convert.ToInt32(item.Value);
				if (num > 0 && num < array.Length && !(array[num] > 0f))
				{
					array[num] = Mathf.Clamp01((float)_returnChance.Invoke(null, new object[1] { (string)item.Key }));
				}
			}
		}
		catch (Exception ex)
		{
			WarnOnce("bonus", "PoV bonus lookup failed (no bonus stamped): " + ex.Message);
		}
		return array;
	}

	internal static int Rarity(ItemData item)
	{
		if (!Pov || _rarityOf == null)
		{
			return -1;
		}
		try
		{
			return Convert.ToInt32(_rarityOf.Invoke(null, new object[1] { item }));
		}
		catch
		{
			return -1;
		}
	}

	internal static bool HasFilledSocket(ItemData item)
	{
		if (!Pov || _sockets == null || _socketSigil == null)
		{
			return false;
		}
		try
		{
			if (!(_sockets.Invoke(null, new object[1] { item }) is IEnumerable enumerable))
			{
				return false;
			}
			foreach (object item2 in enumerable)
			{
				if (item2 != null && !string.IsNullOrEmpty(_socketSigil.GetValue(item2) as string))
				{
					return true;
				}
			}
		}
		catch
		{
			return true;
		}
		return false;
	}

	internal static bool IsUnidentified(ItemData item)
	{
		if (!Pov || _isIdentified == null)
		{
			return false;
		}
		try
		{
			return !(bool)_isIdentified.Invoke(null, new object[1] { item });
		}
		catch
		{
			return true;
		}
	}

	internal static bool IsKvistNest(GameObject go)
	{
		if (!Kvist || (Object)(object)go == (Object)null)
		{
			return false;
		}
		if (_sorterStation != null && (Object)(object)go.GetComponentInParent(_sorterStation) != (Object)null)
		{
			return true;
		}
		return false;
	}

	internal static void KvistIndexChanged()
	{
		if (_chestIndexChanged == null)
		{
			return;
		}
		try
		{
			_chestIndexChanged.Invoke(null, null);
		}
		catch
		{
		}
	}

	internal static bool IsDrawer(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return false;
		}
		if (_drawerComponent != null && (Object)(object)go.GetComponentInParent(_drawerComponent) != (Object)null)
		{
			return true;
		}
		MonoBehaviour[] componentsInParent = go.GetComponentsInParent<MonoBehaviour>(true);
		foreach (MonoBehaviour val in componentsInParent)
		{
			if ((Object)(object)val != (Object)null && ((object)val).GetType().FullName == "ItemDrawers.Game.DrawerComponent")
			{
				return true;
			}
		}
		return false;
	}

	internal static void WarnOnce(string key, string msg)
	{
		if (_warned.Add(key))
		{
			Plugin.Log.LogWarning((object)msg);
		}
	}
}
internal class ConfigWatcher : MonoBehaviour
{
	private FileSystemWatcher _watcher;

	private volatile bool _dirty;

	private float _settleUntil;

	private string _lastText;

	internal static void Start(Plugin plugin)
	{
		((Component)plugin).gameObject.AddComponent<ConfigWatcher>();
	}

	private void Awake()
	{
		string configFilePath = ((BaseUnityPlugin)Plugin.Instance).Config.ConfigFilePath;
		try
		{
			_lastText = (File.Exists(configFilePath) ? File.ReadAllText(configFilePath) : null);
			_watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath))
			{
				NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime)
			};
			FileSystemEventHandler value = delegate
			{
				_dirty = true;
			};
			_watcher.Changed += value;
			_watcher.Created += value;
			_watcher.Renamed += delegate
			{
				_dirty = true;
			};
			_watcher.EnableRaisingEvents = true;
			Plugin.Log.LogInfo((object)("Config reload: watching " + configFilePath + " for edits"));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Config reload unavailable (restart to apply config edits): " + ex.Message));
		}
	}

	private void Update()
	{
		if (_dirty)
		{
			_dirty = false;
			_settleUntil = Time.realtimeSinceStartup + 1f;
		}
		else if (!(_settleUntil <= 0f) && !(Time.realtimeSinceStartup < _settleUntil))
		{
			_settleUntil = 0f;
			Reload();
		}
	}

	private void Reload()
	{
		ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
		try
		{
			string text = File.ReadAllText(config.ConfigFilePath);
			if (text == _lastText)
			{
				return;
			}
			_lastText = text;
			config.Reload();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Config reload failed: " + ex.Message));
			return;
		}
		int num = Cfg.PushToPeers();
		Plugin.Log.LogInfo((object)((num >= 0) ? $"Config reloaded from disk; sent to {num} connected player(s)" : "Config reloaded from disk"));
	}

	private void OnDestroy()
	{
		if (_watcher != null)
		{
			_watcher.EnableRaisingEvents = false;
			_watcher.Dispose();
		}
	}
}
internal class DumpCommand : ConsoleCommand
{
	public override string Name => "lynxshredder_dump";

	public override string Help => "LynxShredder: log the nearest Shredder's parts and state to LogOutput.log";

	internal static void Register()
	{
		try
		{
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DumpCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new IconCommand());
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("dump command not registered: " + ex.Message));
		}
	}

	public override void Run(string[] args)
	{
		//IL_009a: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: 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)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		Player p = Player.m_localPlayer;
		if ((Object)(object)p == (Object)null)
		{
			Plugin.Log.LogInfo((object)"dump: no player");
			return;
		}
		ShredderPiece shredderPiece = (from x in ShredderPiece.All
			where (Object)(object)x != (Object)null
			orderby Vector3.Distance(((Component)x).transform.position, ((Component)p).transform.position)
			select x).FirstOrDefault();
		if ((Object)(object)shredderPiece == (Object)null)
		{
			Plugin.Log.LogInfo((object)"dump: no Shredder loaded");
			return;
		}
		Transform transform = ((Component)shredderPiece).transform;
		Plugin.Log.LogInfo((object)($"dump: Shredder at {transform.position} rot {transform.eulerAngles} scale {transform.lossyScale}, " + $"owner={shredderPiece.NView.IsOwner()}, status={shredderPiece.CurrentStatus}, shredded={shredderPiece.ShreddedCount}, settings: radius {shredderPiece.ReadSettings().Radius:0}"));
		Renderer[] componentsInChildren = ((Component)transform).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			Bounds bounds = val.bounds;
			ManualLogSource log = Plugin.Log;
			string text = $"  {Path(((Component)val).transform, transform)} active={((Component)val).gameObject.activeInHierarchy} enabled={val.enabled} ";
			object[] obj = new object[5]
			{
				((Bounds)(ref bounds)).center - transform.position,
				((Bounds)(ref bounds)).size,
				((Component)val).transform.eulerAngles,
				null,
				null
			};
			Material sharedMaterial = val.sharedMaterial;
			obj[3] = ((sharedMaterial != null) ? ((Object)sharedMaterial).name : null);
			Material sharedMaterial2 = val.sharedMaterial;
			object obj2;
			if (sharedMaterial2 == null)
			{
				obj2 = null;
			}
			else
			{
				Shader shader = sharedMaterial2.shader;
				obj2 = ((shader != null) ? ((Object)shader).name : null);
			}
			obj[4] = obj2;
			log.LogInfo((object)(text + string.Format("center={0} size={1} rot={2} mat={3}/{4}", obj)));
		}
		CircleProjector[] array = Object.FindObjectsByType<CircleProjector>((FindObjectsSortMode)0);
		foreach (CircleProjector val2 in array)
		{
			if (Vector3.Distance(((Component)val2).transform.position, transform.position) < 40f)
			{
				Plugin.Log.LogInfo((object)$"  CircleProjector '{Path(((Component)val2).transform, null)}' at {((Component)val2).transform.position - transform.position} radius {val2.m_radius}");
			}
		}
		RadiusRing[] array2 = Object.FindObjectsByType<RadiusRing>((FindObjectsSortMode)0);
		foreach (RadiusRing radiusRing in array2)
		{
			Plugin.Log.LogInfo((object)$"  RadiusRing at {((Component)radiusRing).transform.position - transform.position} radius {radiusRing.Radius}");
		}
		((Character)p).Message((MessageType)1, "Shredder dump written to the log", 0, (Sprite)null, false);
	}

	private static string Path(Transform t, Transform root)
	{
		List<string> list = new List<string>();
		Transform val = t;
		while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
		{
			list.Insert(0, ((Object)val).name);
			val = val.parent;
		}
		return string.Join("/", list);
	}
}
internal class IconCommand : ConsoleCommand
{
	public override string Name => "lynxshredder_icon";

	public override string Help => "LynxShredder: save Shredder renders from 8 angles (optional size, default 512) to BepInEx/config/LynxShredder_icons";

	public override void Run(string[] args)
	{
		int size = 512;
		if (args.Length != 0 && int.TryParse(args[0], out var result))
		{
			size = Mathf.Clamp(result, 64, 2048);
		}
		string text = IconMaker.RenderSet(Registration.Prefab, size);
		Plugin.Log.LogInfo((object)("lynxshredder_icon: " + text));
		Player localPlayer = Player.m_localPlayer;
		if (localPlayer != null)
		{
			((Character)localPlayer).Message((MessageType)1, "Shredder icons: " + text, 0, (Sprite)null, false);
		}
	}
}
[HarmonyPatch(typeof(Player), "UpdateHover")]
internal static class PlayerUpdateHoverPatch
{
	private static readonly FieldRef<Player, GameObject> Hovering = AccessTools.FieldRefAccess<Player, GameObject>("m_hovering");

	private static readonly FieldRef<Player, Character> HoveringCreature = AccessTools.FieldRefAccess<Player, Character>("m_hoveringCreature");

	private static void Postfix(Player __instance)
	{
		if (SettingsUI.IsOpen && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			Hovering.Invoke(__instance) = null;
			HoveringCreature.Invoke(__instance) = null;
		}
	}
}
internal static class IconMaker
{
	internal static Quaternion DefaultRotation => Quaternion.Euler(Cfg.IconPitch, Cfg.IconYaw, 0f);

	internal static Sprite Render(GameObject prefab, int size, Quaternion rotation)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Expected O, but got Unknown
		if ((Object)(object)prefab == (Object)null)
		{
			return null;
		}
		GameObject val = null;
		try
		{
			val = VisualCopy(prefab);
			RenderRequest val2 = new RenderRequest(val)
			{
				Width = size,
				Height = size,
				Rotation = rotation,
				FieldOfView = 0.5f,
				DistanceMultiplier = 1.05f,
				UseCache = false
			};
			return RenderManager.Instance.Render(val2);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Shredder icon render failed: " + ex.Message));
			return null;
		}
		finally
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}
	}

	private static GameObject VisualCopy(GameObject prefab)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: 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_0130: 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_013f: 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_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("lynx_shredder_iconcopy");
		val.transform.position = new Vector3(0f, -10000f, 0f);
		Transform transform = prefab.transform;
		MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
		foreach (MeshRenderer val2 in componentsInChildren)
		{
			MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null) && ((Renderer)val2).enabled && ActiveUnder(((Component)val2).transform, transform) && !IsSnow((Renderer)(object)val2))
			{
				GameObject val3 = new GameObject(((Object)val2).name)
				{
					layer = prefab.layer
				};
				val3.transform.SetParent(val.transform, false);
				val3.transform.localPosition = transform.InverseTransformPoint(((Component)val2).transform.position);
				val3.transform.localRotation = Quaternion.Inverse(transform.rotation) * ((Component)val2).transform.rotation;
				Vector3 lossyScale = ((Component)val2).transform.lossyScale;
				Vector3 lossyScale2 = transform.lossyScale;
				val3.transform.localScale = new Vector3(lossyScale.x / lossyScale2.x, lossyScale.y / lossyScale2.y, lossyScale.z / lossyScale2.z);
				val3.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
				((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterials = ((Renderer)val2).sharedMaterials;
			}
		}
		return val;
	}

	private static bool ActiveUnder(Transform t, Transform root)
	{
		Transform val = t;
		while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
		{
			if (!((Component)val).gameObject.activeSelf)
			{
				return false;
			}
			val = val.parent;
		}
		return true;
	}

	private static bool IsSnow(Renderer r)
	{
		Material sharedMaterial = r.sharedMaterial;
		if ((Object)(object)sharedMaterial != (Object)null && (((Object)sharedMaterial).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)(object)sharedMaterial.shader != (Object)null && ((Object)sharedMaterial.shader).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0)))
		{
			return true;
		}
		return ((Object)r).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0;
	}

	internal static void ApplyBuildIcon(GameObject prefab)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		Piece val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null);
		if (!((Object)(object)val == (Object)null))
		{
			Sprite val2 = Render(prefab, 128, DefaultRotation);
			if ((Object)(object)val2 != (Object)null)
			{
				val.m_icon = val2;
				Plugin.Log.LogInfo((object)"Shredder build icon rendered");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Shredder build icon: render unavailable, keeping the chest icon");
			}
		}
	}

	internal static string RenderSet(GameObject prefab, int size)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		string text = Path.Combine(Paths.ConfigPath, "LynxShredder_icons");
		Directory.CreateDirectory(text);
		int num = 0;
		for (int i = 0; i < 360; i += 45)
		{
			Sprite val = Render(prefab, size, Quaternion.Euler(Cfg.IconPitch, (float)i, 0f));
			if (!((Object)(object)val == (Object)null))
			{
				File.WriteAllBytes(Path.Combine(text, $"shredder_yaw{i:000}.png"), ImageConversion.EncodeToPNG(val.texture));
				num++;
			}
		}
		if (num <= 0)
		{
			return "rendering failed (see the log)";
		}
		return $"{num} renders written to {text}";
	}
}
internal static class Meshes
{
	private class Builder
	{
		public readonly List<Vector3> V = new List<Vector3>();

		public readonly List<Vector3> N = new List<Vector3>();

		public readonly List<Vector2> U = new List<Vector2>();

		public readonly List<int> T = new List<int>();

		public void Quad(Vector3 a, Vector3 b, Vector3 c, Vector3 d, Vector2 ua, Vector2 ub, Vector2 uc, Vector2 ud)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Cross(b - a, d - a);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			int count = V.Count;
			V.Add(a);
			V.Add(b);
			V.Add(c);
			V.Add(d);
			N.Add(normalized);
			N.Add(normalized);
			N.Add(normalized);
			N.Add(normalized);
			U.Add(ua);
			U.Add(ub);
			U.Add(uc);
			U.Add(ud);
			T.Add(count);
			T.Add(count + 1);
			T.Add(count + 2);
			T.Add(count);
			T.Add(count + 2);
			T.Add(count + 3);
		}

		public void QuadAuto(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float scale = 1f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			float num = Vector3.Distance(a, b) * scale;
			float num2 = Vector3.Distance(a, d) * scale;
			Quad(a, b, c, d, new Vector2(0f, 0f), new Vector2(num, 0f), new Vector2(num, num2), new Vector2(0f, num2));
		}

		public void Box(Vector3 center, Vector3 size)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_0155: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: 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_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 e = size * 0.5f;
			QuadAuto(P(-1f, -1f, 1f), P(1f, -1f, 1f), P(1f, 1f, 1f), P(-1f, 1f, 1f), 2f);
			QuadAuto(P(1f, -1f, -1f), P(-1f, -1f, -1f), P(-1f, 1f, -1f), P(1f, 1f, -1f), 2f);
			QuadAuto(P(1f, -1f, 1f), P(1f, -1f, -1f), P(1f, 1f, -1f), P(1f, 1f, 1f), 2f);
			QuadAuto(P(-1f, -1f, -1f), P(-1f, -1f, 1f), P(-1f, 1f, 1f), P(-1f, 1f, -1f), 2f);
			QuadAuto(P(-1f, 1f, 1f), P(1f, 1f, 1f), P(1f, 1f, -1f), P(-1f, 1f, -1f), 2f);
			QuadAuto(P(-1f, -1f, -1f), P(1f, -1f, -1f), P(1f, -1f, 1f), P(-1f, -1f, 1f), 2f);
			Vector3 P(float x, float y, float z)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				return center + new Vector3(x * e.x, y * e.y, z * e.z);
			}
		}

		public Mesh Build(string name)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0045: Expected O, but got Unknown
			Mesh val = new Mesh
			{
				name = name
			};
			val.SetVertices(V);
			val.SetNormals(N);
			val.SetUVs(0, U);
			val.SetTriangles(T, 0);
			val.RecalculateBounds();
			return val;
		}
	}

	internal static Mesh Hopper(float bx, float bz, float tx, float tz, float h, float t)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_0043: 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)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: 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_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: 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_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		Builder builder = new Builder();
		Vector3[] array = (Vector3[])(object)new Vector3[4]
		{
			new Vector3(0f - bx, 0f, 0f - bz),
			new Vector3(bx, 0f, 0f - bz),
			new Vector3(bx, 0f, bz),
			new Vector3(0f - bx, 0f, bz)
		};
		Vector3[] array2 = (Vector3[])(object)new Vector3[4]
		{
			new Vector3(0f - tx, h, 0f - tz),
			new Vector3(tx, h, 0f - tz),
			new Vector3(tx, h, tz),
			new Vector3(0f - tx, h, tz)
		};
		Vector3[] array3 = (Vector3[])(object)new Vector3[4];
		Vector3[] array4 = (Vector3[])(object)new Vector3[4];
		for (int i = 0; i < 4; i++)
		{
			array3[i] = new Vector3(array[i].x - Mathf.Sign(array[i].x) * t, 0f, array[i].z - Mathf.Sign(array[i].z) * t);
			array4[i] = new Vector3(array2[i].x - Mathf.Sign(array2[i].x) * t, h, array2[i].z - Mathf.Sign(array2[i].z) * t);
		}
		for (int j = 0; j < 4; j++)
		{
			int num = (j + 1) % 4;
			builder.QuadAuto(array[num], array[j], array2[j], array2[num], 1.2f);
			builder.QuadAuto(array3[j], array3[num], array4[num], array4[j], 1.2f);
			builder.QuadAuto(array4[j], array4[num], array2[num], array2[j], 4f);
			builder.QuadAuto(array[j], array[num], array3[num], array3[j], 4f);
		}
		return builder.Build("lynx_shredder_hopper");
	}

	internal static Mesh Rim(float tx, float tz, float h, float w)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		Builder builder = new Builder();
		builder.Box(new Vector3(0f, h, 0f - tz), new Vector3(tx * 2f + w, w, w));
		builder.Box(new Vector3(0f, h, tz), new Vector3(tx * 2f + w, w, w));
		builder.Box(new Vector3(0f - tx, h, 0f), new Vector3(w, w, tz * 2f + w));
		builder.Box(new Vector3(tx, h, 0f), new Vector3(w, w, tz * 2f + w));
		return builder.Build("lynx_shredder_rim");
	}

	internal static Mesh Plate(Vector3 size)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		Builder builder = new Builder();
		builder.Box(Vector3.zero, size);
		return builder.Build("lynx_shredder_plate");
	}

	internal static Mesh Axle(float length, float radius, int sides = 12)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		Builder builder = new Builder();
		float num = length * 0.5f;
		Vector3 val = default(Vector3);
		Vector3 val2 = default(Vector3);
		for (int i = 0; i < sides; i++)
		{
			float num2 = (float)i * (float)Math.PI * 2f / (float)sides;
			float num3 = (float)(i + 1) * (float)Math.PI * 2f / (float)sides;
			((Vector3)(ref val))..ctor(0f, Mathf.Cos(num2) * radius, Mathf.Sin(num2) * radius);
			((Vector3)(ref val2))..ctor(0f, Mathf.Cos(num3) * radius, Mathf.Sin(num3) * radius);
			builder.Quad(new Vector3(0f - num, val.y, val.z), new Vector3(0f - num, val2.y, val2.z), new Vector3(num, val2.y, val2.z), new Vector3(num, val.y, val.z), new Vector2(0f, 0f), new Vector2(0.2f, 0f), new Vector2(0.2f, length), new Vector2(0f, length));
		}
		return builder.Build("lynx_shredder_axle");
	}

	internal static Mesh HookedDisc(float r0, float r1, float thickness, int hooks = 4, int stepsPerHook = 10)
	{
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: 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_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d3: 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_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: 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_0311: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Unknown result type (might be due to invalid IL or missing references)
		//IL_034d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		Builder builder = new Builder();
		List<Vector2> list = new List<Vector2>();
		for (int i = 0; i < hooks; i++)
		{
			for (int j = 0; j <= stepsPerHook; j++)
			{
				float num = (float)j / (float)stepsPerHook;
				float num2 = ((float)i + num * 0.92f) / (float)hooks * (float)Math.PI * 2f;
				float num3 = r0 + (r1 - r0) * Mathf.Pow(num, 1.3f);
				list.Add(new Vector2(Mathf.Cos(num2) * num3, Mathf.Sin(num2) * num3));
			}
			float num4 = ((float)i + 0.97f) / (float)hooks * (float)Math.PI * 2f;
			list.Add(new Vector2(Mathf.Cos(num4) * (r1 * 0.93f), Mathf.Sin(num4) * (r1 * 0.93f)));
			float num5 = ((float)i + 1f) / (float)hooks * (float)Math.PI * 2f;
			list.Add(new Vector2(Mathf.Cos(num5) * r0, Mathf.Sin(num5) * r0));
		}
		float num6 = thickness * 0.5f;
		int count = list.Count;
		Vector3 item = default(Vector3);
		for (int k = -1; k <= 1; k += 2)
		{
			int count2 = builder.V.Count;
			((Vector3)(ref item))..ctor((float)k, 0f, 0f);
			builder.V.Add(new Vector3((float)k * num6, 0f, 0f));
			builder.N.Add(item);
			builder.U.Add(new Vector2(0.5f, 0.5f));
			foreach (Vector2 item4 in list)
			{
				builder.V.Add(new Vector3((float)k * num6, item4.x, item4.y));
				builder.N.Add(item);
				builder.U.Add(new Vector2(0.5f + item4.x / (2f * r1), 0.5f + item4.y / (2f * r1)));
			}
			for (int l = 0; l < count; l++)
			{
				int item2 = count2 + 1 + l;
				int item3 = count2 + 1 + (l + 1) % count;
				if (k > 0)
				{
					builder.T.Add(count2);
					builder.T.Add(item2);
					builder.T.Add(item3);
				}
				else
				{
					builder.T.Add(count2);
					builder.T.Add(item3);
					builder.T.Add(item2);
				}
			}
		}
		for (int m = 0; m < count; m++)
		{
			Vector2 val = list[m];
			Vector2 val2 = list[(m + 1) % count];
			builder.Quad(new Vector3(num6, val.x, val.y), new Vector3(0f - num6, val.x, val.y), new Vector3(0f - num6, val2.x, val2.y), new Vector3(num6, val2.x, val2.y), new Vector2(0f, 0f), new Vector2(0.1f, 0f), new Vector2(0.1f, 0.1f), new Vector2(0f, 0.1f));
		}
		return builder.Build("lynx_shredder_disc");
	}

	internal static Mesh MirrorZ(Mesh src, string name)
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Expected O, but got Unknown
		Vector3[] vertices = src.vertices;
		Vector3[] normals = src.normals;
		int[] triangles = src.triangles;
		for (int i = 0; i < vertices.Length; i++)
		{
			vertices[i].z = 0f - vertices[i].z;
			normals[i].z = 0f - normals[i].z;
		}
		for (int j = 0; j < triangles.Length; j += 3)
		{
			int num = triangles[j + 1];
			triangles[j + 1] = triangles[j + 2];
			triangles[j + 2] = num;
		}
		Mesh val = new Mesh
		{
			name = name,
			vertices = vertices,
			normals = normals,
			uv = src.uv,
			triangles = triangles
		};
		val.RecalculateBounds();
		return val;
	}

	internal static Texture2D WoodTexture()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_012f: 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)
		Texture2D val = new Texture2D(128, 128, (TextureFormat)4, true)
		{
			name = "lynx_shredder_wood",
			wrapMode = (TextureWrapMode)0
		};
		Random random = new Random(1337);
		Color[] array = (Color[])(object)new Color[16384];
		float[] array2 = new float[4];
		for (int i = 0; i < 4; i++)
		{
			array2[i] = 0.85f + (float)random.NextDouble() * 0.3f;
		}
		for (int j = 0; j < 128; j++)
		{
			for (int k = 0; k < 128; k++)
			{
				int num = k / 32;
				float num2 = (float)(k % 32) / 32f;
				float num3 = Mathf.PerlinNoise((float)k * 0.35f, (float)j * 0.03f + (float)num * 7f) * 0.25f + Mathf.PerlinNoise((float)k * 1.7f, (float)j * 0.11f) * 0.08f;
				float num4 = ((num2 < 0.04f || num2 > 0.96f) ? 0.45f : 1f);
				float num5 = (0.55f + num3) * array2[num] * num4;
				array[j * 128 + k] = new Color(0.42f * num5, 0.29f * num5, 0.18f * num5, 1f);
			}
		}
		val.SetPixels(array);
		val.Apply(true);
		return val;
	}

	internal static Texture2D IronTexture(float baseValue, string name)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected O, but got Unknown
		//IL_00c0: 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)
		Texture2D val = new Texture2D(64, 64, (TextureFormat)4, true)
		{
			name = name,
			wrapMode = (TextureWrapMode)0
		};
		Color[] array = (Color[])(object)new Color[4096];
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				float num = Mathf.PerlinNoise((float)j * 0.21f, (float)i * 0.21f) * 0.12f + Mathf.PerlinNoise((float)j * 0.9f, (float)i * 0.9f) * 0.05f;
				float num2 = baseValue + num;
				float num3 = ((Mathf.PerlinNoise((float)j * 0.08f + 3f, (float)i * 0.08f) > 0.72f) ? 0.06f : 0f);
				array[i * 64 + j] = new Color(num2 + num3, num2 + num3 * 0.4f, num2, 1f);
			}
		}
		val.SetPixels(array);
		val.Apply(true);
		return val;
	}

	internal static Material MakeMaterial(string name, Texture2D tex, float metallic, float gloss, Material fallbackBase)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Expected O, but got Unknown
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		Material val = null;
		Shader val2 = Shader.Find("Standard");
		if ((Object)(object)val2 != (Object)null)
		{
			val = new Material(val2);
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", metallic);
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", gloss);
			}
		}
		else if ((Object)(object)fallbackBase != (Object)null)
		{
			val = new Material(fallbackBase);
			string[] array = new string[6] { "_BumpMap", "_MetallicGlossMap", "_EmissionMap", "_OcclusionMap", "_DetailAlbedoMap", "_DetailNormalMap" };
			foreach (string text in array)
			{
				if (val.HasProperty(text))
				{
					val.SetTexture(text, (Texture)null);
				}
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		((Object)val).name = name;
		val.mainTexture = (Texture)(object)tex;
		val.mainTextureScale = Vector2.one;
		return val;
	}
}
[HarmonyPatch(typeof(Container), "Interact")]
internal static class ContainerInteractPatch
{
	[HarmonyPriority(600)]
	private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result)
	{
		ShredderPiece component = ((Component)__instance).GetComponent<ShredderPiece>();
		if ((Object)(object)component == (Object)null || hold || !alt)
		{
			return true;
		}
		Player val = (Player)(object)((character is Player) ? character : null);
		if ((Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)Player.m_localPlayer)
		{
			if (!Access.ContainerCheckAccess(__instance, val.GetPlayerID()))
			{
				((Character)val).Message((MessageType)2, "$msg_cantopen", 0, (Sprite)null, false);
			}
			else
			{
				SettingsUI.Open(component);
			}
		}
		__result = true;
		return false;
	}
}
[HarmonyPatch(typeof(Container), "GetHoverText")]
internal static class ContainerHoverPatch
{
	private static void Postfix(Container __instance, ref string __result)
	{
		ShredderPiece component = ((Component)__instance).GetComponent<ShredderPiece>();
		if (!((Object)(object)component == (Object)null) && component.Valid)
		{
			string text = "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] Settings\n" + component.StatusLine();
			int shreddedCount = component.ShreddedCount;
			if (shreddedCount > 0)
			{
				text += $"  <color=#aaaaaa>({shreddedCount} shredded)</color>";
			}
			if (Localization.instance != null)
			{
				text = Localization.instance.Localize(text);
			}
			__result += text;
		}
	}
}
[HarmonyPatch(typeof(StoreGui), "IsVisible")]
internal static class StoreGuiVisiblePatch
{
	private static void Postfix(ref bool __result)
	{
		if (SettingsUI.IsOpen)
		{
			__result = true;
		}
	}
}
[HarmonyPatch(typeof(Menu), "Update")]
internal static class MenuUpdatePatch
{
	private static bool Prefix()
	{
		if (!SettingsUI.IsOpen)
		{
			return true;
		}
		if (ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("JoyMenu"))
		{
			SettingsUI.Close();
			return false;
		}
		return true;
	}
}
[BepInPlugin("lynx.lynxshredder", "LynxShredder", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "lynx.lynxshredder";

	public const string Name = "LynxShredder";

	public const string Version = "1.0.1";

	internal static ManualLogSource Log;

	internal static Plugin Instance;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Cfg.Bind(((BaseUnityPlugin)this).Config);
		_harmony = new Harmony("lynx.lynxshredder");
		_harmony.PatchAll(typeof(Plugin).Assembly);
		ConfigWatcher.Start(this);
		Log.LogInfo((object)"LynxShredder 1.0.1 loaded");
	}

	private void Start()
	{
		Compat.Detect();
		DumpCommand.Register();
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
internal class RadiusRing : MonoBehaviour
{
	internal float Radius;

	private Vector3 _center;

	private readonly List<Transform> _dashes = new List<Transform>();

	private static Material _mat;

	private static readonly int GroundMask = LayerMask.GetMask(new string[4] { "terrain", "piece", "static_solid", "Default" });

	private const int Count = 64;

	internal static RadiusRing Create(Vector3 center, float radius)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Expected O, but got Unknown
		GameObject val = new GameObject("LynxShredder_RadiusRing");
		RadiusRing radiusRing = val.AddComponent<RadiusRing>();
		radiusRing._center = center;
		radiusRing.Radius = radius;
		if ((Object)(object)_mat == (Object)null)
		{
			_mat = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard"))
			{
				color = new Color(1f, 0.75f, 0.25f, 0.85f),
				name = "lynx_shredder_ring"
			};
		}
		for (int i = 0; i < 64; i++)
		{
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)3);
			Object.Destroy((Object)(object)val2.GetComponent<Collider>());
			((Object)val2).name = "dash";
			val2.transform.SetParent(val.transform, false);
			MeshRenderer component = val2.GetComponent<MeshRenderer>();
			((Renderer)component).sharedMaterial = _mat;
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = false;
			radiusRing._dashes.Add(val2.transform);
		}
		radiusRing.LateUpdate();
		return radiusRing;
	}

	private void LateUpdate()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		float num = (float)Math.PI * 2f * Radius / 64f;
		RaycastHit val2 = default(RaycastHit);
		for (int i = 0; i < _dashes.Count; i++)
		{
			float num2 = ((float)i + 0.5f) / 64f * (float)Math.PI * 2f;
			Vector3 val = _center + new Vector3(Mathf.Sin(num2), 0f, Mathf.Cos(num2)) * Radius;
			if (Physics.Raycast(val + Vector3.up * 3f, Vector3.down, ref val2, 8f, GroundMask, (QueryTriggerInteraction)1))
			{
				val.y = ((RaycastHit)(ref val2)).point.y;
			}
			Transform obj = _dashes[i];
			obj.position = val + Vector3.up * 0.06f;
			obj.rotation = Quaternion.LookRotation(new Vector3(Mathf.Cos(num2), 0f, 0f - Mathf.Sin(num2)));
			obj.localScale = new Vector3(0.08f, 0.04f, num * 0.55f);
		}
	}
}
internal static class Registration
{
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	private static class ZNetSceneAwake
	{
		[HarmonyPriority(200)]
		private static void Postfix(ZNetScene __instance)
		{
			try
			{
				if ((Object)(object)Prefab == (Object)null)
				{
					Build(__instance);
				}
				if (!((Object)(object)Prefab == (Object)null))
				{
					if (!__instance.m_prefabs.Contains(Prefab))
					{
						__instance.m_prefabs.Add(Prefab);
					}
					_named.Invoke(__instance)[StringExtensionMethods.GetStableHashCode("piece_lynx_shredder")] = Prefab;
					ApplyPieceConfig();
					AddToHammer(__instance);
					if (!_iconDone)
					{
						_iconDone = true;
						IconMaker.ApplyBuildIcon(Prefab);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Shredder registration failed: " + ex));
			}
		}
	}

	internal const string PrefabName = "piece_lynx_shredder";

	private const string BasePrefab = "piece_chest";

	internal static GameObject Prefab;

	private static bool _iconDone;

	private static GameObject _holder;

	private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> _named;

	private static ZNetScene _zns;

	static Registration()
	{
		_named = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs");
		Cfg.Changed += delegate
		{
			try
			{
				ApplyPieceConfig();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Applying piece config failed: " + ex.Message));
			}
		};
	}

	private static void AddToHammer(ZNetScene zns)
	{
		GameObject prefab = zns.GetPrefab("Hammer");
		PieceTable val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_buildPieces;
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Hammer piece table not found; Shredder can't be built");
		}
		else if (!val.m_pieces.Contains(Prefab))
		{
			val.m_pieces.Add(Prefab);
		}
	}

	internal static void ApplyPieceConfig()
	{
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Expected O, but got Unknown
		ZNetScene instance = ZNetScene.instance;
		if ((Object)(object)Prefab == (Object)null || (Object)(object)instance == (Object)null)
		{
			return;
		}
		Piece component = Prefab.GetComponent<Piece>();
		List<Requirement> list = new List<Requirement>();
		string[] array = (Cfg.BuildCost ?? "").Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(':');
			string text = array2[0].Trim();
			int result;
			int val = ((array2.Length <= 1 || !int.TryParse(array2[1].Trim(), out result)) ? 1 : result);
			GameObject prefab = instance.GetPrefab(text);
			ItemDrop val2 = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)("BuildCost: no item called '" + text + "'"));
				continue;
			}
			list.Add(new Requirement
			{
				m_resItem = val2,
				m_amount = Math.Max(1, val),
				m_recover = true
			});
		}
		if (list.Count == 0)
		{
			Plugin.Log.LogWarning((object)"BuildCost is empty or invalid; using the default cost");
			(string, int)[] array3 = new(string, int)[3]
			{
				("FineWood", 10),
				("Iron", 6),
				("SurtlingCore", 1)
			};
			for (int i = 0; i < array3.Length; i++)
			{
				(string, int) tuple = array3[i];
				string item = tuple.Item1;
				int item2 = tuple.Item2;
				GameObject prefab2 = instance.GetPrefab(item);
				ItemDrop val3 = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					list.Add(new Requirement
					{
						m_resItem = val3,
						m_amount = item2,
						m_recover = true
					});
				}
			}
		}
		component.m_resources = list.ToArray();
		string text2 = (Cfg.Station ?? "").Trim();
		object craftingStation;
		if (text2.Length != 0)
		{
			GameObject prefab3 = instance.GetPrefab(text2);
			craftingStation = ((prefab3 != null) ? prefab3.GetComponent<CraftingStation>() : null);
		}
		else
		{
			craftingStation = null;
		}
		component.m_craftingStation = (CraftingStation)craftingStation;
		if (text2.Length > 0 && (Object)(object)component.m_craftingStation == (Object)null)
		{
			Plugin.Log.LogWarning((object)("CraftingStation: no station prefab called '" + text2 + "'"));
		}
		component.m_category = ResolveCategory((Cfg.Category ?? "").Trim());
	}

	private static PieceCategory ResolveCategory(string name)
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		if (name.Length == 0)
		{
			name = "LynxStations";
		}
		if (!char.IsDigit(name[0]) && Enum.TryParse<PieceCategory>(name, ignoreCase: true, out PieceCategory result) && (int)result < 9)
		{
			return result;
		}
		try
		{
			return PieceManager.Instance.AddPieceCategory(name);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Could not create build tab '" + name + "' via Jotunn (" + ex.Message + "); using Misc"));
			return (PieceCategory)0;
		}
	}

	private static void Build(ZNetScene zns)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Expected O, but got Unknown
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: 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_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: 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)
		//IL_0041: Expected O, but got Unknown
		//IL_0136: 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_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Invalid comparison between Unknown and I4
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		GameObject prefab = zns.GetPrefab("piece_chest");
		if ((Object)(object)prefab == (Object)null)
		{
			Plugin.Log.LogError((object)"Base prefab piece_chest not found; Shredder not registered");
			return;
		}
		if ((Object)(object)_holder == (Object)null)
		{
			_holder = new GameObject("LynxShredder_Prefabs");
			_holder.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_holder);
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, _holder.transform, false);
		((Object)val).name = "piece_lynx_shredder";
		val.transform.localPosition = Vector3.zero;
		val.transform.localRotation = Quaternion.identity;
		Plugin.Log.LogInfo((object)("piece_chest layout: " + Describe(val.transform, 0)));
		Piece component = val.GetComponent<Piece>();
		component.m_name = "Shredder";
		component.m_description = "Pulls low-tier gear out of nearby chests and salvages it into materials. E opens the output chest, Shift+E opens the settings.";
		Container component2 = val.GetComponent<Container>();
		component2.m_name = "Shredder";
		component2.m_width = 6;
		component2.m_height = 4;
		component2.m_autoDestroyEmpty = false;
		component2.m_defaultItems = new DropTable();
		Bounds val2 = LocalBounds(val.transform);
		RemoveLid(val, component2, val2);
		Bounds body = LocalBounds(val.transform);
		if (((Bounds)(ref body)).size.y < 0.1f)
		{
			body = val2;
		}
		Material val3 = null;
		MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
		foreach (MeshRenderer val4 in componentsInChildren)
		{
			if (!IsSnow((Renderer)(object)val4))
			{
				val3 = ((Renderer)val4).sharedMaterial;
				if ((Object)(object)val3 != (Object)null)
				{
					break;
				}
			}
		}
		_zns = zns;
		if ((int)SystemInfo.graphicsDeviceType == 4)
		{
			Plugin.Log.LogInfo((object)"Headless server: skipping Shredder visuals");
		}
		else
		{
			try
			{
				AddMachine(val, body, val3);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Shredder visuals failed (piece still works): " + ex));
			}
		}
		val.AddComponent<ShredderVisual>();
		val.AddComponent<ShredderPiece>();
		Prefab = val;
		Plugin.Log.LogInfo((object)$"Shredder prefab built (body {((Bounds)(ref body)).size.x:0.00} x {((Bounds)(ref body)).size.y:0.00} x {((Bounds)(ref body)).size.z:0.00} m)");
	}

	private static void RemoveLid(GameObject go, Container c, Bounds full)
	{
		List<GameObject> list = new List<GameObject>();
		GameObject[] array = (GameObject[])(object)new GameObject[2] { c.m_open, c.m_closed };
		foreach (GameObject val in array)
		{
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)go && !list.Contains(val))
			{
				list.Add(val);
			}
		}
		if (list.Count == 0)
		{
			Plugin.Log.LogInfo((object)"Chest has no lid objects; the hopper sits on top");
			return;
		}
		Transform val2 = null;
		MeshFilter[] componentsInChildren = go.GetComponentsInChildren<MeshFilter>(true);
		foreach (MeshFilter val3 in componentsInChildren)
		{
			if ((Object)(object)((Component)val3).GetComponent<Renderer>() == (Object)null || IsSnow(((Component)val3).GetComponent<Renderer>()))
			{
				continue;
			}
			bool flag = false;
			foreach (GameObject item in list)
			{
				if (((Component)val3).transform.IsChildOf(item.transform))
				{
					flag = true;
				}
			}
			if (!flag)
			{
				val2 = ((Component)val3).transform;
				break;
			}
		}
		foreach (GameObject item2 in list)
		{
			if ((Object)(object)val2 != (Object)null && val2.IsChildOf(item2.transform))
			{
				Plugin.Log.LogInfo((object)("Kept '" + ((Object)item2).name + "' (it holds the chest body)"));
				continue;
			}
			Plugin.Log.LogInfo((object)("Removed chest lid '" + ((Object)item2).name + "'"));
			Object.DestroyImmediate((Object)(object)item2);
		}
		if ((Object)(object)c.m_open == (Object)null)
		{
			c.m_open = null;
		}
		if ((Object)(object)c.m_closed == (Object)null)
		{
			c.m_closed = null;
		}
	}

	private static Material Donor(string what, bool triplanarOnly, params string[] prefabs)
	{
		for (int i = 0; i < (triplanarOnly ? 1 : 2); i++)
		{
			foreach (string text in prefabs)
			{
				GameObject val = (((Object)(object)_zns != (Object)null) ? _zns.GetPrefab(text) : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val2 in componentsInChildren)
				{
					Material sharedMaterial = ((Renderer)val2).sharedMaterial;
					if (!((Object)(object)sharedMaterial == (Object)null) && !IsSnow((Renderer)(object)val2))
					{
						bool flag = sharedMaterial.IsKeywordEnabled("_TRIPLANARMAP_ON");
						if (i != 0 || flag)
						{
							ManualLogSource log = Plugin.Log;
							string[] obj = new string[12]
							{
								what,
								" material from '",
								text,
								"/",
								((Object)val2).name,
								"' (",
								((Object)sharedMaterial).name,
								", shader ",
								null,
								null,
								null,
								null
							};
							Shader shader = sharedMaterial.shader;
							obj[8] = ((shader != null) ? ((Object)shader).name : null);
							obj[9] = ", triplanar ";
							obj[10] = (flag ? "on" : "off");
							obj[11] = ")";
							log.LogInfo((object)string.Concat(obj));
							return sharedMaterial;
						}
					}
				}
			}
		}
		Plugin.Log.LogInfo((object)(what + ": no suitable donor piece, using a generated texture on the chest's material"));
		return null;
	}

	private static bool IsSnow(Renderer r)
	{
		Material sharedMaterial = r.sharedMaterial;
		if ((Object)(object)sharedMaterial != (Object)null && (((Object)(object)sharedMaterial.shader != (Object)null && ((Object)sharedMaterial.shader).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0) || ((Object)sharedMaterial).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0))
		{
			return true;
		}
		Transform val = ((Component)r).transform;
		while ((Object)(object)val != (Object)null)
		{
			if (((Object)val).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			val = val.parent;
		}
		return false;
	}

	private static void AddMachine(GameObject go, Bounds body, Material baseMat)
	{
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: 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_013e: Expected O, but got Unknown
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0462: Unknown result type (might be due to invalid IL or missing references)
		//IL_048f: Unknown result type (might be due to invalid IL or missing references)
		//IL_049e: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_050d: 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_0338: Expected O, but got Unknown
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0397: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0431: Unknown result type (might be due to invalid IL or missing references)
		Material mat = Donor("Hopper wood", false, "wood_floor", "wood_floor_1x1", "wood_wall_half") ?? Meshes.MakeMaterial("lynx_shredder_wood", Meshes.WoodTexture(), 0f, 0.15f, baseMat);
		Material mat2 = Donor("Iron", true, "piece_dvergr_metal_wall_2x2", "iron_floor_1x1", "iron_floor_2x2", "iron_wall_1x1", "iron_wall_2x2") ?? Meshes.MakeMaterial("lynx_shredder_iron", Meshes.IronTexture(0.45f, "lynx_shredder_iron"), 0.7f, 0.45f, baseMat);
		Material mat3 = Meshes.MakeMaterial("lynx_shredder_dark", Meshes.IronTexture(0.1f, "lynx_shredder_dark"), 0.3f, 0.2f, baseMat);
		float y = ((Bounds)(ref body)).max.y;
		float num = ((Bounds)(ref body)).extents.x * 0.97f;
		float num2 = ((Bounds)(ref body)).extents.z * 0.97f;
		float num3 = 0.42f;
		float num4 = 0.04f;
		float num5 = num * 1.1f + 0.05f;
		float num6 = num2 * 1.3f + 0.05f;
		GameObject val = new GameObject("lynx_machine");
		val.layer = go.layer;
		val.transform.SetParent(go.transform, false);
		val.transform.localPosition = new Vector3(((Bounds)(ref body)).center.x, y - 0.005f, ((Bounds)(ref body)).center.z);
		Part(val.transform, "lynx_hopper", Meshes.Hopper(num, num2, num5, num6, num3, num4), mat, Vector3.zero);
		Part(val.transform, "lynx_rim", Meshes.Rim(num5 - num4 * 0.5f, num6 - num4 * 0.5f, num3, num4 * 1.4f), mat2, Vector3.zero);
		Part(val.transform, "lynx_band", Meshes.Rim(num + 0.005f, num2 + 0.005f, 0.05f, 0.07f), mat2, Vector3.zero);
		Part(val.transform, "lynx_throat_plate", Meshes.Plate(new Vector3((num - num4) * 2f, 0.02f, (num2 - num4) * 2f)), mat3, new Vector3(0f, 0.012f, 0f));
		float num7 = (num - num4) * 2f - 0.04f;
		float num8 = Mathf.Clamp((num2 - num4) * 2f * 0.25f, 0.08f, 0.16f);
		float num9 = num8 * 0.68f;
		float radius = num9 * 0.4f;
		float num10 = num8 + num9 * 0.75f;
		float num11 = 0.03f + num8;
		int num12 = Mathf.Max(3, Mathf.FloorToInt(num7 / 0.12f));
		Mesh val2 = Meshes.HookedDisc(num9, num8, 0.06f, 3, 8);
		Mesh val3 = Meshes.MirrorZ(val2, "lynx_shredder_disc_b");
		Mesh mesh = Meshes.Axle(num7, radius);
		for (int i = 0; i < 2; i++)
		{
			GameObject val4 = new GameObject((i == 0) ? "lynx_shaft_a" : "lynx_shaft_b");
			val4.layer = go.layer;
			val4.transform.SetParent(val.transform, false);
			val4.transform.localPosition = new Vector3(0f, num11, (i == 0) ? ((0f - num10) * 0.5f) : (num10 * 0.5f));
			Part(val4.transform, "axle", mesh, mat2, Vector3.zero);
			float num13 = ((i == 0) ? 0f : 0.06f);
			for (int j = 0; j < num12; j++)
			{
				float num14 = (0f - num7) * 0.5f + 0.06f + (float)j * 0.12f + num13;
				if (num14 > num7 * 0.5f - 0.03f)
				{
					break;
				}
				Part(val4.transform, "disc", (i == 0) ? val2 : val3, mat2, new Vector3(num14, 0f, 0f)).transform.localRotation = Quaternion.Euler((float)j * 37f, 0f, 0f);
			}
		}
		GameObject val5 = new GameObject("lynx_throat");
		val5.transform.SetParent(val.transform, false);
		val5.transform.localPosition = new Vector3(0f, num11 + num8 * 0.5f, 0f);
		GameObject val6 = new GameObject("lynx_mouth");
		val6.transform.SetParent(val.transform, false);
		val6.transform.localPosition = new Vector3(0f, num3 + 0.35f, 0f);
		BoxCollider obj = val.AddComponent<BoxCollider>();
		obj.center = new Vector3(0f, num3 * 0.5f, 0f);
		obj.size = new Vector3(num5 * 2f, num3, num6 * 2f);
	}

	private static GameObject Part(Transform parent, string name, Mesh mesh, Material mat, Vector3 pos)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		GameObject val = new GameObject(name)
		{
			layer = ((Component)parent).gameObject.layer
		};
		val.transform.SetParent(parent, false);
		val.transform.localPosition = pos;
		val.AddComponent<MeshFilter>().sharedMesh = mesh;
		MeshRenderer val2 = val.AddComponent<MeshRenderer>();
		if ((Object)(object)mat != (Object)null)
		{
			((Renderer)val2).sharedMaterial = mat;
		}
		return val;
	}

	private static Bounds LocalBounds(Transform t, Transform root = null)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: 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_0108: Unknown result type (might be due to invalid IL or missing references)
		root = root ?? t;
		Matrix4x4 worldToLocalMatrix = root.worldToLocalMatrix;
		bool flag = false;
		Bounds result = default(Bounds);
		MeshFilter[] componentsInChildren = ((Component)t).GetComponentsInChildren<MeshFilter>(true);
		Vector3 val3 = default(Vector3);
		foreach (MeshFilter val in componentsInChildren)
		{
			if ((Object)(object)val.sharedMesh == (Object)null || (Object)(object)((Component)val).GetComponent<Renderer>() == (Object)null || !CountsForBounds(((Component)val).transform, root))
			{
				continue;
			}
			Bounds bounds = val.sharedMesh.bounds;
			Matrix4x4 val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
			for (int j = 0; j < 8; j++)
			{
				((Vector3)(ref val3))..ctor(((j & 1) == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, ((j & 2) == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, ((j & 4) == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z);
				Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3);
				if (!flag)
				{
					((Bounds)(ref result))..ctor(val4, Vector3.zero);
					flag = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val4);
				}
			}
		}
		return result;
	}

	private static bool CountsForBounds(Transform t, Transform root)
	{
		Transform val = t;
		while ((Object)(object)val != (Object)null)
		{
			if (((Object)val).name.IndexOf("snow", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			if ((Object)(object)val == (Object)(object)root)
			{
				return true;
			}
			if (!((Component)val).gameObject.activeSelf)
			{
				return false;
			}
			val = val.parent;
		}
		return true;
	}

	private static string Describe(Transform t, int depth)
	{
		StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
		if (depth >= 2 || t.childCount == 0)
		{
			return stringBuilder.ToString();
		}
		stringBuilder.Append(" [");
		for (int i = 0; i < t.childCount; i++)
		{
			if (i > 0)
			{
				stringBuilder.Append(", ");
			}
			stringBuilder.Append(Describe(t.GetChild(i), depth + 1));
		}
		return stringBuilder.Append(']').ToString();
	}
}
internal enum Cat
{
	None = -1,
	Weapons,
	Armour,
	Shields,
	Tools,
	Capes
}
internal struct Payout
{
	public ItemDrop Item;

	public int Amount;
}
internal static class Salvage
{
	internal static readonly string[] CatNames = new string[5] { "Weapons", "Armour", "Shields", "Tools", "Capes" };

	internal const int CatCount = 5;

	private static readonly Dictionary<string, Recipe> _recipeCache = new Dictionary<string, Recipe>();

	private static ObjectDB _cacheDb;

	internal static Cat CategoryOf(ItemData item)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected I4, but got Unknown
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Invalid comparison between Unknown and I4
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Invalid comparison between Unknown and I4
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Invalid comparison between Unknown and I4
		SharedData val = item?.m_shared;
		if (val == null)
		{
			return Cat.None;
		}
		ItemType itemType = val.m_itemType;
		switch (itemType - 3)
		{
		default:
			if ((int)itemType != 22)
			{
				break;
			}
			goto case 0;
		case 0:
		case 1:
		case 11:
			if ((int)val.m_skillType == 12 || (int)val.m_skillType == 104)
			{
				return Cat.Tools;
			}
			return Cat.Weapons;
		case 16:
			return Cat.Tools;
		case 2:
			return Cat.Shields;
		case 3:
		case 4:
		case 8:
			return Cat.Armour;
		case 14:
			return Cat.Capes;
		case 5:
		case 6:
		case 7:
		case 9:
		case 10:
		case 12:
		case 13:
		case 15:
			break;
		}
		return Cat.None;
	}

	internal static Recipe RecipeOf(ItemData item)
	{
		ObjectDB instance = ObjectDB.instance;
		if ((Object)(object)instance == (Object)null || item?.m_shared == null)
		{
			return null;
		}
		if ((Object)(object)_cacheDb != (Object)(object)instance)
		{
			_recipeCache.Clear();
			_cacheDb = instance;
		}
		string name = item.m_shared.m_name;
		if (_recipeCache.TryGetValue(name, out var value))
		{
			return value;
		}
		Recipe val = null;
		foreach (Recipe recipe2 in instance.m_recipes)
		{
			if (!((Object)(object)recipe2 == (Object)null) && !((Object)(object)recipe2.m_item == (Object)null) && recipe2.m_enabled && !(recipe2.m_item.m_itemData?.m_shared?.m_name != name) && !UsesItself(recipe2))
			{
				val = recipe2;
				break;
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Recipe recipe = instance.GetRecipe(item);
			if ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null && !UsesItself(recipe))
			{
				val = recipe;
			}
		}
		_recipeCache[name] = val;
		return val;
	}

	private static bool UsesItself(Recipe r)
	{
		if (r?.m_resources == null || (Object)(object)r.m_item == (Object)null)
		{
			return false;
		}
		string text = r.m_item.m_itemData?.m_shared?.m_name;
		Requirement[] resources = r.m_resources;
		for (int i = 0; i < resources.Length; i++)
		{
			if (resources[i]?.m_resItem?.m_itemData?.m_shared?.m_name == text)
			{
				return true;
			}
		}
		return false;
	}

	internal static List<Payout> Returns(ItemData item, Recipe r, float share, float[] bonusByClass)
	{
		List<Payout> list = new List<Payout>();
		if (r?.m_resources == null)
		{
			return list;
		}
		int num = Math.Max(1, item.m_quality);
		int num2 = Math.Max(1, item.m_stack);
		int num3 = Math.Max(1, r.m_amount);
		Requirement[] resources = r.m_resources;
		foreach (Requirement req in resources)
		{
			if ((Object)(object)req?.m_resItem == (Object)null || req.m_resItem.m_itemData?.m_shared?.m_name == item.m_shared.m_name)
			{
				continue;
			}
			int num4 = 0;
			for (int j = 1; j <= num; j++)
			{
				num4 += req.GetAmount(j);
			}
			num4 = num4 * num2 / num3;
			if (num4 <= 0)
			{
				continue;
			}
			int num5 = Mathf.FloorToInt((float)num4 * share);
			int num6 = num4 - num5;
			int num7 = 0;
			if (num6 > 0 && bonusByClass != null)
			{
				int num8 = Compat.MaterialClass(((Object)req.m_resItem).name);
				float num9 = ((num8 > 0 && num8 < bonusByClass.Length) ? bonusByClass[num8] : 0f);
				if (num9 > 0f)
				{
					for (int k = 0; k < num6; k++)
					{
						if (Random.value < num9)
						{
							num7++;
						}
					}
				}
			}
			int num10 = num5 + num7;
			if (num10 > 0)
			{
				int num11 = list.FindIndex((Payout p) => (Object)(object)p.Item == (Object)(object)req.m_resItem);
				if (num11 >= 0)
				{
					Payout value = list[num11];
					value.Amount += num10;
					list[num11] = value;
				}
				else
				{
					list.Add(new Payout
					{
						Item = req.m_resItem,
						Amount = num10
					});
				}
			}
		}
		return list;
	}

	internal static bool Fits(Inventory inv, List<Payout> payouts)
	{
		if (payouts.Count == 0)
		{
			return true;
		}
		int num = inv.GetEmptySlots();
		float num2 = Game.m_worldLevel;
		foreach (Payout payout in payouts)
		{
			SharedData shared = payout.Item.m_itemData.m_shared;
			int num3 = Math.Max(1, shared.m_maxStackSize);
			int num4 = inv.FindFreeStackSpace(shared.m_name, num2);
			int num5 = payout.Amount - num4;
			if (num5 > 0)
			{
				num -= (num5 + num3 - 1) / num3;
				if (num < 0)
				{
					return false;
				}
			}
		}
		return true;
	}

	internal static void Pay(Inventory inv, List<Payout> payouts, Vector3 dropAt)
	{
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		foreach (Payout payout in payouts)
		{
			int num = payout.Amount;
			int val = Math.Max(1, payout.Item.m_itemData.m_shared.m_maxStackSize);
			while (num > 0)
			{
				int num2 = Math.Min(num, val);
				num -= num2;
				ItemData val2 = payout.Item.m_itemData.Clone();
				val2.m_dropPrefab = ((Component)payout.Item).gameObject;
				val2.m_stack = num2;
				val2.m_quality = 1;
				val2.m_worldLevel = (byte)Game.m_worldLevel;
				if (!inv.AddItem(val2))
				{
					ItemDrop.DropItem(val2, num2, dropAt, Quaternion.identity);
					Plugin.Log.LogWarning((object)$"Output full while paying {((Object)payout.Item).name} x{num2}; dropped it on the ground instead");
				}
			}
		}
	}

	internal static string Describe(List<Payout> payouts)
	{
		if (payouts.Count == 0)
		{
			return "nothing";
		}
		List<string> list = new List<string>();
		foreach (Payout payout in payouts)
		{
			list.Add($"{((Object)payout.Item).name} x{payout.Amount}");
		}
		return string.Join(", ", list);
	}
}
internal class SettingsUI : MonoBehaviour
{
	private static SettingsUI _instance;

	private static TMP_FontAsset _font;

	private ShredSettings _edit;

	private RadiusRing _ring;

	private TMP_Text[] _cutValues;

	private TMP_Text _radiusValue;

	private TMP_Text _rarityValue;

	private TMP_Text _pauseValue;

	private TMP_Text _status;

	private TMP_Text _info;

	private static readonly Color Panel = new Color(0.1f, 0.08f, 0.06f, 0.96f);

	private static readonly Color Edge = new Color(0.55f, 0.42f, 0.22f, 1f);

	private static readonly Color Btn = new Color(0.3f, 0.23f, 0.14f, 1f);

	private static readonly Color BtnHi = new Color(0.45f, 0.34f, 0.18f, 1f);

	private static readonly Color Gold = new Color(1f, 0.82f, 0.45f, 1f);

	private static readonly string[] Rarities = new string[3] { "Common only", "Up to Magic", "Up to Rare" };

	internal static ShredderPiece Target { get; private set; }

	internal static bool IsOpen => (Object)(object)_instance != (Object)null;

	internal static void Open(ShredderPiece target)
	{
		//IL_