Decompiled source of DvergrPieces v1.0.4

DvergrPieces.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("DvergrPieces")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+16eaa06624bab7178c9402a3e840dcefc64279c5")]
[assembly: AssemblyProduct("DvergrPieces")]
[assembly: AssemblyTitle("DvergrPieces")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 DvergrPieces
{
	public enum Group
	{
		Building,
		Furniture
	}
	public enum SnapRule
	{
		Explicit,
		ColliderCorners,
		Origin
	}
	public readonly struct Req
	{
		public readonly string Item;

		public readonly int Amount;

		public Req(string item, int amount)
		{
			Item = item;
			Amount = amount;
		}

		public override string ToString()
		{
			string item = Item;
			int amount = Amount;
			return item + "," + amount.ToString(CultureInfo.InvariantCulture);
		}
	}
	public readonly struct Point
	{
		public readonly float X;

		public readonly float Y;

		public readonly float Z;

		public Point(float x, float y, float z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public override string ToString()
		{
			return string.Format(CultureInfo.InvariantCulture, "({0}, {1}, {2})", X, Y, Z);
		}
	}
	public sealed class PieceSpec
	{
		public string Prefab;

		public string Name;

		public string Description;

		public Group Group;

		public string[] Tags;

		public Req[] Cost;

		public SnapRule Snap;

		public Point[] SnapPoints;
	}
	public static class DvergrCatalog
	{
		public const string Station = "piece_workbench";

		public const string PlaceEffectDonor = "woodwall";

		public const string FallbackIconDonor = "piece_hexagonal_door";

		public static readonly string[] KnownTags = new string[12]
		{
			"Misc", "Building", "Floor", "Wall", "Roof", "Architecture", "Furniture", "Lighting", "Decor", "Storage",
			"Defense", "Stairs"
		};

		private static readonly Req[] NoCost = new Req[0];

		public static readonly PieceSpec[] Pieces = new PieceSpec[18]
		{
			Building("dvergrprops_wood_pole", "Dvergr Wood Pole 4m", "A sturdy dvergr post of Yggdrasil wood.", new string[1] { "Building" }, Cost("YggdrasilWood", 1), SnapRule.Explicit, new Point(0f, 2f, 0f), new Point(0f, -2f, 0f)),
			Building("dvergrprops_wood_beam", "Dvergr Wood Beam 6m", "A long dvergr beam of Yggdrasil wood.", new string[1] { "Building" }, Cost("YggdrasilWood", 2), SnapRule.Explicit, new Point(3f, 0f, 0f), new Point(-3f, 0f, 0f)),
			Building("dvergrprops_wood_wall", "Dvergr Wood Wall 4x4", "Dvergr timber wall, braced with copper.", new string[2] { "Building", "Wall" }, Cost("YggdrasilWood", 2, "Copper", 2), SnapRule.Explicit, new Point(2.2f, 2f, 0f), new Point(-2.2f, 2f, 0f), new Point(2.2f, -2f, 0f), new Point(-2.2f, -2f, 0f)),
			Building("dvergrprops_wood_floor", "Dvergr Wood Floor", "Dvergr floor planks of Yggdrasil wood.", new string[2] { "Building", "Floor" }, Cost("YggdrasilWood", 2), SnapRule.ColliderCorners),
			Building("dvergrprops_wood_stair", "Dvergr Wood Stairs", "Dvergr stairs, copper-shod.", new string[2] { "Building", "Stairs" }, Cost("YggdrasilWood", 3, "Copper", 1), SnapRule.ColliderCorners),
			Building("dvergrtown_stair_corner_wood_left", "Dvergr Corner Stairs", "A dvergr quarter-turn stair with landing.", new string[2] { "Building", "Stairs" }, Cost("YggdrasilWood", 3, "Copper", 1), SnapRule.Explicit, new Point(0.25f, 0f, -0.25f), new Point(0.25f, 0f, 0.25f), new Point(0.25f, 1.1f, -0.25f), new Point(0.25f, 1.1f, 0.25f), new Point(0.25f, 0f, 2f), new Point(-0.25f, 1.1f, -0.25f), new Point(-2f, 1.1f, -0.25f)),
			Building("dvergrprops_wood_stakewall", "Dvergr Stake Wall", "Iron-tipped dvergr stakes. They hurt.", new string[2] { "Building", "Defense" }, Cost("YggdrasilWood", 4, "Iron", 1), SnapRule.ColliderCorners),
			Building("dvergrtown_wood_crane", "Dvergr Crane", "A dvergr loading crane. Decorative, but imposing.", new string[2] { "Building", "Decor" }, Cost("YggdrasilWood", 8, "Chain", 2, "Iron", 2), SnapRule.Explicit, new Point(0f, -3f, 0f)),
			Furniture("dvergrprops_bed", "Dvergr Bed", "A dvergr bunk. Too short to sleep in; fine to look at.", new string[1] { "Furniture" }, Cost("YggdrasilWood", 8, "ScaleHide", 2)),
			Furniture("dvergrprops_chair", "Dvergr Chair", "A dvergr chair of Yggdrasil wood.", new string[1] { "Furniture" }, Cost("YggdrasilWood", 3)),
			Furniture("dvergrprops_stool", "Dvergr Stool", "A dvergr stool of Yggdrasil wood.", new string[1] { "Furniture" }, Cost("YggdrasilWood", 1)),
			Furniture("dvergrprops_table", "Dvergr Table", "A dvergr work table.", new string[1] { "Furniture" }, Cost("YggdrasilWood", 3)),
			Furniture("dvergrprops_shelf", "Dvergr Shelf", "Dvergr shelving with copper brackets.", new string[2] { "Furniture", "Storage" }, Cost("YggdrasilWood", 2, "Copper", 2)),
			Furniture("dvergrprops_banner", "Dvergr Banner", "A blue dvergr banner.", new string[2] { "Furniture", "Decor" }, Cost("JuteBlue", 3, "FineWood", 2)),
			Furniture("dvergrprops_curtain", "Dvergr Curtain", "A heavy blue dvergr curtain.", new string[2] { "Furniture", "Decor" }, Cost("JuteBlue", 3, "FineWood", 2)),
			Furniture("dvergrprops_hooknchain", "Dvergr Hook and Chain", "A hanging iron hook on a chain.", new string[2] { "Furniture", "Decor" }, Cost("Chain", 2, "Iron", 2)),
			Furniture("dvergrprops_crate", "Dvergr Crate", "A sealed dvergr crate. Purely decorative.", new string[2] { "Furniture", "Decor" }, Cost("YggdrasilWood", 2)),
			Furniture("dvergrprops_crate_long", "Dvergr Long Crate", "A long sealed dvergr crate. Purely decorative.", new string[2] { "Furniture", "Decor" }, Cost("YggdrasilWood", 3))
		};

		private static PieceSpec Building(string prefab, string name, string desc, string[] tags, Req[] cost, SnapRule snap, params Point[] points)
		{
			return new PieceSpec
			{
				Prefab = prefab,
				Name = name,
				Description = desc,
				Group = Group.Building,
				Tags = tags,
				Cost = cost,
				Snap = snap,
				SnapPoints = points
			};
		}

		private static PieceSpec Furniture(string prefab, string name, string desc, string[] tags, Req[] cost)
		{
			return new PieceSpec
			{
				Prefab = prefab,
				Name = name,
				Description = desc,
				Group = Group.Furniture,
				Tags = tags,
				Cost = cost,
				Snap = SnapRule.Origin,
				SnapPoints = new Point[0]
			};
		}

		private static Req[] Cost(params object[] pairs)
		{
			List<Req> list = new List<Req>();
			for (int i = 0; i < pairs.Length; i += 2)
			{
				list.Add(new Req((string)pairs[i], (int)pairs[i + 1]));
			}
			return list.ToArray();
		}

		public static PieceSpec Find(string prefab)
		{
			PieceSpec[] pieces = Pieces;
			foreach (PieceSpec pieceSpec in pieces)
			{
				if (pieceSpec.Prefab == prefab)
				{
					return pieceSpec;
				}
			}
			return null;
		}

		public static Req[] ParseCost(string text, out string error)
		{
			error = null;
			if (text == null || text.Trim().Length == 0)
			{
				error = "empty";
				return null;
			}
			List<Req> list = new List<Req>();
			string[] array = text.Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length != 0)
				{
					string[] array2 = text2.Split(new char[1] { ',' });
					if (array2.Length != 2)
					{
						error = "expected Item,amount in '" + text2 + "'";
						return null;
					}
					string text3 = array2[0].Trim();
					if (text3.Length == 0)
					{
						error = "missing item name in '" + text2 + "'";
						return null;
					}
					if (!int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 1)
					{
						error = "amount must be a whole number of at least 1 in '" + text2 + "'";
						return null;
					}
					list.Add(new Req(text3, result));
				}
			}
			if (list.Count == 0)
			{
				error = "empty";
				return null;
			}
			return list.ToArray();
		}

		public static string FormatCost(Req[] cost)
		{
			return string.Join(";", Array.ConvertAll(cost, (Req r) => r.ToString()));
		}

		public static Point[] BoxCorners(Point center, Point size)
		{
			float num = size.X / 2f;
			float num2 = size.Y / 2f;
			float num3 = size.Z / 2f;
			Point[] array = new Point[8];
			int num4 = 0;
			for (int i = -1; i <= 1; i += 2)
			{
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						array[num4++] = new Point(center.X + (float)k * num, center.Y + (float)i * num2, center.Z + (float)j * num3);
					}
				}
			}
			return array;
		}

		public static bool NeedsPlaceEffect(int effectCount)
		{
			return effectCount <= 0;
		}

		public static bool ChargesCost(bool freePieces)
		{
			return !freePieces;
		}

		public static bool RefundsCost(bool placedByPlayer, bool worldRefundSetting)
		{
			return placedByPlayer || worldRefundSetting;
		}
	}
	[BepInPlugin("lily.dvergrpieces", "Dvergr Pieces", "1.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class DvergrPiecesPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Piece), "DropResources")]
		private static class RefundPatch
		{
			private static bool Prefix(Piece __instance)
			{
				if (!Patched.Contains(Utils.GetPrefabName(((Component)__instance).gameObject)))
				{
					return true;
				}
				return DvergrCatalog.RefundsCost(__instance.IsPlacedByPlayer(), _worldRefund);
			}
		}

		public const string Guid = "lily.dvergrpieces";

		public const string Version = "1.0.4";

		private const string HammerTable = "Hammer";

		private const string SnapTag = "snappoint";

		private const string SnapName = "_snappoint";

		private static DvergrPiecesPlugin _instance;

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

		private static bool _worldRefund;

		private readonly Dictionary<string, ConfigEntry<bool>> _enabled = new Dictionary<string, ConfigEntry<bool>>();

		private readonly Dictionary<string, ConfigEntry<string>> _cost = new Dictionary<string, ConfigEntry<string>>();

		private ConfigEntry<bool> _worldRefundEntry;

		private ConfigEntry<bool> _free;

		private ConfigEntry<bool> _debugLog;

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

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			_instance = this;
			_worldRefundEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "WorldPiecesRefund", false, "Deconstructing a dvergr piece the world generated (an outpost you did not build) refunds its build cost. Off = only vanilla drops (BEH-2-2).");
			_free = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FreePieces", false, "Dvergr pieces cost nothing while this is on. Applies immediately. Pieces built for free refund the normal cost if you deconstruct them after turning it off (BEH-3-7).");
			_free.SettingChanged += delegate
			{
				ReapplyCosts();
			};
			_debugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLog", false, "Log each registered piece with its cost and snap points.");
			PieceSpec[] pieces = DvergrCatalog.Pieces;
			foreach (PieceSpec pieceSpec in pieces)
			{
				_enabled[pieceSpec.Prefab] = ((BaseUnityPlugin)this).Config.Bind<bool>("Pieces", pieceSpec.Prefab, true, pieceSpec.Name + ": show in the Hammer. Off keeps it repairable only. Applies on next world load.");
				_cost[pieceSpec.Prefab] = ((BaseUnityPlugin)this).Config.Bind<string>("Cost", pieceSpec.Prefab, DvergrCatalog.FormatCost(pieceSpec.Cost), pieceSpec.Name + " cost as Item,amount;Item,amount (item prefab names). Bad values fall back to the default.");
			}
			_worldRefund = _worldRefundEntry.Value;
			_worldRefundEntry.SettingChanged += delegate
			{
				_worldRefund = _worldRefundEntry.Value;
			};
			PrefabManager.OnVanillaPrefabsAvailable += PatchPrefabs;
			PieceManager.OnPiecesRegistered += UpdateHammer;
			_harmony = new Harmony("lily.dvergrpieces");
			_harmony.PatchAll(typeof(RefundPatch));
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= PatchPrefabs;
			PieceManager.OnPiecesRegistered -= UpdateHammer;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void PatchPrefabs()
		{
			GameObject prefab = GetPrefab("piece_workbench");
			CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
			GameObject prefab2 = GetPrefab("woodwall");
			Piece donor = ((prefab2 != null) ? prefab2.GetComponent<Piece>() : null);
			GameObject prefab3 = GetPrefab("piece_hexagonal_door");
			Sprite val2 = ((prefab3 == null) ? null : prefab3.GetComponent<Piece>()?.m_icon);
			if ((Object)(object)val == (Object)null)
			{
				WarnOnce("station", "crafting station piece_workbench not found; pieces will need no station");
			}
			PieceSpec[] pieces = DvergrCatalog.Pieces;
			foreach (PieceSpec pieceSpec in pieces)
			{
				try
				{
					GameObject prefab4 = GetPrefab(pieceSpec.Prefab);
					if ((Object)(object)prefab4 == (Object)null)
					{
						WarnOnce(pieceSpec.Prefab, "prefab " + pieceSpec.Prefab + " not found; skipped");
						continue;
					}
					if ((Object)(object)prefab4.GetComponent<WearNTear>() == (Object)null)
					{
						WarnOnce(pieceSpec.Prefab, pieceSpec.Prefab + " has no WearNTear; skipped");
						continue;
					}
					bool num = !Patched.Contains(pieceSpec.Prefab);
					Piece val3 = prefab4.GetComponent<Piece>();
					if ((Object)(object)val3 == (Object)null)
					{
						val3 = AddPieceComponent(prefab4);
					}
					if (num)
					{
						ApplySpec(val3, pieceSpec, val, donor);
						if (prefab4.layer == 0)
						{
							prefab4.layer = LayerMask.NameToLayer("piece");
						}
						AddSnapPoints(prefab4, pieceSpec);
						Patched.Add(pieceSpec.Prefab);
					}
					val3.m_resources = ResolveCost(pieceSpec);
					if ((Object)(object)val3.m_icon == (Object)null)
					{
						val3.m_icon = RenderIcon(prefab4) ?? val2;
					}
					if (_debugLog.Value)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)Describe(prefab4, val3));
					}
				}
				catch (Exception ex)
				{
					WarnOnce(pieceSpec.Prefab + ":ex", "failed to patch " + pieceSpec.Prefab + ": " + ex);
				}
			}
		}

		private void UpdateHammer()
		{
			PieceTable pieceTable = PieceManager.Instance.GetPieceTable("Hammer");
			if ((Object)(object)pieceTable == (Object)null)
			{
				WarnOnce("hammer", "Hammer piece table not found; nothing added");
				return;
			}
			Piece val = FindDonor(pieceTable);
			if ((Object)(object)val == (Object)null)
			{
				WarnOnce("donor", "no woodwall in the Hammer; place/repair effects stay silent");
			}
			int num = 0;
			PieceSpec[] pieces = DvergrCatalog.Pieces;
			foreach (PieceSpec pieceSpec in pieces)
			{
				if (!Patched.Contains(pieceSpec.Prefab))
				{
					continue;
				}
				GameObject prefab = GetPrefab(pieceSpec.Prefab);
				if (!((Object)(object)prefab == (Object)null))
				{
					Piece component = prefab.GetComponent<Piece>();
					if ((Object)(object)val != (Object)null && (Object)(object)component != (Object)null && DvergrCatalog.NeedsPlaceEffect(EffectCount(component)))
					{
						component.m_placeEffect = val.m_placeEffect;
					}
					bool value = _enabled[pieceSpec.Prefab].Value;
					bool flag = pieceTable.m_pieces.Contains(prefab);
					if (value && !flag)
					{
						pieceTable.m_pieces.Add(prefab);
						num++;
					}
					else if (!value && flag)
					{
						pieceTable.m_pieces.Remove(prefab);
					}
				}
			}
			if (_debugLog.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Hammer: added " + num + " dvergr pieces; place effect donor " + (Object.op_Implicit((Object)(object)val) ? "found" : "missing")));
			}
		}

		private static GameObject GetPrefab(string name)
		{
			return PrefabManager.Instance.GetPrefab(name);
		}

		private static Piece FindDonor(PieceTable table)
		{
			foreach (GameObject piece in table.m_pieces)
			{
				if ((Object)(object)piece != (Object)null && ((Object)piece).name == "woodwall")
				{
					return piece.GetComponent<Piece>();
				}
			}
			return null;
		}

		private static int EffectCount(Piece piece)
		{
			if (piece.m_placeEffect != null && piece.m_placeEffect.m_effectPrefabs != null)
			{
				return piece.m_placeEffect.m_effectPrefabs.Length;
			}
			return 0;
		}

		private static Piece AddPieceComponent(GameObject go)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Piece obj = go.AddComponent<Piece>();
			obj.m_groundOnly = false;
			obj.m_groundPiece = false;
			obj.m_cultivatedGroundOnly = false;
			obj.m_waterPiece = false;
			obj.m_noInWater = false;
			obj.m_notOnWood = false;
			obj.m_notOnTiltingSurface = false;
			obj.m_inCeilingOnly = false;
			obj.m_notOnFloor = false;
			obj.m_onlyInTeleportArea = false;
			obj.m_allowedInDungeons = false;
			obj.m_clipEverything = false;
			obj.m_clipGround = false;
			obj.m_allowRotatedOverlap = true;
			obj.m_repairPiece = false;
			obj.m_onlyInBiome = (Biome)0;
			((StaticTarget)obj).m_randomTarget = true;
			obj.m_targetNonPlayerBuilt = false;
			return obj;
		}

		private static void ApplySpec(Piece piece, PieceSpec spec, CraftingStation station, Piece donor)
		{
			//IL_0034: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			piece.m_name = spec.Name;
			piece.m_description = spec.Description;
			piece.m_enabled = true;
			piece.m_canBeRemoved = true;
			piece.m_category = (PieceCategory)((spec.Group == Group.Furniture) ? 4 : 2);
			piece.m_craftingStation = station;
			piece.m_usage = ParseTags(spec);
			if ((Object)(object)donor != (Object)null && donor.m_placeEffect != null && DvergrCatalog.NeedsPlaceEffect(EffectCount(piece)))
			{
				piece.m_placeEffect = donor.m_placeEffect;
			}
		}

		private static UsageTagFlags ParseTags(PieceSpec spec)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			UsageTagFlags val = (UsageTagFlags)0;
			string[] tags = spec.Tags;
			foreach (string text in tags)
			{
				if (Enum.TryParse<UsageTagFlags>(text, out UsageTagFlags result))
				{
					val |= result;
				}
				else
				{
					_instance.WarnOnce("tag:" + text, "unknown hammer tag '" + text + "' on " + spec.Prefab);
				}
			}
			return val;
		}

		private void ReapplyCosts()
		{
			PieceSpec[] pieces = DvergrCatalog.Pieces;
			foreach (PieceSpec pieceSpec in pieces)
			{
				if (Patched.Contains(pieceSpec.Prefab))
				{
					GameObject prefab = GetPrefab(pieceSpec.Prefab);
					Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
					if ((Object)(object)val != (Object)null)
					{
						val.m_resources = ResolveCost(pieceSpec);
					}
				}
			}
			if (_debugLog.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("FreePieces " + (_free.Value ? "on" : "off") + "; costs reapplied"));
			}
		}

		private Requirement[] ResolveCost(PieceSpec spec)
		{
			if (!DvergrCatalog.ChargesCost(_free.Value))
			{
				return (Requirement[])(object)new Requirement[0];
			}
			string error;
			Req[] array = DvergrCatalog.ParseCost(_cost[spec.Prefab].Value, out error);
			if (array == null)
			{
				WarnOnce("cost:" + spec.Prefab, spec.Prefab + " cost config ignored (" + error + "); using default");
				array = spec.Cost;
			}
			Requirement[] array2 = ToRequirements(array, spec.Prefab);
			if (array2 == null && array != spec.Cost)
			{
				array2 = ToRequirements(spec.Cost, spec.Prefab);
			}
			return (Requirement[])(((object)array2) ?? ((object)new Requirement[0]));
		}

		private Requirement[] ToRequirements(Req[] cost, string prefab)
		{
			//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_0099: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			Requirement[] array = (Requirement[])(object)new Requirement[cost.Length];
			for (int i = 0; i < cost.Length; i++)
			{
				GameObject prefab2 = GetPrefab(cost[i].Item);
				ItemDrop val = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null)
				{
					WarnOnce("item:" + cost[i].Item, "item " + cost[i].Item + " not found (cost of " + prefab + ")");
					return null;
				}
				array[i] = new Requirement
				{
					m_resItem = val,
					m_amount = cost[i].Amount,
					m_amountPerLevel = 0,
					m_recover = true
				};
			}
			return array;
		}

		private static void AddSnapPoints(GameObject go, PieceSpec spec)
		{
			//IL_0095: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)(object)go.transform && ((Component)val).CompareTag("snappoint"))
				{
					return;
				}
			}
			foreach (Point item in spec.Snap switch
			{
				SnapRule.Explicit => spec.SnapPoints, 
				SnapRule.Origin => new Point[1]
				{
					new Point(0f, 0f, 0f)
				}, 
				_ => ColliderCorners(go), 
			})
			{
				GameObject val2 = new GameObject("_snappoint");
				val2.transform.SetParent(go.transform, false);
				val2.transform.localPosition = new Vector3(item.X, item.Y, item.Z);
				val2.tag = "snappoint";
				val2.SetActive(false);
			}
		}

		private static IEnumerable<Point> ColliderCorners(GameObject go)
		{
			//IL_001f: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider[] componentsInChildren = go.GetComponentsInChildren<BoxCollider>(true);
			foreach (BoxCollider val in componentsInChildren)
			{
				if (!((Collider)val).isTrigger)
				{
					Point[] array = DvergrCatalog.BoxCorners(new Point(val.center.x, val.center.y, val.center.z), new Point(val.size.x, val.size.y, val.size.z));
					List<Point> list = new List<Point>(array.Length);
					Point[] array2 = array;
					for (int j = 0; j < array2.Length; j++)
					{
						Point point = array2[j];
						Vector3 val2 = go.transform.InverseTransformPoint(((Component)val).transform.TransformPoint(new Vector3(point.X, point.Y, point.Z)));
						list.Add(new Point(val2.x, val2.y, val2.z));
					}
					return list;
				}
			}
			return new Point[1]
			{
				new Point(0f, 0f, 0f)
			};
		}

		private static Sprite RenderIcon(GameObject go)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0022: Expected O, but got Unknown
			try
			{
				return RenderManager.Instance.Render(new RenderRequest(go)
				{
					Rotation = RenderManager.IsometricRotation,
					UseCache = true
				});
			}
			catch (Exception ex)
			{
				_instance.WarnOnce("icon:" + ((Object)go).name, "icon render failed for " + ((Object)go).name + ": " + ex.Message);
				return null;
			}
		}

		private static string Describe(GameObject go, Piece piece)
		{
			//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)
			List<string> list = new List<string>();
			Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)(object)go.transform && ((Component)val).CompareTag("snappoint"))
				{
					list.Add(((object)val.localPosition/*cast due to .constrained prefix*/).ToString());
				}
			}
			List<string> list2 = new List<string>();
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val2 in resources)
			{
				list2.Add(val2.m_amount + " " + (Object.op_Implicit((Object)(object)val2.m_resItem) ? ((Object)val2.m_resItem).name : "?"));
			}
			return ((Object)go).name + " '" + piece.m_name + "' cost [" + string.Join(", ", list2) + "] tags " + ((object)Unsafe.As<UsageTagFlags, UsageTagFlags>(ref piece.m_usage)/*cast due to .constrained prefix*/).ToString() + " snaps [" + string.Join(" ", list) + "] icon " + (Object.op_Implicit((Object)(object)piece.m_icon) ? "yes" : "none") + " placeEffects " + EffectCount(piece);
		}

		private void WarnOnce(string key, string message)
		{
			if (_warned.Add(key))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			}
		}
	}
}