Decompiled source of Shack Workbench Pack v1.2.0

ShackWorkbenchPack.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShackWorkbenchPack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("ShackWorkbenchPack")]
[assembly: AssemblyTitle("ShackWorkbenchPack")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TheShack.WorkbenchPack
{
	internal static class Access
	{
		public delegate bool PieceRayTestFn(Player player, out Vector3 point, out Vector3 normal, out Piece piece, out Heightmap heightmap, out Collider waterSurface, bool water);

		public static FieldRef<Humanoid, ItemData> UtilityItem;

		public static FieldRef<Player, CraftingStation> CurrentStation;

		public static FieldRef<CraftingStation, List<StationExtension>> AttachedExtensions;

		public static FieldRef<CraftingStation, float> BuildRange;

		public static FieldRef<CraftingStation, CircleProjector> AreaMarkerCircle;

		public static FieldRef<VisEquipment, List<GameObject>> UtilityItemInstances;

		public static PieceRayTestFn PieceRayTest;

		public static Func<Player, bool> TakeInput;

		public static Action<InventoryGui, bool> UpdateCraftingPanel;

		public static FieldRef<InventoryGui, Recipe> CraftRecipe;

		public static FieldRef<InventoryGui, ItemData> CraftUpgradeItem;

		public static Action<Inventory> UpdateTotalWeight;

		public static FieldRef<Character, ZSyncAnimation> Zanim;

		public static void Init()
		{
			UtilityItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_utilityItem");
			CurrentStation = AccessTools.FieldRefAccess<Player, CraftingStation>("m_currentStation");
			AttachedExtensions = AccessTools.FieldRefAccess<CraftingStation, List<StationExtension>>("m_attachedExtensions");
			BuildRange = AccessTools.FieldRefAccess<CraftingStation, float>("m_buildRange");
			AreaMarkerCircle = AccessTools.FieldRefAccess<CraftingStation, CircleProjector>("m_areaMarkerCircle");
			UtilityItemInstances = AccessTools.FieldRefAccess<VisEquipment, List<GameObject>>("m_utilityItemInstances");
			PieceRayTest = Method<PieceRayTestFn>(typeof(Player), "PieceRayTest", new Type[6]
			{
				typeof(Vector3).MakeByRefType(),
				typeof(Vector3).MakeByRefType(),
				typeof(Piece).MakeByRefType(),
				typeof(Heightmap).MakeByRefType(),
				typeof(Collider).MakeByRefType(),
				typeof(bool)
			});
			TakeInput = Method<Func<Player, bool>>(typeof(Player), "TakeInput", Array.Empty<Type>());
			UpdateCraftingPanel = Method<Action<InventoryGui, bool>>(typeof(InventoryGui), "UpdateCraftingPanel", new Type[1] { typeof(bool) });
			CraftRecipe = AccessTools.FieldRefAccess<InventoryGui, Recipe>("m_craftRecipe");
			CraftUpgradeItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_craftUpgradeItem");
			UpdateTotalWeight = Method<Action<Inventory>>(typeof(Inventory), "UpdateTotalWeight", Array.Empty<Type>());
			Zanim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim");
		}

		private static T Method<T>(Type type, string name, params Type[] parameters) where T : Delegate
		{
			return AccessTools.MethodDelegate<T>(AccessTools.Method(type, name, parameters, (Type[])null) ?? throw new MissingMethodException(type.Name, name), (object)null, true);
		}
	}
	internal static class Content
	{
		public const string ItemName = "ShackWorkbenchBackpack";

		public const string PieceName = "piece_shack_workbench_backpack";

		public const string Token = "$shack_benchpack";

		public const string CutterItemName = "ShackBenchStonecutter";

		public const string CutterToken = "$shack_benchpack_cutter";

		public const string StonecutterPrefab = "piece_stonecutter";

		public const int MaxLevel = 5;

		public const string ForgeItemName = "ShackForgeBackpack";

		public const string ForgePieceName = "piece_shack_forge_backpack";

		public const string ForgeToken = "$shack_forgepack";

		public const string ForgePrefab = "forge";

		public const int ForgeMaxLevel = 7;

		public static readonly string[] ForgeUpgrades = new string[6] { "forge_ext1", "forge_ext2", "forge_ext3", "forge_ext4", "forge_ext5", "forge_ext6" };

		public static readonly string[] Upgrades = new string[4] { "piece_workbench_ext1", "piece_workbench_ext2", "piece_workbench_ext3", "piece_workbench_ext4" };

		public const string LevelKey = "theshack.bench.level";

		public const string CrafterIdKey = "theshack.bench.crafterid";

		public const string CrafterNameKey = "theshack.bench.craftername";

		public const string PlacerNameKey = "theshack.bench.placer";

		public const string DurabilityKey = "theshack.bench.durability";

		public const string CutterKey = "theshack.bench.stonecutter";

		public const string BrokenKey = "theshack.bench.broken";

		public const string PairKey = "theshack.bench.pair";

		public const string CutterData = "theshack.bench.stonecutter";

		public const string SeenData = "theshack.bench.v";

		public static readonly Vector3 PlacedScale = new Vector3(0.5f, 0.75f, 0.75f);

		private const float GroundWidth = 0.6f;

		public const float BackWidth = 0.7f;

		public static readonly Vector3 BackPosition = new Vector3(0f, 0.15f, -0.25f);

		private const float CutterWidth = 0.75f;

		private const float CutterGap = 0.1f;

		public static readonly Vector3 ForgeScale = new Vector3(0.6f, 0.6f, 0.6f);

		private const float ForgeGap = 0.15f;

		public static GameObject ItemPrefab;

		public static GameObject PiecePrefab;

		public static Piece BenchPiece;

		public static CraftingStation Workbench;

		public static CraftingStation Stonecutter;

		public static Piece StonecutterPiece;

		public static string BackBone = "Spine2";

		public static GameObject BenchModel;

		public static Bounds ModelBounds;

		public static GameObject CutterModel;

		private static Bounds cutterBounds;

		private static GameObject holder;

		public static GameObject ForgeItemPrefab;

		public static GameObject ForgePiecePrefab;

		public static Piece ForgePiece;

		public static CraftingStation Forge;

		public static Piece ForgeBuildPiece;

		public static GameObject ForgeModel;

		private static Bounds forgeBounds;

		public static Vector3 ForgeOffset;

		private static readonly Dictionary<Material, Material> movingMaterials = new Dictionary<Material, Material>();

		private static readonly int ValueNoise = Shader.PropertyToID("_ValueNoise");

		private static readonly int TriplanarLocalPos = Shader.PropertyToID("_TriplanarLocalPos");

		private static readonly int RippleDistance = Shader.PropertyToID("_RippleDistance");

		public static Bounds ForgeBoundsPlaced => new Bounds(Vector3.Scale(((Bounds)(ref forgeBounds)).center, ForgeScale), Vector3.Scale(((Bounds)(ref forgeBounds)).size, ForgeScale));

		public static bool Ready
		{
			get
			{
				if ((Object)(object)ItemPrefab != (Object)null)
				{
					return (Object)(object)PiecePrefab != (Object)null;
				}
				return false;
			}
		}

		public static bool ForgeReady
		{
			get
			{
				if ((Object)(object)ForgeItemPrefab != (Object)null)
				{
					return (Object)(object)ForgePiecePrefab != (Object)null;
				}
				return false;
			}
		}

		public static void Init()
		{
			AddWords();
			PrefabManager.OnVanillaPrefabsAvailable += Build;
			ItemManager.OnItemsRegistered += Recipes.Rebuild;
		}

		public static bool IsOurs(ItemData item)
		{
			if (item?.m_shared != null)
			{
				return item.m_shared.m_name == "$shack_benchpack";
			}
			return false;
		}

		public static bool IsOurs(SharedData shared)
		{
			if (shared != null)
			{
				return shared.m_name == "$shack_benchpack";
			}
			return false;
		}

		public static bool IsForge(ItemData item)
		{
			if (item?.m_shared != null)
			{
				return item.m_shared.m_name == "$shack_forgepack";
			}
			return false;
		}

		public static int MaxLevelOf(bool forge)
		{
			if (!forge)
			{
				return 5;
			}
			return 7;
		}

		public static bool HasCutter(ItemData item)
		{
			if (item?.m_customData != null && item.m_customData.TryGetValue("theshack.bench.stonecutter", out var value))
			{
				return value == "1";
			}
			return false;
		}

		public static void SetCutter(ItemData item, bool cutter)
		{
			if (cutter)
			{
				item.m_customData["theshack.bench.stonecutter"] = "1";
			}
			else
			{
				item.m_customData.Remove("theshack.bench.stonecutter");
			}
		}

		public static float MaxDurability(int level, bool forge = false)
		{
			return Settings.Durability.Value + (float)(Mathf.Clamp(level, 1, MaxLevelOf(forge)) - 1) * Settings.DurabilityPerLevel.Value;
		}

		public static bool Broken(ItemData item)
		{
			if (item != null)
			{
				return item.m_durability <= 0f;
			}
			return false;
		}

		public static float Weight(ItemData item)
		{
			if (!IsForge(item))
			{
				return Settings.Weight.Value + (HasCutter(item) ? Settings.CutterWeight.Value : 0f);
			}
			return Settings.ForgeWeight.Value;
		}

		public static void ApplyShared(SharedData shared, bool forge = false)
		{
			shared.m_maxQuality = MaxLevelOf(forge);
			shared.m_useDurability = true;
			shared.m_maxDurability = Settings.Durability.Value;
			shared.m_durabilityPerLevel = Settings.DurabilityPerLevel.Value;
			shared.m_durabilityDrain = 0f;
			shared.m_canBeReparied = true;
			shared.m_destroyBroken = false;
		}

		public static void ApplySettings()
		{
			if (Object.op_Implicit((Object)(object)ItemPrefab))
			{
				SharedData shared = ItemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared;
				shared.m_weight = Settings.Weight.Value;
				ApplyShared(shared);
			}
			if (Object.op_Implicit((Object)(object)ForgeItemPrefab))
			{
				SharedData shared2 = ForgeItemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared;
				shared2.m_weight = Settings.ForgeWeight.Value;
				ApplyShared(shared2, forge: true);
			}
			if (Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				Recipes.Rebuild();
			}
		}

		private static void AddWords()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "shack_benchpack", "Workbench backpack" },
				{ "shack_benchpack_desc", "A workbench you can carry. Wear it and press Tab to work from your back, or set it down from the hotbar. Upgrade it at a workbench with what the workbench's own upgrades cost." },
				{ "shack_benchpack_level", "Bench level" },
				{ "shack_benchpack_packed", "Packed upgrades" },
				{ "shack_benchpack_nothing", "none yet" },
				{ "shack_benchpack_slow", "Movement while carried" },
				{ "shack_benchpack_radius", "Build radius" },
				{ "shack_benchpack_packup", "Pack up" },
				{ "shack_benchpack_packing", "Packing up" },
				{ "shack_benchpack_notyours", "Only {0} can pack this up" },
				{ "shack_benchpack_full", "No room in your inventory: the backpack is at your feet" },
				{ "shack_benchpack_placing", "Left-click: set down   Scroll: turn   Right-click: cancel" },
				{ "shack_benchpack_badspot", "Can't set it down here" },
				{ "shack_benchpack_steep", "Too steep to set it down" },
				{ "shack_benchpack_broken", "The Workbench backpack is broken: repair it at a workbench" },
				{ "shack_benchpack_brokenplaced", "This bench is broken: pack it up and repair it at a workbench" },
				{ "shack_benchpack_brokenword", "broken" },
				{ "shack_benchpack_repair", "Repairs at bench level" },
				{ "shack_benchpack_orhigher", "or higher, not at itself" },
				{ "shack_benchpack_cutter", "Backpack stonecutter" },
				{ "shack_benchpack_cutter_desc", "Packs a stonecutter into a Workbench backpack in your inventory, so stone pieces can be built around it, worn or set down. It makes the backpack heavier." },
				{ "shack_benchpack_cutteradded", "Stonecutter packed into the Workbench backpack" },
				{ "shack_benchpack_cutterneed", "You need a Workbench backpack without a stonecutter in your inventory" },
				{ "shack_forgepack", "Forge backpack" },
				{ "shack_forgepack_desc", "A forge you can carry. It goes down beside your Workbench backpack when you set that down, and packs up with it. Upgrade it at a forge with what the forge's own upgrades cost." },
				{ "shack_forgepack_level", "Forge level" },
				{ "shack_forgepack_brokenplaced", "This forge is broken: pack it up and repair it at a forge" },
				{ "shack_forgepack_brokenleft", "The Forge backpack is broken, so it stays in your bag: repair it at a forge" },
				{ "shack_forgepack_needbench", "The Forge backpack goes down with a Workbench backpack: set that down" },
				{ "shack_forgepack_noroom", "No room for the forge beside the bench" },
				{ "shack_forgepack_repair", "Repairs at forge level" }
			});
		}

		private static void Build()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			PrefabManager.OnVanillaPrefabsAvailable -= Build;
			try
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("piece_workbench");
				Workbench = prefab.GetComponent<CraftingStation>();
				holder = new GameObject("ShackWorkbenchBackpack_models");
				holder.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)holder);
				FindBackBone();
				BuildModel(prefab);
				BuildPiece(prefab);
				BuildItem(prefab.GetComponent<Piece>());
				Plugin.Log.LogInfo((object)("Workbench backpack added (back bone " + BackBone + ", model " + $"{((Bounds)(ref ModelBounds)).size.x:0.00} x {((Bounds)(ref ModelBounds)).size.y:0.00} x {((Bounds)(ref ModelBounds)).size.z:0.00} m set down)."));
				BuildCutter();
				BuildForge();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not make the workbench backpack: " + ex));
			}
		}

		private static void FindBackBone()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("Player");
			Transform[] source = (Transform[])(Object.op_Implicit((Object)(object)prefab) ? ((Array)prefab.GetComponentsInChildren<Transform>(true)) : ((Array)new Transform[0]));
			string[] array = new string[3] { "Spine2", "Spine1", "Spine" };
			foreach (string name in array)
			{
				if (source.Any((Transform b) => ((Object)b).name == name))
				{
					BackBone = name;
					return;
				}
			}
			Plugin.Log.LogWarning((object)"No spine bone found on the player; the backpack won't show on players' backs.");
		}

		private static void BuildModel(GameObject workbench)
		{
			//IL_0047: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			BenchModel = CopyMeshes(workbench, "BenchModel");
			MeshRenderer[] componentsInChildren = BenchModel.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj in componentsInChildren)
			{
				((Renderer)obj).sharedMaterials = MovingMaterials(((Renderer)obj).sharedMaterials);
			}
			Bounds val = MeshBounds(BenchModel.transform);
			ModelBounds = new Bounds(Vector3.Scale(((Bounds)(ref val)).center, PlacedScale), Vector3.Scale(((Bounds)(ref val)).size, PlacedScale));
		}

		private static GameObject CopyMeshes(GameObject prefab, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: 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_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(holder.transform, false);
			Transform transform = prefab.transform;
			HashSet<Renderer> hashSet = new HashSet<Renderer>();
			HashSet<Renderer> hashSet2 = new HashSet<Renderer>();
			LODGroup[] componentsInChildren = prefab.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				LOD[] lODs = componentsInChildren[i].GetLODs();
				for (int j = 0; j < lODs.Length; j++)
				{
					Renderer[] renderers = lODs[j].renderers;
					foreach (Renderer val2 in renderers)
					{
						if (Object.op_Implicit((Object)(object)val2))
						{
							hashSet2.Add(val2);
							if (j == 0)
							{
								hashSet.Add(val2);
							}
						}
					}
				}
			}
			HashSet<Transform> hidden = HiddenLooks(prefab);
			int num = 0;
			int num2 = 0;
			HashSet<string> hashSet3 = new HashSet<string>();
			MeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val3 in componentsInChildren2)
			{
				if (!ShownWhenNew(((Component)val3).transform, transform, hidden) || (hashSet2.Contains((Renderer)(object)val3) && !hashSet.Contains((Renderer)(object)val3)))
				{
					num2++;
					continue;
				}
				MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh))
				{
					continue;
				}
				Matrix4x4 val4 = transform.worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix;
				GameObject val5 = new GameObject(((Object)val3).name);
				val5.transform.SetParent(val.transform, false);
				val5.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val4)).GetColumn(3));
				val5.transform.localRotation = ((Matrix4x4)(ref val4)).rotation;
				val5.transform.localScale = ((Matrix4x4)(ref val4)).lossyScale;
				val5.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
				((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterials = ((Renderer)val3).sharedMaterials;
				num++;
				Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
				foreach (Material val6 in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val6) && Object.op_Implicit((Object)(object)val6.shader))
					{
						hashSet3.Add(((Object)val6.shader).name);
					}
				}
			}
			Plugin.Log.LogInfo((object)(string.Format("{0}: {1} meshes from {2} ({3}), ", name, num, ((Object)prefab).name, string.Join(", ", hashSet3)) + $"{num2} left out (other levels of detail, worn, broken, snow, wet)."));
			return val;
		}

		public static Material[] MovingMaterials(Material[] materials)
		{
			Material[] array = (Material[])(object)new Material[materials.Length];
			for (int i = 0; i < materials.Length; i++)
			{
				array[i] = Moving(materials[i]);
			}
			return array;
		}

		private static Material Moving(Material source)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)source))
			{
				return source;
			}
			if (movingMaterials.TryGetValue(source, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			if (movingMaterials.ContainsValue(source))
			{
				return source;
			}
			value = new Material(source)
			{
				name = ((Object)source).name + " (moving)"
			};
			string text = "";
			foreach (KeyValuePair<int, float> item in new Dictionary<int, float>
			{
				{ ValueNoise, 0f },
				{ TriplanarLocalPos, 1f },
				{ RippleDistance, 0f }
			})
			{
				text += (value.HasProperty(item.Key) ? $" {value.GetFloat(item.Key):0.##}" : " -");
				value.SetFloat(item.Key, item.Value);
			}
			movingMaterials[source] = value;
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[7]
			{
				"Moving copy of material ",
				((Object)source).name,
				" (",
				null,
				null,
				null,
				null
			};
			Shader shader = source.shader;
			obj[3] = ((shader != null) ? ((Object)shader).name : null);
			obj[4] = "): noise, triplanar, ripple were";
			obj[5] = text;
			obj[6] = ".";
			log.LogInfo((object)string.Concat(obj));
			return value;
		}

		public static HashSet<Transform> HiddenLooks(GameObject piece)
		{
			HashSet<Transform> hashSet = new HashSet<Transform>();
			WearNTear component = piece.GetComponent<WearNTear>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return hashSet;
			}
			GameObject[] array = (GameObject[])(object)new GameObject[3] { component.m_worn, component.m_broken, component.m_wet };
			foreach (GameObject val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)component.m_new)
				{
					hashSet.Add(val.transform);
				}
			}
			MeshRenderer[] array2 = (MeshRenderer[])(object)new MeshRenderer[3] { component.m_snow, component.m_snowWorn, component.m_snowBroken };
			foreach (MeshRenderer val2 in array2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					hashSet.Add(((Component)val2).transform);
				}
			}
			return hashSet;
		}

		private static bool ShownWhenNew(Transform t, Transform root, HashSet<Transform> hidden)
		{
			while ((Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)root)
			{
				if (!((Component)t).gameObject.activeSelf || hidden.Contains(t))
				{
					return false;
				}
				t = t.parent;
			}
			return true;
		}

		private static Bounds MeshBounds(Transform model)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//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_008c: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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)
			bool flag = false;
			Bounds result = default(Bounds);
			MeshFilter[] componentsInChildren = ((Component)model).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				Bounds bounds = val.sharedMesh.bounds;
				Matrix4x4 val2 = model.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
					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;
		}

		public static Transform NewModel(Transform parent, float width)
		{
			//IL_001f: 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)
			GameObject val = Object.Instantiate<GameObject>(BenchModel, parent, false);
			((Object)val).name = "bench";
			FitModel(val.transform, width, Vector3.zero, Quaternion.identity);
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.layer = ((Component)parent).gameObject.layer;
			}
			return val.transform;
		}

		public static void FitModel(Transform model, float width, Vector3 position, Quaternion rotation)
		{
			//IL_001f: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0073: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			float num = (Object.op_Implicit((Object)(object)model.parent) ? Mathf.Max(0.0001f, model.parent.lossyScale.x) : 1f);
			float num2 = width / Mathf.Max(0.01f, ((Bounds)(ref ModelBounds)).size.x);
			model.localScale = PlacedScale * (num2 / num);
			model.localRotation = rotation;
			model.localPosition = (position - rotation * (((Bounds)(ref ModelBounds)).center * num2)) / num;
		}

		private static void BuildPiece(GameObject workbench)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			PiecePrefab = BuildStationPiece(workbench, "piece_shack_workbench_backpack", "$shack_benchpack", PlacedScale);
			BenchPiece = PiecePrefab.GetComponent<Piece>();
		}

		private static GameObject BuildStationPiece(GameObject source, string name, string token, Vector3 scale)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(name, source);
			CraftingStation component = val.GetComponent<CraftingStation>();
			Piece component2 = val.GetComponent<Piece>();
			component2.m_name = token;
			component2.m_description = token + "_desc";
			Transform transform = val.transform;
			HashSet<Transform> hashSet = new HashSet<Transform>();
			if (Object.op_Implicit((Object)(object)component.m_areaMarker))
			{
				hashSet.Add(TopChild(transform, component.m_areaMarker.transform));
			}
			if (Object.op_Implicit((Object)(object)component.m_effectAreaCollider))
			{
				hashSet.Add(TopChild(transform, ((Component)component.m_effectAreaCollider).transform));
			}
			GameObject val2 = new GameObject("scaled")
			{
				layer = val.layer
			};
			val2.transform.SetParent(transform, false);
			foreach (Transform item in ((IEnumerable)transform).Cast<Transform>().ToList())
			{
				if ((Object)(object)item != (Object)(object)val2.transform && !hashSet.Contains(item))
				{
					item.SetParent(val2.transform, false);
				}
			}
			val2.transform.localScale = scale;
			val.AddComponent<PlacedBench>();
			PrefabManager.Instance.AddPrefab(val);
			return val;
		}

		private static Transform TopChild(Transform root, Transform t)
		{
			while ((Object)(object)t != (Object)null && (Object)(object)t.parent != (Object)(object)root)
			{
				t = t.parent;
			}
			return t;
		}

		private static void BuildItem(Piece workbenchPiece)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			ItemConfig val = new ItemConfig();
			val.Name = "$shack_benchpack";
			val.Description = "$shack_benchpack_desc";
			val.CraftingStation = CraftingStations.Workbench;
			val.MinStationLevel = 1;
			val.Weight = Settings.Weight.Value;
			val.Icon = workbenchPiece.m_icon;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("Wood", 10, 0, true),
				new RequirementConfig("DeerHide", 2, 0, true)
			};
			ItemConfig val2 = val;
			CustomItem val3 = new CustomItem("ShackWorkbenchBackpack", "BeltStrength", val2);
			ItemPrefab = val3.ItemPrefab;
			SharedData shared = val3.ItemDrop.m_itemData.m_shared;
			shared.m_maxQuality = 5;
			shared.m_maxStackSize = 1;
			shared.m_equipStatusEffect = null;
			shared.m_setStatusEffect = null;
			shared.m_setName = "";
			shared.m_setSize = 0;
			shared.m_movementModifier = 0f;
			shared.m_scaleWeightByQuality = 0f;
			shared.m_teleportable = true;
			shared.m_value = 0;
			ApplyShared(shared);
			foreach (Transform item in ((IEnumerable)ItemPrefab.transform).Cast<Transform>().ToList())
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
			LODGroup component = ItemPrefab.GetComponent<LODGroup>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			Transform obj = NewModel(ItemPrefab.transform, 0.6f);
			BoxCollider val4 = ((Component)obj).gameObject.AddComponent<BoxCollider>();
			Bounds val5 = MeshBounds(obj);
			val4.center = ((Bounds)(ref val5)).center;
			val4.size = ((Bounds)(ref val5)).size;
			GameObject val6 = new GameObject("attach_" + BackBone);
			val6.transform.SetParent(ItemPrefab.transform, false);
			val6.SetActive(false);
			NewModel(val6.transform, 0.7f);
			ItemManager.Instance.AddItem(val3);
		}

		private static void BuildCutter()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//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_008e: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_stonecutter");
			Stonecutter = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<CraftingStation>() : null);
			StonecutterPiece = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Piece>() : null);
			if (!Object.op_Implicit((Object)(object)Stonecutter) || !Object.op_Implicit((Object)(object)StonecutterPiece))
			{
				Plugin.Log.LogWarning((object)"No stonecutter in this game version; backpacks can't get one.");
				return;
			}
			CutterModel = CopyMeshes(prefab, "CutterModel");
			cutterBounds = MeshBounds(CutterModel.transform);
			ItemConfig val = new ItemConfig();
			val.Name = "$shack_benchpack_cutter";
			val.Description = "$shack_benchpack_cutter_desc";
			val.CraftingStation = "piece_stonecutter";
			val.MinStationLevel = 1;
			val.Icon = StonecutterPiece.m_icon;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig("Wood", 10, 0, true)
			};
			ItemConfig val2 = val;
			CustomItem val3 = new CustomItem("ShackBenchStonecutter", "Wood", val2);
			SharedData shared = val3.ItemDrop.m_itemData.m_shared;
			shared.m_maxStackSize = 1;
			shared.m_weight = 0f;
			shared.m_value = 0;
			shared.m_teleportable = true;
			ItemManager.Instance.AddItem(val3);
			Plugin.Log.LogInfo((object)("Backpack stonecutter added (cost " + string.Join(", ", StonecutterPiece.m_resources.Select((Requirement r) => string.Format("{0} {1}", Object.op_Implicit((Object)(object)r.m_resItem) ? ((Object)r.m_resItem).name : "?", r.m_amount))) + ", " + $"vanilla build radius {Stonecutter.m_rangeBuild:0} m, craft tab {Stonecutter.m_hasCraftTab}, " + $"model {((Bounds)(ref cutterBounds)).size.x:0.00} m wide)."));
		}

		private static void BuildForge()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_00c2: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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)
			GameObject prefab = PrefabManager.Instance.GetPrefab("forge");
			Forge = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<CraftingStation>() : null);
			ForgeBuildPiece = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Piece>() : null);
			if (!Object.op_Implicit((Object)(object)Forge) || !Object.op_Implicit((Object)(object)ForgeBuildPiece))
			{
				Plugin.Log.LogWarning((object)"No forge in this game version; there is no forge backpack.");
				return;
			}
			ForgeModel = CopyMeshes(prefab, "ForgeModel");
			forgeBounds = MeshBounds(ForgeModel.transform);
			ForgeOffset = new Vector3(((Bounds)(ref ModelBounds)).min.x - 0.15f - ((Bounds)(ref forgeBounds)).max.x * ForgeScale.x, 0f, ((Bounds)(ref ModelBounds)).center.z - ((Bounds)(ref forgeBounds)).center.z * ForgeScale.z);
			ForgePiecePrefab = BuildStationPiece(prefab, "piece_shack_forge_backpack", "$shack_forgepack", ForgeScale);
			ForgePiece = ForgePiecePrefab.GetComponent<Piece>();
			BuildForgeItem();
			Plugin.Log.LogInfo((object)("Forge backpack added (cost " + string.Join(", ", ForgeBuildPiece.m_resources.Select((Requirement r) => string.Format("{0} {1}", Object.op_Implicit((Object)(object)r.m_resItem) ? ((Object)r.m_resItem).name : "?", r.m_amount))) + ", " + $"vanilla build radius {Forge.m_rangeBuild:0} m (+{Forge.m_extraRangePerLevel:0.#} per level), model {((Bounds)(ref forgeBounds)).size.x * ForgeScale.x:0.00} m wide set down, " + $"{ForgeOffset.x:0.00} m beside the bench)."));
		}

		private static void BuildForgeItem()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00a5: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			ItemConfig val = new ItemConfig();
			val.Name = "$shack_forgepack";
			val.Description = "$shack_forgepack_desc";
			val.CraftingStation = CraftingStations.Forge;
			val.MinStationLevel = 1;
			val.Weight = Settings.ForgeWeight.Value;
			val.Icon = ForgeBuildPiece.m_icon;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig("Wood", 10, 0, true)
			};
			ItemConfig val2 = val;
			CustomItem val3 = new CustomItem("ShackForgeBackpack", "BeltStrength", val2);
			ForgeItemPrefab = val3.ItemPrefab;
			SharedData shared = val3.ItemDrop.m_itemData.m_shared;
			shared.m_itemType = (ItemType)16;
			shared.m_maxStackSize = 1;
			shared.m_equipStatusEffect = null;
			shared.m_setStatusEffect = null;
			shared.m_setName = "";
			shared.m_setSize = 0;
			shared.m_movementModifier = 0f;
			shared.m_scaleWeightByQuality = 0f;
			shared.m_teleportable = true;
			shared.m_value = 0;
			ApplyShared(shared, forge: true);
			foreach (Transform item in ((IEnumerable)ForgeItemPrefab.transform).Cast<Transform>().ToList())
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
			LODGroup component = ForgeItemPrefab.GetComponent<LODGroup>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			Transform transform = Object.Instantiate<GameObject>(ForgeModel, ForgeItemPrefab.transform, false).transform;
			((Object)transform).name = "forge";
			float num = 0.6f / Mathf.Max(0.01f, ((Bounds)(ref forgeBounds)).size.x);
			transform.localScale = Vector3.one * num;
			transform.localPosition = -((Bounds)(ref forgeBounds)).center * num;
			MeshRenderer[] componentsInChildren = ((Component)transform).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj in componentsInChildren)
			{
				((Renderer)obj).sharedMaterials = MovingMaterials(((Renderer)obj).sharedMaterials);
			}
			Transform[] componentsInChildren2 = ((Component)transform).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Component)componentsInChildren2[i]).gameObject.layer = ForgeItemPrefab.layer;
			}
			BoxCollider obj2 = ForgeItemPrefab.AddComponent<BoxCollider>();
			obj2.center = Vector3.zero;
			obj2.size = ((Bounds)(ref forgeBounds)).size * num;
			ItemManager.Instance.AddItem(val3);
		}

		public static void AddForgeModel(Transform bench)
		{
			//IL_003c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)ForgeModel) && !Object.op_Implicit((Object)(object)bench.Find("forgepack")))
			{
				GameObject obj = Object.Instantiate<GameObject>(ForgeModel, bench, false);
				((Object)obj).name = "forgepack";
				obj.transform.localScale = ForgeScale;
				obj.transform.localRotation = Quaternion.identity;
				obj.transform.localPosition = ForgeOffset;
				Transform[] componentsInChildren = obj.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.layer = ((Component)bench).gameObject.layer;
				}
			}
		}

		public static void AddCutterModel(Transform bench)
		{
			//IL_0045: 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_0062: 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_0081: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)CutterModel) && !Object.op_Implicit((Object)(object)bench.Find("stonecutter")))
			{
				GameObject obj = Object.Instantiate<GameObject>(CutterModel, bench, false);
				((Object)obj).name = "stonecutter";
				float num = 0.75f / Mathf.Max(0.01f, ((Bounds)(ref cutterBounds)).size.x);
				obj.transform.localScale = Vector3.one * num;
				obj.transform.localRotation = Quaternion.identity;
				Vector3 val = ((Bounds)(ref cutterBounds)).min * num;
				Vector3 val2 = ((Bounds)(ref cutterBounds)).center * num;
				obj.transform.localPosition = new Vector3(((Bounds)(ref ModelBounds)).max.x + 0.1f - val.x, ((Bounds)(ref ModelBounds)).min.y - val.y, ((Bounds)(ref ModelBounds)).center.z - val2.z);
				Transform[] componentsInChildren = obj.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.layer = ((Component)bench).gameObject.layer;
				}
			}
		}

		public static void DropBackpack(Vector3 position, Quaternion rotation, int level, long crafterId, string crafterName, float durability, bool cutter, bool forge = false)
		{
			//IL_0094: 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)
			GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(forge ? "ShackForgeBackpack" : "ShackWorkbenchBackpack") : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				ItemData obj = val.GetComponent<ItemDrop>().m_itemData.Clone();
				obj.m_dropPrefab = val;
				obj.m_stack = 1;
				obj.m_quality = Mathf.Clamp(level, 1, MaxLevelOf(forge));
				obj.m_crafterID = crafterId;
				obj.m_crafterName = crafterName ?? "";
				obj.m_worldLevel = (byte)Game.m_worldLevel;
				SetState(obj, durability, cutter);
				ItemDrop.DropItem(obj, 1, position, rotation);
			}
		}

		public static void SetState(ItemData item, float durability, bool cutter)
		{
			bool flag = IsForge(item);
			item.m_durability = Mathf.Clamp(durability, 0f, MaxDurability(item.m_quality, flag));
			SetCutter(item, cutter && !flag);
			item.m_customData["theshack.bench.v"] = "1";
		}

		public static string ForgeTooltip(int level)
		{
			Localization instance = Localization.instance;
			List<string> list = new List<string>();
			for (int i = 0; i < ForgeUpgrades.Length && i < level - 1; i++)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(ForgeUpgrades[i]);
				Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					list.Add(instance.Localize(val.m_name));
				}
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(string.Format("\n{0}: <color=orange>{1}</color>", instance.Localize("$shack_forgepack_level"), level));
			stringBuilder.Append("\n" + instance.Localize("$shack_benchpack_packed") + ": <color=orange>" + ((list.Count > 0) ? string.Join(", ", list) : instance.Localize("$shack_benchpack_nothing")) + "</color>");
			if (Settings.ForgeSlowPercent.Value > 0)
			{
				stringBuilder.Append(string.Format("\n{0}: <color=orange>-{1}%</color>", instance.Localize("$shack_benchpack_slow"), Settings.ForgeSlowPercent.Value));
			}
			if (Settings.RepairNeedsLevel.Value)
			{
				stringBuilder.Append(string.Format("\n{0}: <color=orange>{1}</color> ", instance.Localize("$shack_forgepack_repair"), level) + instance.Localize("$shack_benchpack_orhigher"));
			}
			return stringBuilder.ToString();
		}

		public static string Tooltip(int level, bool cutter)
		{
			Localization instance = Localization.instance;
			List<string> list = new List<string>();
			for (int i = 0; i < Upgrades.Length && i < level - 1; i++)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(Upgrades[i]);
				Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					list.Add(instance.Localize(val.m_name));
				}
			}
			if (cutter && Object.op_Implicit((Object)(object)StonecutterPiece))
			{
				list.Add(instance.Localize(StonecutterPiece.m_name));
			}
			float num = Stations.Radius(level);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(string.Format("\n{0}: <color=orange>{1}</color>", instance.Localize("$shack_benchpack_level"), level));
			stringBuilder.Append("\n" + instance.Localize("$shack_benchpack_packed") + ": <color=orange>" + ((list.Count > 0) ? string.Join(", ", list) : instance.Localize("$shack_benchpack_nothing")) + "</color>");
			if (Settings.SlowPercent.Value > 0)
			{
				stringBuilder.Append(string.Format("\n{0}: <color=orange>-{1}%</color>", instance.Localize("$shack_benchpack_slow"), Settings.SlowPercent.Value));
			}
			stringBuilder.Append(string.Format("\n{0}: <color=orange>{1:0} m</color>", instance.Localize("$shack_benchpack_radius"), num));
			if (Settings.RepairNeedsLevel.Value)
			{
				stringBuilder.Append(string.Format("\n{0}: <color=orange>{1}</color> ", instance.Localize("$shack_benchpack_repair"), level) + instance.Localize("$shack_benchpack_orhigher"));
			}
			return stringBuilder.ToString();
		}
	}
	internal static class Durability
	{
		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class InventoryGui_DoCrafting
		{
			private static void Prefix(InventoryGui __instance)
			{
				Recipe val = Access.CraftRecipe.Invoke(__instance);
				Player localPlayer = Player.m_localPlayer;
				CraftingStation val2 = (Object.op_Implicit((Object)(object)localPlayer) ? localPlayer.GetCurrentCraftingStation() : null);
				crafting = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.m_craftingStation) && Object.op_Implicit((Object)(object)val2) && val.m_craftingStation.m_name == val2.m_name) ? Stations.Current(localPlayer) : null);
			}

			private static void Finalizer()
			{
				crafting = null;
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private static class Player_ConsumeResources
		{
			private static void Postfix(int multiplier)
			{
				if (Durability.crafting != null)
				{
					IBench crafting = Durability.crafting;
					Durability.crafting = null;
					crafting.Wear(Settings.WearPerUse.Value * (float)Mathf.Max(1, multiplier));
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "RepairOneItem")]
		private static class InventoryGui_RepairOneItem
		{
			private static void Prefix()
			{
				Player localPlayer = Player.m_localPlayer;
				repairing = Stations.Current(localPlayer);
				wornBefore = ((repairing != null) ? CountWorn(localPlayer) : 0);
			}

			private static void Postfix()
			{
				IBench repairing = Durability.repairing;
				Durability.repairing = null;
				if (repairing != null && Object.op_Implicit((Object)(object)Player.m_localPlayer) && CountWorn(Player.m_localPlayer) < wornBefore)
				{
					repairing.Wear(Settings.WearPerUse.Value);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "CanRepair")]
		private static class InventoryGui_CanRepair
		{
			private static void Postfix(ItemData item, ref bool __result)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!__result || (!Content.IsOurs(item) && !Content.IsForge(item)) || !Object.op_Implicit((Object)(object)localPlayer) || localPlayer.NoCostCheat())
				{
					return;
				}
				CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
				if (Object.op_Implicit((Object)(object)currentCraftingStation))
				{
					if (Stations.TryGet(currentCraftingStation, out var bench) && bench is BackBench backBench && backBench.IsFor(item))
					{
						__result = false;
					}
					else if (Settings.RepairNeedsLevel.Value && currentCraftingStation.GetLevel(true) < item.m_quality)
					{
						__result = false;
					}
				}
			}
		}

		private static IBench crafting;

		private static IBench repairing;

		private static int wornBefore;

		private static readonly List<ItemData> worn = new List<ItemData>();

		private static int CountWorn(Player player)
		{
			worn.Clear();
			((Humanoid)player).GetInventory().GetWornItems(worn);
			return worn.Count;
		}
	}
	internal static class Header
	{
		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		private static class InventoryGui_UpdateRecipe
		{
			private static void Postfix(InventoryGui __instance, Player player)
			{
				//IL_0140: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				CraftingStation val = (Object.op_Implicit((Object)(object)player) ? player.GetCurrentCraftingStation() : null);
				IBench bench;
				bool flag = Stations.TryGet(val, out bench) && bench.HasCutter && Object.op_Implicit((Object)(object)Content.StonecutterPiece);
				TMP_Text craftingStationName = __instance.m_craftingStationName;
				Image craftingStationIcon = __instance.m_craftingStationIcon;
				if (!Object.op_Implicit((Object)(object)craftingStationName) || !Object.op_Implicit((Object)(object)craftingStationIcon))
				{
					return;
				}
				if (nameSize < 0f)
				{
					nameSize = craftingStationName.fontSize;
					nameAutoSize = craftingStationName.enableAutoSizing;
				}
				if (flag)
				{
					Localization instance = Localization.instance;
					craftingStationName.text = instance.Localize(val.m_name) + " + " + instance.Localize(Content.StonecutterPiece.m_name);
					craftingStationName.enableAutoSizing = true;
					craftingStationName.fontSizeMax = nameSize;
					craftingStationName.fontSizeMin = nameSize * 0.5f;
				}
				else if (craftingStationName.enableAutoSizing != nameAutoSize)
				{
					craftingStationName.enableAutoSizing = nameAutoSize;
					craftingStationName.fontSize = nameSize;
				}
				if (flag && !Object.op_Implicit((Object)(object)cutterIcon))
				{
					cutterIcon = Object.Instantiate<Image>(craftingStationIcon, ((Component)craftingStationIcon).transform.parent);
					((Object)cutterIcon).name = "ShackStonecutterIcon";
					RectTransform rectTransform = ((Graphic)craftingStationIcon).rectTransform;
					RectTransform rectTransform2 = ((Graphic)cutterIcon).rectTransform;
					Vector2 anchoredPosition = rectTransform.anchoredPosition;
					Rect rect = rectTransform.rect;
					rectTransform2.anchoredPosition = anchoredPosition + new Vector2(((Rect)(ref rect)).width * 0.9f, 0f);
				}
				if (Object.op_Implicit((Object)(object)cutterIcon))
				{
					((Component)cutterIcon).gameObject.SetActive(flag);
					if (flag)
					{
						cutterIcon.sprite = Content.StonecutterPiece.m_icon;
					}
				}
			}
		}

		private static Image cutterIcon;

		private static float nameSize = -1f;

		private static bool nameAutoSize;
	}
	internal static class PackingUp
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static class Player_GetActionProgress
		{
			private static void Postfix(Player __instance, ref string name, ref float progress, ref MinorActionData data)
			{
				if (Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && string.IsNullOrEmpty(name))
				{
					name = PackingUp.progress.m_progressText;
					progress = Mathf.Clamp01(elapsed / PackingUp.progress.m_duration);
					data = PackingUp.progress;
				}
			}
		}

		private const float ExtraReach = 1f;

		private const string Animation = "equipping";

		private static PlacedBench bench;

		private static bool animating;

		private static float elapsed;

		private static readonly MinorActionData progress = new MinorActionData();

		public static bool Active => Object.op_Implicit((Object)(object)bench);

		private static float Duration
		{
			get
			{
				float num = (Object.op_Implicit((Object)(object)Content.ItemPrefab) ? Content.ItemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_equipDuration : 1f);
				return Mathf.Max(1f, num);
			}
		}

		public static void Start(Player player, PlacedBench target)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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)
			if (!((Object)(object)bench == (Object)(object)target) && target.MayStartPackUp(player))
			{
				Stop(player);
				bench = target;
				elapsed = 0f;
				progress.m_duration = Duration;
				progress.m_progressText = "$shack_benchpack_packing " + target.Token;
				ZSyncAnimation obj = Access.Zanim.Invoke((Character)(object)player);
				if (obj != null)
				{
					obj.SetBool("equipping", true);
				}
				animating = true;
				player.m_equipStartEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
		}

		private static void Stop(Player player)
		{
			if (animating && Object.op_Implicit((Object)(object)player))
			{
				ZSyncAnimation obj = Access.Zanim.Invoke((Character)(object)player);
				if (obj != null)
				{
					obj.SetBool("equipping", false);
				}
			}
			animating = false;
			bench = null;
		}

		public static void Update()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (bench == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			CraftingStation val = (Object.op_Implicit((Object)(object)bench) ? ((Component)bench).GetComponent<CraftingStation>() : null);
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !Object.op_Implicit((Object)(object)val) || ((Character)localPlayer).InAttack() || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)bench).transform.position) > val.m_useDistance + 1f)
			{
				Stop(localPlayer);
				return;
			}
			elapsed += Time.deltaTime;
			if (elapsed >= progress.m_duration)
			{
				PlacedBench placedBench = bench;
				PlacedBench placedBench2 = placedBench.Partner();
				Stop(localPlayer);
				placedBench.RequestPackUp(localPlayer);
				if (Object.op_Implicit((Object)(object)placedBench2) && placedBench2.MayPackUp(localPlayer, showMessage: false))
				{
					placedBench2.RequestPackUp(localPlayer);
				}
			}
		}
	}
	internal class PlacedBench : MonoBehaviour, IBench
	{
		public class PendingInfo
		{
			public bool Forge;

			public int Level;

			public long CrafterId;

			public string CrafterName;

			public string Placer;

			public float Durability;

			public bool Cutter;

			public long Pair;

			public bool Created;
		}

		[HarmonyPatch(typeof(Game), "Start")]
		private static class Game_Start
		{
			private static void Postfix()
			{
				ZRoutedRpc.instance.Register<ZPackage>("TheShack_BenchPacked", (Action<long, ZPackage>)RPC_Packed);
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		private static class Piece_DropResources
		{
			private static bool Prefix(Piece __instance)
			{
				PlacedBench component = ((Component)__instance).GetComponent<PlacedBench>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					return true;
				}
				component.DropAsItem();
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		private static class Player_RemovePiece
		{
			private static void Prefix()
			{
				removing = true;
			}

			private static void Finalizer()
			{
				removing = false;
			}
		}

		[HarmonyPatch(typeof(Player), "CheckCanRemovePiece")]
		private static class Player_CheckCanRemovePiece
		{
			private static void Postfix(Player __instance, Piece piece, ref bool __result)
			{
				if ((removing & __result) && Object.op_Implicit((Object)(object)piece))
				{
					PlacedBench component = ((Component)piece).GetComponent<PlacedBench>();
					if (component != null && !component.MayPackUp(__instance, showMessage: true))
					{
						__result = false;
					}
				}
			}
		}

		public static PendingInfo Pending;

		public static PlacedBench LastCreated;

		private static readonly List<PlacedBench> all = new List<PlacedBench>();

		private const float PairReach = 6f;

		private const string PackUpRpc = "TheShack_BenchPackUp";

		private const string PackedRpc = "TheShack_BenchPacked";

		private const string WearRpc = "TheShack_BenchWear";

		private ZNetView nview;

		private Piece piece;

		private CraftingStation station;

		private CraftingStation cutter;

		private static float askedAt = -100f;

		private static int awaited;

		private const float WearReach = 10f;

		private const float ReplyWindow = 15f;

		private static bool removing;

		public bool Worn => false;

		public bool IsForge { get; private set; }

		public string Token
		{
			get
			{
				if (!IsForge)
				{
					return "$shack_benchpack";
				}
				return "$shack_forgepack";
			}
		}

		public int Level
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)nview) || !nview.IsValid())
				{
					return 1;
				}
				return Mathf.Clamp(nview.GetZDO().GetInt("theshack.bench.level", 1), 1, Content.MaxLevelOf(IsForge));
			}
		}

		public float Durability
		{
			get
			{
				float num = Content.MaxDurability(Level, IsForge);
				float num2 = ((Object.op_Implicit((Object)(object)nview) && nview.IsValid()) ? nview.GetZDO().GetFloat("theshack.bench.durability", -1f) : (-1f));
				if (!(num2 < 0f))
				{
					return Mathf.Min(num2, num);
				}
				return num;
			}
		}

		public bool Broken => Durability <= 0f;

		public bool HasCutter
		{
			get
			{
				if (!IsForge && Object.op_Implicit((Object)(object)nview) && nview.IsValid())
				{
					return nview.GetZDO().GetBool("theshack.bench.stonecutter", false);
				}
				return false;
			}
		}

		private long Pair
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)nview) || !nview.IsValid())
				{
					return 0L;
				}
				return nview.GetZDO().GetLong("theshack.bench.pair", 0L);
			}
		}

		private void Awake()
		{
			nview = ((Component)this).GetComponent<ZNetView>();
			piece = ((Component)this).GetComponent<Piece>();
			station = ((Component)this).GetComponent<CraftingStation>();
			IsForge = Object.op_Implicit((Object)(object)piece) && piece.m_name == "$shack_forgepack";
			if (Object.op_Implicit((Object)(object)station))
			{
				Stations.Register(station, this, IsForge ? Role.Forge : Role.Workbench);
			}
			if (Object.op_Implicit((Object)(object)nview) && nview.GetZDO() != null)
			{
				all.Add(this);
				nview.Register("TheShack_BenchPackUp", (Action<long>)RPC_PackUp);
				nview.Register<float>("TheShack_BenchWear", (Action<long, float>)RPC_Wear);
				TakePending();
				if (HasCutter)
				{
					cutter = Stonecutter.AddStation(((Component)this).gameObject, this);
					Content.AddCutterModel(((Component)this).transform);
				}
			}
		}

		private void TakePending()
		{
			if (Pending != null && !Pending.Created && Pending.Forge == IsForge && nview.IsOwner())
			{
				Pending.Created = true;
				LastCreated = this;
				ZDO zDO = nview.GetZDO();
				zDO.Set("theshack.bench.level", Mathf.Clamp(Pending.Level, 1, Content.MaxLevelOf(IsForge)));
				zDO.Set("theshack.bench.crafterid", Pending.CrafterId);
				zDO.Set("theshack.bench.craftername", Pending.CrafterName ?? "");
				zDO.Set("theshack.bench.placer", Pending.Placer ?? "");
				zDO.Set("theshack.bench.durability", Mathf.Max(0f, Pending.Durability));
				zDO.Set("theshack.bench.stonecutter", Pending.Cutter && !IsForge);
				if (Pending.Pair != 0L)
				{
					zDO.Set("theshack.bench.pair", Pending.Pair);
				}
			}
		}

		public PlacedBench Partner()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			long pair = Pair;
			if (pair == 0L)
			{
				return null;
			}
			foreach (PlacedBench item in all)
			{
				if (Object.op_Implicit((Object)(object)item) && (Object)(object)item != (Object)(object)this && item.IsForge != IsForge && item.Pair == pair && Vector3.Distance(((Component)item).transform.position, ((Component)this).transform.position) < 6f)
				{
					return item;
				}
			}
			return null;
		}

		private void OnDestroy()
		{
			all.Remove(this);
			Stations.Unregister(station);
			Stations.Unregister(cutter);
		}

		public void Wear(float amount)
		{
			if (amount > 0f && Object.op_Implicit((Object)(object)nview) && nview.IsValid())
			{
				nview.InvokeRPC("TheShack_BenchWear", new object[1] { amount });
			}
		}

		private void RPC_Wear(long sender, float amount)
		{
			//IL_0055: 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)
			if (!nview.IsValid() || !nview.IsOwner() || float.IsNaN(amount))
			{
				return;
			}
			Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)delegate(Player p)
			{
				//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)
				if (Object.op_Implicit((Object)(object)p))
				{
					ZDOID zDOID = ((Character)p).GetZDOID();
					return ((ZDOID)(ref zDOID)).UserID == sender;
				}
				return false;
			});
			if (Object.op_Implicit((Object)(object)val) && !(Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position) > 10f))
			{
				float num = Mathf.Max(0f, Durability - Mathf.Clamp(amount, 0f, 1000f));
				nview.GetZDO().Set("theshack.bench.durability", num);
			}
		}

		public bool MayPackUp(Player player, bool showMessage)
		{
			long num = (Object.op_Implicit((Object)(object)piece) ? piece.GetCreator() : 0);
			if (!Settings.OwnerOnly.Value || num == 0L || num == player.GetPlayerID() || SynchronizationManager.Instance.PlayerIsAdmin)
			{
				return true;
			}
			if (showMessage)
			{
				string text = ((Object.op_Implicit((Object)(object)nview) && nview.IsValid()) ? nview.GetZDO().GetString("theshack.bench.placer", "") : "");
				((Character)player).Message((MessageType)2, string.Format(Localization.instance.Localize("$shack_benchpack_notyours"), (text.Length > 0) ? text : "?"), 0, (Sprite)null, false);
			}
			return false;
		}

		public bool MayStartPackUp(Player player)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)nview) || !nview.IsValid() || !MayPackUp(player, showMessage: true))
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				((Character)player).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false);
				return false;
			}
			return true;
		}

		public void RequestPackUp(Player player)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)nview) || !nview.IsValid() || !MayPackUp(player, showMessage: true))
			{
				return;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				((Character)player).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false);
				return;
			}
			if (Time.time - askedAt > 15f)
			{
				awaited = 0;
			}
			askedAt = Time.time;
			awaited++;
			nview.InvokeRPC("TheShack_BenchPackUp", Array.Empty<object>());
		}

		private void RPC_PackUp(long sender)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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)
			if (!nview.IsValid() || !nview.IsOwner())
			{
				return;
			}
			ZDO zDO = nview.GetZDO();
			ZPackage val = new ZPackage();
			val.Write(Level);
			val.Write(zDO.GetLong("theshack.bench.crafterid", 0L));
			val.Write(zDO.GetString("theshack.bench.craftername", ""));
			val.Write(((Component)this).transform.position);
			val.Write(Durability);
			val.Write(HasCutter);
			val.Write(IsForge);
			if (Object.op_Implicit((Object)(object)piece))
			{
				piece.m_placeEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
			int num;
			if (sender != ZDOMan.GetSessionID())
			{
				num = (ZNet.instance.GetPlayerList().Any((PlayerInfo p) => ((ZDOID)(ref p.m_characterID)).UserID == sender) ? 1 : 0);
				if (num == 0)
				{
					DropAsItem();
				}
			}
			else
			{
				num = 1;
			}
			ZNetScene.instance.Destroy(((Component)this).gameObject);
			if (num != 0)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "TheShack_BenchPacked", new object[1] { val });
			}
		}

		private static void RPC_Packed(long sender, ZPackage package)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			if (awaited <= 0 || Time.time - askedAt > 15f)
			{
				awaited = 0;
				Plugin.Log.LogWarning((object)$"Ignored a packed bench nobody here asked for (from {sender}).");
				return;
			}
			if (--awaited <= 0)
			{
				askedAt = -100f;
			}
			long crafterId;
			string text;
			Vector3 val;
			float num2;
			bool flag2;
			int num;
			bool flag;
			try
			{
				num = package.ReadInt();
				crafterId = package.ReadLong();
				text = package.ReadString() ?? "";
				val = package.ReadVector3();
				num2 = package.ReadSingle();
				flag = package.ReadBool();
				flag2 = package.ReadBool();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Ignored a malformed packed-bench message: " + ex.Message));
				return;
			}
			num = Mathf.Clamp(num, 1, Content.MaxLevelOf(flag2));
			flag = flag && !flag2;
			if (text.Length > 64)
			{
				text = text.Substring(0, 64);
			}
			if (float.IsNaN(num2))
			{
				num2 = 0f;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				Content.DropBackpack(val + Vector3.up * 0.5f, Quaternion.identity, num, crafterId, text, num2, flag, flag2);
			}
			else
			{
				Give(localPlayer, flag2, num, crafterId, text, num2, flag);
			}
		}

		private static void Give(Player player, bool forge, int level, long crafterId, string crafterName, float durability, bool hasCutter)
		{
			//IL_0063: 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_0078: 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_0082: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = ((Humanoid)player).GetInventory();
			GameObject val = (forge ? Content.ForgeItemPrefab : Content.ItemPrefab);
			string text = (forge ? "$shack_forgepack" : "$shack_benchpack");
			ItemData val2 = ((Object.op_Implicit((Object)(object)val) && inventory.CanAddItem(val, 1)) ? inventory.AddItem(forge ? "ShackForgeBackpack" : "ShackWorkbenchBackpack", 1, level, 0, crafterId, crafterName, false, false) : null);
			if (val2 == null)
			{
				Content.DropBackpack(((Component)player).transform.position + ((Component)player).transform.forward * 0.6f + Vector3.up, ((Component)player).transform.rotation, level, crafterId, crafterName, durability, hasCutter, forge);
				((Character)player).Message((MessageType)2, "$shack_benchpack_full", 0, (Sprite)null, false);
				return;
			}
			Content.SetState(val2, durability, hasCutter);
			Access.UpdateTotalWeight(inventory);
			((Character)player).Message((MessageType)1, "$msg_added " + text, 1, val2.GetIcon(), false);
			if (!forge && Settings.WearAfterPackUp.Value && Access.UtilityItem.Invoke((Humanoid)(object)player) == null && !Content.Broken(val2))
			{
				((Humanoid)player).EquipItem(val2, true);
			}
		}

		private void DropAsItem()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = ((Object.op_Implicit((Object)(object)nview) && nview.IsValid()) ? nview.GetZDO() : null);
			Content.DropBackpack(((Component)this).transform.position + Vector3.up * 0.5f, ((Component)this).transform.rotation, Level, (val != null) ? val.GetLong("theshack.bench.crafterid", 0L) : 0, ((val != null) ? val.GetString("theshack.bench.craftername", "") : null) ?? "", Durability, HasCutter, IsForge);
		}
	}
	internal static class Placing
	{
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private static class Humanoid_UseItem
		{
			private static bool Prefix(Humanoid __instance, ItemData item, bool fromInventoryGui)
			{
				Player localPlayer = Player.m_localPlayer;
				if (fromInventoryGui || (Object)(object)__instance != (Object)(object)localPlayer || !Object.op_Implicit((Object)(object)localPlayer))
				{
					return true;
				}
				if (Content.IsOurs(item))
				{
					Toggle(localPlayer, item);
					return false;
				}
				if (Content.IsForge(item))
				{
					ItemData val = Worn.Item(localPlayer) ?? ((IEnumerable<ItemData>)((Humanoid)localPlayer).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)Content.IsOurs);
					if (Active)
					{
						Cancel();
					}
					else if (val != null)
					{
						Begin(localPlayer, val);
					}
					else
					{
						((Character)localPlayer).Message((MessageType)2, "$shack_forgepack_needbench", 0, (Sprite)null, false);
					}
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		private static class Player_SetControls
		{
			private static void Prefix(ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold)
			{
				if (HoldBackAttacks)
				{
					attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (block = (blockHold = false)))));
				}
			}
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		private static class ZInput_GetMouseScrollWheel
		{
			private static bool Prefix(ref float __result)
			{
				if (!Active || ReadingScroll)
				{
					return true;
				}
				__result = 0f;
				return false;
			}
		}

		private static GameObject ghost;

		private static Piece ghostPiece;

		private static BoxCollider ghostBox;

		private static ItemData item;

		private static ItemData forgeItem;

		private static Transform forgeGhost;

		private static Vector3 forgePoint;

		private static int rotation;

		private static bool holdBack;

		public static bool ReadingScroll;

		private static int characterMask;

		private static int groundMask;

		private const float MaxStep = 0.6f;

		public static bool Active => (Object)(object)ghost != (Object)null;

		public static bool HoldBackAttacks
		{
			get
			{
				if (!Active)
				{
					return holdBack;
				}
				return true;
			}
		}

		private static int CharacterMask
		{
			get
			{
				if (characterMask == 0)
				{
					return characterMask = LayerMask.GetMask(new string[4] { "character", "character_net", "character_ghost", "character_noenv" });
				}
				return characterMask;
			}
		}

		private static int GroundMask
		{
			get
			{
				if (groundMask == 0)
				{
					return groundMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" });
				}
				return groundMask;
			}
		}

		public static void Toggle(Player player, ItemData backpack)
		{
			if (Active)
			{
				Cancel();
			}
			else
			{
				Begin(player, backpack);
			}
		}

		private static void Begin(Player player, ItemData backpack)
		{
			if (!Content.Ready || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead() || backpack == null)
			{
				return;
			}
			if (Content.Broken(backpack))
			{
				((Character)player).Message((MessageType)2, "$shack_benchpack_broken", 0, (Sprite)null, false);
				return;
			}
			if (((Character)player).InPlaceMode())
			{
				((Humanoid)player).HideHandItems(false, true);
			}
			ZNetView.m_forceDisableInit = true;
			try
			{
				ghost = Object.Instantiate<GameObject>(Content.PiecePrefab);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
			((Object)ghost).name = "piece_shack_workbench_backpack_ghost";
			foreach (Transform item in Content.HiddenLooks(ghost))
			{
				((Component)item).gameObject.SetActive(false);
			}
			WearNTear component = ghost.GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_new))
			{
				component.m_new.SetActive(true);
			}
			if (Content.HasCutter(backpack))
			{
				Content.AddCutterModel(ghost.transform);
			}
			forgeItem = null;
			ItemData val = ((!Content.ForgeReady) ? null : (((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => Content.IsForge(i) && !Content.Broken(i))) ?? ((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)Content.IsForge)));
			if (val != null && Content.Broken(val))
			{
				((Character)player).Message((MessageType)2, "$shack_forgepack_brokenleft", 0, (Sprite)null, false);
			}
			else if (val != null)
			{
				forgeItem = val;
				Content.AddForgeModel(ghost.transform);
			}
			MeshRenderer[] componentsInChildren = ghost.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj in componentsInChildren)
			{
				((Renderer)obj).sharedMaterials = Content.MovingMaterials(((Renderer)obj).sharedMaterials);
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			}
			EffectArea[] componentsInChildren2 = ghost.GetComponentsInChildren<EffectArea>(true);
			for (int num = 0; num < componentsInChildren2.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[num]);
			}
			Joint[] componentsInChildren3 = ghost.GetComponentsInChildren<Joint>(true);
			for (int num = 0; num < componentsInChildren3.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[num]);
			}
			Rigidbody[] componentsInChildren4 = ghost.GetComponentsInChildren<Rigidbody>(true);
			for (int num = 0; num < componentsInChildren4.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[num]);
			}
			Collider[] componentsInChildren5 = ghost.GetComponentsInChildren<Collider>(true);
			for (int num = 0; num < componentsInChildren5.Length; num++)
			{
				componentsInChildren5[num].enabled = false;
			}
			int layer = LayerMask.NameToLayer("ghost");
			Transform[] componentsInChildren6 = ghost.GetComponentsInChildren<Transform>(true);
			for (int num = 0; num < componentsInChildren6.Length; num++)
			{
				((Component)componentsInChildren6[num]).gameObject.layer = layer;
			}
			ghostPiece = ghost.GetComponent<Piece>();
			Transform obj2 = ghost.transform.Find("scaled/collider");
			ghostBox = ((obj2 != null) ? ((Component)obj2).GetComponent<BoxCollider>() : null);
			forgeGhost = ghost.transform.Find("forgepack");
			ghost.SetActive(false);
			Placing.item = backpack;
			((Character)player).Message((MessageType)1, "$shack_benchpack_placing", 0, (Sprite)null, false);
		}

		public static void Cancel()
		{
			if (Object.op_Implicit((Object)(object)ghost))
			{
				Object.Destroy((Object)(object)ghost);
			}
			ghost = null;
			ghostPiece = null;
			ghostBox = null;
			item = null;
			forgeItem = null;
			forgeGhost = null;
			holdBack = true;
		}

		public static void Update()
		{
			//IL_0166: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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_01ff: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (holdBack && !ZInput.GetButton("Attack") && !ZInput.GetButton("Block") && !ZInput.GetButton("JoyAttack") && !ZInput.GetButton("JoyBlock"))
			{
				holdBack = false;
			}
			if (!Active)
			{
				CheckSetDownKey(localPlayer);
				return;
			}
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || item == null || !((Humanoid)localPlayer).GetInventory().ContainsItem(item) || ((Character)localPlayer).InPlaceMode() || InventoryGui.IsVisible() || Menu.IsVisible() || Minimap.IsOpen())
			{
				Cancel();
				return;
			}
			if (!Access.TakeInput(localPlayer))
			{
				ghost.SetActive(false);
				return;
			}
			if (ZInput.GetButtonDown("Block") || ZInput.GetButtonDown("JoyBlock") || SetDownKeyDown())
			{
				Cancel();
				return;
			}
			ReadingScroll = true;
			float mouseScrollWheel;
			try
			{
				mouseScrollWheel = ZInput.GetMouseScrollWheel();
			}
			finally
			{
				ReadingScroll = false;
			}
			if (mouseScrollWheel > 0f)
			{
				rotation = (rotation + 1) % 16;
			}
			else if (mouseScrollWheel < 0f)
			{
				rotation = (rotation + 15) % 16;
			}
			if (!Access.PieceRayTest(localPlayer, out var point, out var normal, out var piece, out var heightmap, out var waterSurface, water: false))
			{
				ghost.SetActive(false);
				return;
			}
			ghost.SetActive(true);
			Quaternion val = Quaternion.Euler(0f, (float)rotation * 22.5f, 0f);
			ghost.transform.SetPositionAndRotation(point, val);
			Access.PieceRayTest(localPlayer, out var _, out var _, out piece, out heightmap, out var waterSurface2, water: true);
			string text = Problem(point, normal, Object.op_Implicit((Object)(object)waterSurface) ? waterSurface : waterSurface2);
			if (forgeItem != null)
			{
				text = text ?? ForgeProblem(point, val);
			}
			ghostPiece.SetInvalidPlacementHeightlight(text != null);
			if (ZInput.GetButtonDown("Attack") || ZInput.GetButtonDown("JoyPlace"))
			{
				if (text != null)
				{
					((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
				}
				else
				{
					Place(localPlayer, point, val);
				}
			}
		}

		private static void CheckSetDownKey(Player player)
		{
			if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && SetDownKeyDown() && Access.TakeInput(player))
			{
				ItemData val = Worn.Item(player) ?? ((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)Content.IsOurs);
				if (val != null)
				{
					Begin(player, val);
				}
			}
		}

		private static bool BlockedByCharacter()
		{
			//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_0022: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider val = ghostBox;
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			Vector3 val2 = ((Component)val).transform.TransformPoint(val.center);
			Vector3 val3 = Vector3.Scale(val.size * 0.5f, ((Component)val).transform.lossyScale);
			Collider[] array = Physics.OverlapBox(val2, val3, ((Component)val).transform.rotation, CharacterMask);
			for (int i = 0; i < array.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)((Component)array[i]).GetComponentInParent<Character>()))
				{
					return true;
				}
			}
			return false;
		}

		private static bool SetDownKeyDown()
		{
			//IL_0005: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			KeyboardShortcut value = Settings.SetDownKey.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			if (!((KeyboardShortcut)(ref value)).Modifiers.Any((KeyCode k) => (int)k == 308 || (int)k == 307) && (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307)))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}

		private static string Problem(Vector3 point, Vector3 normal, Collider water)
		{
			//IL_000e: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)water))
			{
				return "$shack_benchpack_badspot";
			}
			if (normal.y < 0.6f)
			{
				return "$shack_benchpack_steep";
			}
			if (Location.IsInsideNoBuildLocation(point))
			{
				return "$msg_nobuildzone";
			}
			if (!PrivateArea.CheckAccess(point, 0f, false, false))
			{
				return "$msg_privatezone";
			}
			if (BlockedByCharacter())
			{
				return "$msg_blocked";
			}
			return null;
		}

		private static string ForgeProblem(Vector3 point, Quaternion turn)
		{
			//IL_001b: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_002c: 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_0040: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00a6: 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_00b1: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)forgeGhost))
			{
				forgeGhost.localPosition = Content.ForgeOffset;
			}
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(point + turn * Content.ForgeOffset + Vector3.up * 1.5f, Vector3.down, ref val, 3f, GroundMask) || Mathf.Abs(((RaycastHit)(ref val)).point.y - point.y) > 0.6f)
			{
				return "$shack_forgepack_noroom";
			}
			forgePoint = ((RaycastHit)(ref val)).point;
			if (Object.op_Implicit((Object)(object)forgeGhost))
			{
				forgeGhost.position = ((RaycastHit)(ref val)).point;
			}
			if (Physics.Linecast(point + Vector3.up * 0.6f, ((RaycastHit)(ref val)).point + Vector3.up * 0.6f, GroundMask))
			{
				return "$shack_forgepack_noroom";
			}
			Bounds forgeBoundsPlaced = Content.ForgeBoundsPlaced;
			Collider[] array = Physics.OverlapBox(((RaycastHit)(ref val)).point + turn * ((Bounds)(ref forgeBoundsPlaced)).center, ((Bounds)(ref forgeBoundsPlaced)).extents, turn, CharacterMask);
			for (int i = 0; i < array.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)((Component)array[i]).GetComponentInParent<Character>()))
				{
					return "$msg_blocked";
				}
			}
			if (((RaycastHit)(ref val)).normal.y < 0.6f)
			{
				return "$shack_benchpack_steep";
			}
			if (Object.op_Implicit((Object)(object)ZoneSystem.instance) && ((RaycastHit)(ref val)).point.y < ZoneSystem.instance.m_waterLevel)
			{
				return "$shack_forgepack_noroom";
			}
			if (Location.IsInsideNoBuildLocation(((RaycastHit)(ref val)).point))
			{
				return "$msg_nobuildzone";
			}
			if (!PrivateArea.CheckAccess(((RaycastHit)(ref val)).point, 0f, false, false))
			{
				return "$msg_privatezone";
			}
			return null;
		}

		private static void Place(Player player, Vector3 point, Quaternion turn)
		{
			//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_00ed: 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = item;
			ItemData val2 = forgeItem;
			Vector3 point2 = forgePoint;
			Cancel();
			long num = ((val2 == null) ? 0 : (((long)Random.Range(1, int.MaxValue) << 31) ^ DateTime.UtcNow.Ticks));
			if (val2 != null && num == 0L)
			{
				num = 1L;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (!inventory.ContainsItem(val))
			{
				return;
			}
			if (((Humanoid)player).IsItemEquiped(val))
			{
				((Humanoid)player).UnequipItem(val, false);
			}
			if (!inventory.RemoveItem(val))
			{
				Plugin.Log.LogWarning((object)"Could not take the backpack out of the inventory to set it down.");
				return;
			}
			PlacedBench.PendingInfo pendingInfo = (PlacedBench.Pending = new PlacedBench.PendingInfo
			{
				Level = val.m_quality,
				CrafterId = val.m_crafterID,
				CrafterName = val.m_crafterName,
				Placer = player.GetPlayerName(),
				Durability = val.m_durability,
				Cutter = Content.HasCutter(val),
				Pair = num
			});
			PlacedBench.LastCreated = null;
			try
			{
				player.PlacePiece(Content.BenchPiece, point, turn, false, false);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Setting the bench down failed" + (pendingInfo.Created ? " after the bench was made. " : "; the backpack goes back in your inventory. ") + ex));
				if (!pendingInfo.Created)
				{
					inventory.AddItem(val);
				}
			}
			finally
			{
				PlacedBench.Pending = null;
			}
			if (Object.op_Implicit((Object)(object)(pendingInfo.Created ? PlacedBench.LastCreated : null)) && val2 != null && inventory.ContainsItem(val2) && !Content.Broken(val2))
			{
				PlaceForge(player, val2, point2, turn, num);
			}
		}

		private static void PlaceForge(Player player, ItemData forge, Vector3 point, Quaternion turn, long pair)
		{
			//IL_0083: 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)
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (!inventory.RemoveItem(forge))
			{
				Plugin.Log.LogWarning((object)"Could not take the forge backpack out of the inventory to set it down.");
				return;
			}
			PlacedBench.PendingInfo pendingInfo = (PlacedBench.Pending = new PlacedBench.PendingInfo
			{
				Forge = true,
				Level = forge.m_quality,
				CrafterId = forge.m_crafterID,
				CrafterName = forge.m_crafterName,
				Placer = player.GetPlayerName(),
				Durability = forge.m_durability,
				Pair = pair
			});
			PlacedBench.LastCreated = null;
			try
			{
				player.PlacePiece(Content.ForgePiece, point, turn, false, false);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Setting the forge down failed" + (pendingInfo.Created ? " after the forge was made. " : "; the forge backpack goes back in your inventory. ") + ex));
				if (!pendingInfo.Created)
				{
					inventory.AddItem(forge);
				}
			}
			finally
			{
				PlacedBench.Pending = null;
			}
		}
	}
	[BepInPlugin("theshack.workbenchpack", "Shack Workbench Pack", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "theshack.workbenchpack";

		public const string PluginName = "Shack Workbench Pack";

		public const string PluginVersion = "1.2.0";

		internal static ManualLogSource Log;

		private bool ready;

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Settings.Bind(((BaseUnityPlugin)this).Config);
			Harmony val = new Harmony("theshack.workbenchpack");
			try
			{
				Access.Init();
				val.PatchAll(Assembly.GetExecutingAssembly());
				Content.Init();
			}
			catch (Exception arg)
			{
				val.UnpatchSelf();
				Log.LogError((object)string.Format("{0} could not hook into this game version; the backpack is not added. {1}", "Shack Workbench Pack", arg));
				return;
			}
			ready = true;
			Log.LogInfo((object)(string.Format("{0} {1} ready (weight {2}, ", "Shack Workbench Pack", "1.2.0", Settings.Weight.Value) + $"{Settings.SlowPercent.Value}% slower while carried)."));
		}

		private void Update()
		{
			if (ready)
			{
				Placing.Update();
				PackingUp.Update();
			}
		}
	}
	internal static class Settings
	{
		public static ConfigEntry<KeyboardShortcut> SetDownKey;

		public static ConfigEntry<bool> WearAfterPackUp;

		public static ConfigEntry<float> Weight;

		public static ConfigEntry<int> SlowPercent;

		public static ConfigEntry<bool> NeedsRoof;

		public static ConfigEntry<bool> OwnerOnly;

		public static ConfigEntry<string> CraftCost;

		public static ConfigEntry<bool> BuildWhileWorn;

		public static ConfigEntry<float> BuildRadius;

		public static ConfigEntry<float> BuildRadiusPerLevel;

		public static ConfigEntry<float> Durability;

		public static ConfigEntry<float> DurabilityPerLevel;

		public static ConfigEntry<float> WearPerUse;

		public static ConfigEntry<bool> RepairNeedsLevel;

		public static ConfigEntry<float> CutterWeight;

		public static ConfigEntry<float> CutterRadius;

		public static ConfigEntry<int> SettingsVersion;

		public static ConfigEntry<float> ForgeWeight;

		public static ConfigEntry<int> ForgeSlowPercent;

		public static ConfigEntry<string> ForgeCraftCost;

		public static int Version;

		public static void Bind(ConfigFile config)
		{
			//IL_0022: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			int order = 100;
			SetDownKey = Personal<KeyboardShortcut>("0 - This PC", "Set down key", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), "Sets down the backpack you're wearing (worn gear isn't in the hotbar). The hotbar key does it when the backpack is in your hotbar. Not while Alt is held (Alt+U toggles the compass), unless the key includes Alt.");
			KeyboardShortcut value = SetDownKey.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 103)
			{
				value = SetDownKey.Value;
				if (!((KeyboardShortcut)(ref value)).Modifiers.Any())
				{
					SetDownKey.Value = new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>());
					Plugin.Log.LogInfo((object)"Set down key moved from G (the game's radial menu key) to U.");
				}
			}
			WearAfterPackUp = Personal<bool>("0 - This PC", "Wear after packing up", value: true, "Packing the bench up puts the backpack straight on your back when your utility slot is free.");
			Weight = Bind<float>("1 - General", "Weight", 30f, "Weight of the backpack, worn or in the bag.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f));
			SlowPercent = Bind<int>("1 - General", "Slower while carried", 15, "How much slower you walk, run and swim while the backpack is anywhere in your inventory (worn or in the bag), in percent. In a cart or a