Decompiled source of BetterCreative v1.5.0

plugins\BetterCreative\BetterCreative.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Better Creative Mode")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BetterCreative")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.0.0")]
namespace Heinermann
{
	public class SimplePiece
	{
		public string Name { get; set; }

		public string PieceTable { get; set; }

		public string Category { get; set; }

		public string CraftingStation { get; set; }

		public Dictionary<string, int> Requirements { get; set; } = new Dictionary<string, int>();


		public PieceConfig PieceConfig()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0090: Expected O, but got Unknown
			return new PieceConfig
			{
				Name = "$heinermann_" + Name,
				PieceTable = PieceTable,
				Category = Category,
				CraftingStation = CraftingStation,
				Description = "$heinermann_" + Name + "_desc",
				Requirements = ((IEnumerable<KeyValuePair<string, int>>)Requirements).Select((Func<KeyValuePair<string, int>, RequirementConfig>)((KeyValuePair<string, int> item) => new RequirementConfig(item.Key, item.Value, 0, true))).ToArray()
			};
		}
	}
	public static class PieceUtil
	{
		private static Sprite CreateIcon(GameObject prefab)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return RenderManager.Instance.Render(prefab, RenderManager.IsometricRotation);
		}

		public static void AddPieces(AssetBundle bundle, IEnumerable<SimplePiece> pieces)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			foreach (SimplePiece piece in pieces)
			{
				GameObject val = bundle.LoadAsset<GameObject>("heinermann_" + piece.Name);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogError((object)("Failed to load asset: heinermann_" + piece.Name));
					continue;
				}
				PieceConfig val2 = piece.PieceConfig();
				Piece component = val.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null)
				{
					if ((Object)(object)component.m_icon == (Object)null)
					{
						component.m_icon = CreateIcon(val);
					}
					val2.Icon = component.m_icon;
				}
				else
				{
					val2.Icon = CreateIcon(val);
				}
				PieceManager.Instance.AddPiece(new CustomPiece(val, true, piece.PieceConfig()));
			}
		}
	}
	public static class UnityExtensions
	{
		public static T GetOrAddComponent<T>(this GameObject go) where T : Component
		{
			T val = go.GetComponent<T>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<T>();
			}
			return val;
		}

		public static void DestroyComponent<T>(this GameObject go) where T : Component
		{
			T[] componentsInChildren = go.GetComponentsInChildren<T>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		public static bool HasAnyComponent(this GameObject go, params string[] componentNames)
		{
			return componentNames.Any((string component) => (Object)(object)go.GetComponent(component) != (Object)null);
		}

		public static bool HasAnyComponentInChildren(this GameObject go, params Type[] components)
		{
			return components.Any((Type component) => (Object)(object)go.GetComponentInChildren(component, true) != (Object)null);
		}

		public static bool HasAllComponents(this GameObject go, params string[] componentNames)
		{
			return componentNames.All((string component) => (Object)(object)go.GetComponent(component) != (Object)null);
		}

		public static bool ContainsAny(this string str, params string[] substrings)
		{
			return substrings.Any((string s) => str.Contains(s));
		}
	}
}
namespace Heinermann.BetterCreative
{
	public static class Configs
	{
		private const string CommandStates = "Command States";

		public static ConfigEntry<bool> DevCommands;

		public static ConfigEntry<bool> NoCost;

		public static ConfigEntry<bool> God;

		public static ConfigEntry<bool> Ghost;

		public static ConfigEntry<bool> DebugMode;

		private const string Improvements = "Improvements";

		public static ConfigEntry<bool> UnlimitedStamina;

		public static ConfigEntry<bool> AllPrefabs;

		public static ConfigEntry<bool> UnrestrictedPlacement;

		public static ConfigEntry<bool> NoPieceDrops;

		public static ConfigEntry<bool> NoPieceDelay;

		public static ConfigEntry<bool> NoDurabilityDrain;

		public static ConfigEntry<bool> NoEncumbered;

		public static ConfigEntry<bool> NoUnlockMsg;

		public static ConfigEntry<int> DeleteRange;

		private const string Hotkeys = "Hotkeys";

		public static ConfigEntry<KeyboardShortcut> KeyUndo1;

		public static ConfigEntry<KeyboardShortcut> KeyUndo2;

		public static ConfigEntry<KeyboardShortcut> KeyRedo1;

		public static ConfigEntry<KeyboardShortcut> KeyRedo2;

		public static ConfigEntry<KeyboardShortcut> KeyDelete1;

		public static ConfigEntry<KeyboardShortcut> KeyDelete2;

		public static void Init(ConfigFile config)
		{
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			DevCommands = config.Bind<bool>("Command States", "devcommands", true, "Enable devcommands automatically. Required for other commands to function.");
			NoCost = config.Bind<bool>("Command States", "nocost", true, "No build cost, unlocks everything.");
			God = config.Bind<bool>("Command States", "god", true, "Makes it so you don't take damage from monsters.");
			Ghost = config.Bind<bool>("Command States", "ghost", true, "Prevents mobs from seeing you.");
			DebugMode = config.Bind<bool>("Command States", "debugmode", true, "Enables fly mode and debug hotkeys.");
			UnlimitedStamina = config.Bind<bool>("Improvements", "Unlimited Stamina", true, "Can always perform stamina actions regardless of stamina amount.");
			AllPrefabs = config.Bind<bool>("Improvements", "All Prefabs", true, "Allow placement of all functional prefabs. (Requires restart to take effect)");
			UnrestrictedPlacement = config.Bind<bool>("Improvements", "Unrestricted Placement", true, "Allow unrestricted placements (no collision, campfire on wood, etc). Note: Disabling this won't allow placement of some objects. (Requires restart to take effect)");
			NoPieceDrops = config.Bind<bool>("Improvements", "No Piece Drops", true, "Don't drop materials when pieces are destroyed.");
			NoPieceDelay = config.Bind<bool>("Improvements", "No Placement Delay", true, "No cooldowns for the hammer, cultivator, or hoe. (Requires restart to take effect)");
			NoDurabilityDrain = config.Bind<bool>("Improvements", "No Durability Drain", true, "Tools don't lose durability. (Requires restart to take effect)");
			NoEncumbered = config.Bind<bool>("Improvements", "No Encumbered", true, "No effect when surpassing maximum carry weight");
			NoUnlockMsg = config.Bind<bool>("Improvements", "No Unlock Messages", true, "No popup message when unlocking a recipe");
			DeleteRange = config.Bind<int>("Improvements", "Delete Range", 5, "Range to delete objects with the delete key. This is the radius from the placement ghost's center.");
			KeyboardShortcut val = default(KeyboardShortcut);
			((KeyboardShortcut)(ref val))..ctor((KeyCode)122, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 });
			KeyUndo1 = config.Bind<KeyboardShortcut>("Hotkeys", "Undo", val, "Warning: default (ctrl+z) conflicts with sneak and fly.");
			KeyUndo2 = config.Bind<KeyboardShortcut>("Hotkeys", "Undo (alt)", KeyboardShortcut.Empty, "Alternative.");
			KeyboardShortcut val2 = default(KeyboardShortcut);
			((KeyboardShortcut)(ref val2))..ctor((KeyCode)122, (KeyCode[])(object)new KeyCode[2]
			{
				(KeyCode)306,
				(KeyCode)304
			});
			KeyboardShortcut val3 = default(KeyboardShortcut);
			((KeyboardShortcut)(ref val3))..ctor((KeyCode)121, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 });
			KeyRedo1 = config.Bind<KeyboardShortcut>("Hotkeys", "Redo", val2, "Warning: default (ctrl+shift+z) conflicts with sneak and fly.");
			KeyRedo2 = config.Bind<KeyboardShortcut>("Hotkeys", "Redo (alt)", val3, "Alternative.");
			KeyDelete1 = config.Bind<KeyboardShortcut>("Hotkeys", "Delete", new KeyboardShortcut((KeyCode)127, Array.Empty<KeyCode>()), "Destroys all prefabs that match the currently selected piece in the area.");
			KeyDelete2 = config.Bind<KeyboardShortcut>("Hotkeys", "Delete (alt)", KeyboardShortcut.Empty, (ConfigDescription)null);
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
		private class PlayerSetupPlacementGhost
		{
			private static void Prefix(Player __instance)
			{
				if ((Object)(object)GetSelectedPrefab(__instance) != (Object)null)
				{
					settingUpPlacementGhost = true;
				}
			}

			private static void Postfix()
			{
				settingUpPlacementGhost = false;
			}
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		private class OnRemovePiece
		{
			private static bool Prefix(Player __instance, ref bool __result, ref int ___m_removeRayMask)
			{
				//IL_0012: 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_0038: 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_0085: Unknown result type (might be due to invalid IL or missing references)
				inRemovePiece = true;
				Piece val = null;
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val2, 50f, ___m_removeRayMask) && Vector3.Distance(((RaycastHit)(ref val2)).point, ((Character)__instance).m_eye.position) < __instance.m_maxPlaceDistance)
				{
					val = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Piece>();
					if ((Object)(object)val == (Object)null && Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponent("Heightmap")))
					{
						val = TerrainModifier.FindClosestModifierPieceInRange(((RaycastHit)(ref val2)).point, 2.5f);
					}
				}
				if (Configs.UnrestrictedPlacement.Value && Object.op_Implicit((Object)(object)val))
				{
					WearNTear component = ((Component)val).GetComponent<WearNTear>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.Remove();
					}
					else
					{
						((Component)val).GetComponent<ZNetView>().ClaimOwnership();
						val.DropResources((HitData)null);
						ZNetScene.instance.Destroy(((Component)val).gameObject);
					}
					__result = true;
					return false;
				}
				return true;
			}

			private static void Postfix()
			{
				inRemovePiece = false;
			}
		}

		private static bool settingUpPlacementGhost;

		private static bool inRemovePiece;

		public static GameObject lastPlacementGhost;

		public static GameObject GetSelectedPrefab(Player player)
		{
			if (player == null)
			{
				return null;
			}
			Piece selectedPiece = player.GetSelectedPiece();
			if (selectedPiece == null)
			{
				return null;
			}
			return ((Component)selectedPiece).gameObject;
		}

		[HarmonyPatch(typeof(Piece), "SetCreator")]
		[HarmonyPrefix]
		private static void PieceSetCreatorPrefix(long uid, Piece __instance)
		{
			UndoHelper.Create(((Component)__instance).gameObject);
			Container component = ((Component)__instance).GetComponent<Container>();
			if (Object.op_Implicit((Object)(object)component) && (component.m_autoDestroyEmpty || Object.op_Implicit((Object)(object)((Component)__instance).GetComponent("TombStone"))))
			{
				component.GetInventory().AddItem(PrefabManager.Instance.GetPrefab("Wood"), 1);
			}
			ZNetView component2 = ((Component)__instance).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component2) && !component2.m_persistent)
			{
				component2.m_persistent = true;
				if (component2.GetZDO() != null)
				{
					component2.GetZDO().Persistent = true;
				}
				ZSyncTransform orAddComponent = ((Component)__instance).gameObject.GetOrAddComponent<ZSyncTransform>();
				orAddComponent.m_syncPosition = true;
				orAddComponent.m_syncRotation = true;
			}
		}

		[HarmonyPatch(typeof(Player), "IsEncumbered")]
		[HarmonyPrefix]
		private static bool PlayerIsEncumberedPrefix(ref bool __result)
		{
			if (Configs.NoEncumbered.Value)
			{
				__result = false;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Object), "Internal_CloneSingle", new Type[] { typeof(Object) })]
		[HarmonyPrefix]
		private static bool ObjectInstantiate1Prefix(ref Object __result, Object data)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if (settingUpPlacementGhost)
			{
				settingUpPlacementGhost = false;
				if (Prefabs.AddedPrefabs.Contains(data.name))
				{
					Logger.LogInfo((object)("Setting up placement ghost for " + data.name));
					GameObject val = new GameObject();
					val.SetActive(false);
					Object val2 = Object.Instantiate(data, val.transform, false);
					Prefabs.PrepareGhostPrefab((GameObject)(object)((val2 is GameObject) ? val2 : null));
					__result = Object.Instantiate(val2);
					Object.DestroyImmediate((Object)(object)val);
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		[HarmonyPostfix]
		private static void PlayerUpdatePlacementGhostPostfix(ref GameObject ___m_placementGhost, ref int ___m_placementStatus)
		{
			lastPlacementGhost = ___m_placementGhost;
			if (Configs.UnrestrictedPlacement.Value && Object.op_Implicit((Object)(object)___m_placementGhost))
			{
				___m_placementStatus = 0;
				___m_placementGhost.GetComponent<Piece>().SetInvalidPlacementHeightlight(false);
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		[HarmonyPrefix]
		private static bool DropPieceResourcesPrefix()
		{
			return !Configs.NoPieceDrops.Value;
		}

		[HarmonyPatch(typeof(ZNetScene), "Destroy")]
		[HarmonyPrefix]
		private static void ZNetSceneDestroyPrefix(GameObject go)
		{
			if (inRemovePiece)
			{
				UndoHelper.Remove(go);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		[HarmonyPrefix]
		private static void ObjectDBAwakePrefix()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name == "main")
			{
				BetterCreative.ModifyItems();
				if (Configs.AllPrefabs.Value)
				{
					Prefabs.FindAndRegisterPrefabs();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "HaveStamina")]
		[HarmonyPrefix]
		private static bool HaveStaminaPrefix(ref bool __result)
		{
			if (Configs.UnlimitedStamina.Value)
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Player), "ShowTutorial")]
		[HarmonyPrefix]
		private static bool ShowTutorialPrefix(string name, bool force)
		{
			return false;
		}

		[HarmonyPatch(typeof(MessageHud), "QueueUnlockMsg")]
		[HarmonyPrefix]
		private static bool MessageHudQueueUnlockMessagePrefix(Sprite icon, string topic, string description)
		{
			return !Configs.NoUnlockMsg.Value;
		}

		[HarmonyPatch(typeof(Player), "SetLocalPlayer")]
		[HarmonyPostfix]
		private static void SetLocalPlayerPostfix(Player __instance)
		{
			if (Configs.DevCommands.Value && Object.op_Implicit((Object)(object)__instance))
			{
				if (!((Terminal)Console.instance).IsCheatsEnabled())
				{
					((Terminal)Console.instance).TryRunCommand("devcommands", true, true);
				}
				if (Configs.DebugMode.Value)
				{
					Player.m_debugMode = true;
				}
				if (Configs.God.Value)
				{
					__instance.SetGodMode(true);
				}
				if (Configs.Ghost.Value)
				{
					__instance.SetGhostMode(true);
				}
				if (Configs.NoCost.Value && !__instance.NoCostCheat())
				{
					__instance.ToggleNoPlacementCost();
				}
				if (Configs.NoPieceDelay.Value)
				{
					__instance.m_placeDelay = 0f;
				}
			}
		}

		[HarmonyPatch(typeof(ZNetView), "Awake")]
		[HarmonyPrefix]
		private static bool ZNetViewAwakePrefix(ZNetView __instance)
		{
			if (ZNetView.m_useInitZDO && ZNetView.m_initZDO == null)
			{
				Logger.LogWarning((object)("Double ZNetview when initializing object " + ((Object)__instance).name + "; OVERRIDE: Deleting the " + ((Object)__instance).name + " gameobject"));
				ZNetScene.instance.Destroy(((Component)__instance).gameObject);
				return false;
			}
			return true;
		}
	}
	internal static class Prefabs
	{
		public static HashSet<string> AddedPrefabs = new HashSet<string>();

		private static HashSet<string> pieceNameCache = null;

		private static readonly HashSet<string> IgnoredPrefabs = new HashSet<string> { "Player", "Valkyrie", "HelmetOdin", "CapeOdin", "CastleKit_pot03", "Ravens", "TERRAIN_TEST", "PlaceMarker", "Circle_section" };

		private const int NumPiecesPerPage = 90;

		private static Dictionary<string, int> itemCounts = new Dictionary<string, int>
		{
			{ "Extended", 0 },
			{ "Pickable", 0 },
			{ "NPCs", 0 },
			{ "Spawners", 0 },
			{ "Vegetation", 0 },
			{ "Furniture", 90 },
			{ "Building", 90 },
			{ "Destructible", 0 },
			{ "Other", 0 }
		};

		private static readonly HashSet<string> unrestrictedExceptions = new HashSet<string> { "horizontal_web", "tunnel_web", "dragoneggcup", "SmokeBall", "HeathRockPillar", "MountainGraveStone01", "Rock_7", "demister_ball" };

		private static readonly HashSet<string> restrictedExceptions = new HashSet<string> { "Pickable_SurtlingCoreStand" };

		private static HashSet<string> GetPieceNames()
		{
			if (pieceNameCache == null)
			{
				pieceNameCache = new HashSet<string>(from piece in Resources.FindObjectsOfTypeAll<PieceTable>().SelectMany((PieceTable pieceTable) => pieceTable.m_pieces)
					select ((Object)piece).name);
			}
			return pieceNameCache;
		}

		private static bool ShouldIgnorePrefab(GameObject prefab)
		{
			HashSet<string> pieceNames = GetPieceNames();
			if (!prefab.HasAnyComponentInChildren(typeof(Collider), typeof(Renderer), typeof(CreatureSpawner), typeof(SpawnArea)))
			{
				return true;
			}
			if (!prefab.HasAnyComponent("Projectile", "TimedDestruction", "Ragdoll", "LocationProxy", "Gibber", "MineRock5", "FishingFloat", "Smoke", "TeleportAbility") && (!prefab.HasAnyComponent("ItemDrop") || prefab.HasAnyComponent("Fish")) && (!prefab.HasAnyComponent("Aoe") || prefab.HasAnyComponent("Collider", "MeshCollider", "WearNTear")) && !((Object)prefab).name.StartsWith("vfx_") && !((Object)prefab).name.StartsWith("sfx_") && !((Object)prefab).name.StartsWith("fx_") && !((Object)prefab).name.StartsWith("_") && !((Object)prefab).name.EndsWith("_aoe") && !IgnoredPrefabs.Contains(((Object)prefab).name))
			{
				return pieceNames.Contains(((Object)prefab).name);
			}
			return true;
		}

		private static string GetPrefabCategory(GameObject prefab)
		{
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Invalid comparison between Unknown and I4
			Destructible component = prefab.GetComponent<Destructible>();
			string text = "Extended";
			if (prefab.HasAnyComponent("Pickable", "PickableItem"))
			{
				text = "Pickable";
			}
			else if (prefab.HasAnyComponent("Humanoid", "Character", "Leviathan", "RandomFlyingBird", "Fish", "Trader", "Odin", "Valkyrie", "Player"))
			{
				text = "NPCs";
			}
			else if (prefab.HasAnyComponent("CreatureSpawner", "SpawnArea", "TriggerSpawner"))
			{
				text = "Spawners";
			}
			else if (((Object)prefab).name.ContainsAny("Bush", "Root", "root", "shrub", "stubbe", "vines", "SwampTree") || prefab.HasAnyComponent("TreeBase", "TreeLog") || (component != null && (int)component.m_destructibleType == 2))
			{
				text = "Vegetation";
			}
			else if (prefab.HasAnyComponent("ArmorStand", "Container", "Fireplace") || ((Object)prefab).name.ContainsAny("groundtorch", "brazier", "cloth_hanging", "banner", "table", "chair", "sign", "bed"))
			{
				text = "Furniture";
			}
			else if (prefab.HasAnyComponent("WearNTear", "Door"))
			{
				text = "Building";
			}
			else if (prefab.HasAnyComponent("Destructible", "MineRock"))
			{
				text = "Destructible";
			}
			else if (Object.op_Implicit((Object)(object)prefab.GetComponent("ZNetView")))
			{
				text = "Other";
			}
			int num = itemCounts[text] / 90 + 1;
			itemCounts[text]++;
			if (num > 1)
			{
				return $"{text} {num}";
			}
			return text;
		}

		private static void ModifyPiece(Piece piece)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)piece == (Object)null))
			{
				piece.m_enabled = true;
				piece.m_canBeRemoved = true;
				if (((Component)piece).gameObject.HasAnyComponent("Character", "Pickable", "PickableItem", "Odin", "RandomFlyingBird", "Fish", "TombStone") || unrestrictedExceptions.Contains(((Object)piece).name))
				{
					piece.m_clipEverything = !restrictedExceptions.Contains(((Object)piece).name);
				}
				piece.m_groundPiece = false;
				piece.m_groundOnly = false;
				piece.m_noInWater = false;
				piece.m_notOnWood = false;
				piece.m_notOnTiltingSurface = false;
				piece.m_notOnFloor = false;
				piece.m_allowedInDungeons = true;
				piece.m_onlyInTeleportArea = false;
				piece.m_inCeilingOnly = false;
				piece.m_cultivatedGroundOnly = false;
				piece.m_onlyInBiome = (Biome)0;
				piece.m_allowRotatedOverlap = true;
			}
		}

		private static void InitPieceData(GameObject prefab)
		{
			if ((Object)(object)prefab.GetComponent<Piece>() == (Object)null)
			{
				ModifyPiece(prefab.AddComponent<Piece>());
			}
		}

		private static bool SpriteIsBlank(Sprite sprite)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Color[] pixels = sprite.texture.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				if (pixels[i].a != 0f)
				{
					return false;
				}
			}
			return true;
		}

		private static Sprite CreatePrefabIcon(GameObject prefab)
		{
			//IL_0006: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = RenderManager.Instance.Render(prefab, RenderManager.IsometricRotation);
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = prefab.GetComponent<CreatureSpawner>()?.m_creaturePrefab;
				if ((Object)(object)val2 != (Object)null)
				{
					val = RenderManager.Instance.Render(val2, RenderManager.IsometricRotation);
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				RandomItem[] array = prefab.GetComponent<PickableItem>()?.m_randomItemPrefabs;
				if (array != null && array.Length != 0)
				{
					ItemDrop itemPrefab = array[0].m_itemPrefab;
					GameObject val3 = ((itemPrefab != null) ? ((Component)itemPrefab).gameObject : null);
					if ((Object)(object)val3 != (Object)null)
					{
						val = RenderManager.Instance.Render(val3, RenderManager.IsometricRotation);
					}
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				SpriteIsBlank(val);
			}
			return val;
		}

		public static void PrepareGhostPrefab(GameObject ghost)
		{
			//IL_0090: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			ghost.DestroyComponent<CharacterDrop>();
			Component[] componentsInChildren = ghost.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!(val is Piece) && !(val is Collider) && !(val is Renderer) && !(val is Transform) && !(val is ZNetView) && !(val is Rigidbody) && !(val is MeshFilter) && !(val is LODGroup) && !(val is PickableItem) && !(val is Canvas) && !(val is CanvasRenderer) && !(val is UIBehaviour) && !(val is WearNTear))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			Bounds val2 = default(Bounds);
			Renderer[] componentsInChildren2 = ghost.GetComponentsInChildren<Renderer>();
			foreach (Renderer val3 in componentsInChildren2)
			{
				((Bounds)(ref val2)).Encapsulate(val3.bounds);
			}
			BoxCollider obj = ghost.AddComponent<BoxCollider>();
			obj.center = ((Bounds)(ref val2)).center;
			obj.size = ((Bounds)(ref val2)).size;
		}

		private static string GetPrefabFriendlyName(GameObject prefab)
		{
			HoverText component = prefab.GetComponent<HoverText>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component.m_text;
			}
			ItemDrop component2 = prefab.GetComponent<ItemDrop>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				return component2.m_itemData.m_shared.m_name;
			}
			Character component3 = prefab.GetComponent<Character>();
			if (Object.op_Implicit((Object)(object)component3))
			{
				return component3.m_name;
			}
			RuneStone component4 = prefab.GetComponent<RuneStone>();
			if (Object.op_Implicit((Object)(object)component4))
			{
				return component4.m_name;
			}
			ItemStand component5 = prefab.GetComponent<ItemStand>();
			if (Object.op_Implicit((Object)(object)component5))
			{
				return component5.m_name;
			}
			MineRock component6 = prefab.GetComponent<MineRock>();
			if (Object.op_Implicit((Object)(object)component6))
			{
				return component6.m_name;
			}
			Pickable component7 = prefab.GetComponent<Pickable>();
			if (Object.op_Implicit((Object)(object)component7))
			{
				return GetPrefabFriendlyName(component7.m_itemPrefab);
			}
			CreatureSpawner component8 = prefab.GetComponent<CreatureSpawner>();
			if (Object.op_Implicit((Object)(object)component8))
			{
				return GetPrefabFriendlyName(component8.m_creaturePrefab);
			}
			SpawnArea component9 = prefab.GetComponent<SpawnArea>();
			if (Object.op_Implicit((Object)(object)component9) && component9.m_prefabs.Count > 0)
			{
				return GetPrefabFriendlyName(component9.m_prefabs[0].m_prefab);
			}
			Piece component10 = prefab.GetComponent<Piece>();
			if (Object.op_Implicit((Object)(object)component10) && !string.IsNullOrEmpty(component10.m_name))
			{
				return component10.m_name;
			}
			return ((Object)prefab).name;
		}

		private static bool EnsureNoDuplicateZNetView(GameObject prefab)
		{
			ZNetView[] components = prefab.GetComponents<ZNetView>();
			for (int i = 1; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			return components.Length <= 1;
		}

		private static void CreatePrefabPiece(GameObject prefab)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (EnsureNoDuplicateZNetView(prefab))
			{
				InitPieceData(prefab);
				PieceConfig val = new PieceConfig
				{
					Name = ((Object)prefab).name,
					Description = GetPrefabFriendlyName(prefab),
					PieceTable = "_HammerPieceTable",
					Category = GetPrefabCategory(prefab),
					AllowedInDungeons = true,
					Icon = CreatePrefabIcon(prefab)
				};
				CustomPiece val2 = new CustomPiece(prefab, true, val);
				PieceManager.Instance.AddPiece(val2);
				AddedPrefabs.Add(((Object)prefab).name);
			}
		}

		private static void OnVanillaLocationsAvailable()
		{
		}

		public static void FindAndRegisterPrefabs()
		{
			(from go in ZNetScene.instance.m_prefabs
				where (Object)(object)go.transform.parent == (Object)null && !ShouldIgnorePrefab(go)
				orderby ((Object)go).name
				select go).ToList().ForEach(CreatePrefabPiece);
			ZoneManager.OnVanillaLocationsAvailable += OnVanillaLocationsAvailable;
		}
	}
	[BepInPlugin("com.heinermann.bettercreative", "BetterCreative", "1.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class BetterCreative : BaseUnityPlugin
	{
		public const string PluginGUID = "com.heinermann.bettercreative";

		public const string PluginName = "BetterCreative";

		public const string PluginVersion = "1.5.0";

		private readonly Harmony harmony = new Harmony("com.heinermann.bettercreative");

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		private void Awake()
		{
			Game.isModded = true;
			Configs.Init(((BaseUnityPlugin)this).Config);
			Console.SetConsoleEnabled(true);
			PieceManager.Instance.GetPieceTables();
			harmony.PatchAll();
		}

		public static void ShowHUDMessage(string msg)
		{
			Logger.LogInfo((object)msg);
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)1, msg, 0, (Sprite)null);
			}
		}

		private void KeyDeletePressed()
		{
			GameObject selectedPrefab = Patches.GetSelectedPrefab(Player.m_localPlayer);
			if ((Object)(object)selectedPrefab == (Object)null)
			{
				return;
			}
			GameObject ghost = Patches.lastPlacementGhost;
			if (!((Object)(object)ghost == (Object)null))
			{
				string matchPattern = "^" + Regex.Escape(((Object)selectedPrefab).name) + "(\\(Clone\\))?$";
				float sqrRadius = Configs.DeleteRange.Value * Configs.DeleteRange.Value;
				List<GameObject> list = (from inst in AccessTools.FieldRefAccess<ZNetScene, Dictionary<ZDO, ZNetView>>(ZNetScene.instance, "m_instances").Values.Where((ZNetView inst) => Regex.IsMatch(((Object)inst).name, matchPattern)).Where(delegate(ZNetView inst)
					{
						//IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references)
						//IL_0020: Unknown result type (might be due to invalid IL or missing references)
						Vector3 val = ((Component)inst).transform.position - ghost.transform.position;
						return ((Vector3)(ref val)).sqrMagnitude <= sqrRadius;
					})
					select ((Component)inst).gameObject).ToList();
				UndoHelper.Remove((IEnumerable<GameObject>)list);
				list.ForEach((Action<GameObject>)ZNetScene.instance.Destroy);
				ShowHUDMessage($"Deleted {list.Count} Objects");
			}
		}

		private bool InLoadingScreen()
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				return ((Character)Player.m_localPlayer).IsTeleporting();
			}
			return true;
		}

		private void Update()
		{
			//IL_001a: 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)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || InLoadingScreen())
			{
				return;
			}
			KeyboardShortcut value = Configs.KeyUndo1.Value;
			if (!((KeyboardShortcut)(ref value)).IsDown())
			{
				value = Configs.KeyUndo2.Value;
				if (!((KeyboardShortcut)(ref value)).IsDown())
				{
					value = Configs.KeyRedo1.Value;
					if (!((KeyboardShortcut)(ref value)).IsDown())
					{
						value = Configs.KeyRedo2.Value;
						if (!((KeyboardShortcut)(ref value)).IsDown())
						{
							value = Configs.KeyDelete1.Value;
							if (!((KeyboardShortcut)(ref value)).IsDown())
							{
								value = Configs.KeyDelete2.Value;
								if (!((KeyboardShortcut)(ref value)).IsDown())
								{
									return;
								}
							}
							KeyDeletePressed();
							return;
						}
					}
					UndoHelper.Redo();
					return;
				}
			}
			UndoHelper.Undo();
		}

		public static GameObject PlacePiece(GameObject prefab, Vector3 position, Quaternion rotation)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			TerrainModifier.SetTriggerOnPlaced(true);
			GameObject obj = Object.Instantiate<GameObject>(prefab, position, rotation);
			TerrainModifier.SetTriggerOnPlaced(false);
			CraftingStation componentInChildren = obj.GetComponentInChildren<CraftingStation>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				Player.m_localPlayer.AddKnownStation(componentInChildren);
			}
			Piece component = obj.GetComponent<Piece>();
			if (component != null)
			{
				component.SetCreator(Player.m_localPlayer.GetPlayerID());
			}
			PrivateArea component2 = obj.GetComponent<PrivateArea>();
			if (component2 != null)
			{
				component2.Setup(Game.instance.GetPlayerProfile().GetName());
			}
			WearNTear component3 = obj.GetComponent<WearNTear>();
			if (component3 != null)
			{
				component3.OnPlaced();
				return obj;
			}
			return obj;
		}

		public static void ModifyItems()
		{
			if (!Configs.NoDurabilityDrain.Value)
			{
				return;
			}
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				ItemDrop component = item.GetComponent<ItemDrop>();
				if (!((Object)(object)component == (Object)null))
				{
					component.m_itemData.m_shared.m_useDurabilityDrain = 0f;
				}
			}
		}
	}
	internal static class UndoHelper
	{
		public static void Remove(IEnumerable<GameObject> objects)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			List<GameObject> list = objects.ToList();
			List<ZDO> list2 = (from zdo in list.Select(delegate(GameObject obj)
				{
					ZNetView component = obj.GetComponent<ZNetView>();
					return (component == null) ? null : component.GetZDO();
				})
				where zdo != null
				select zdo).ToList();
			if (list2.Any())
			{
				Logger.LogInfo((object)$"Removing {list2.Count} objects");
				UndoRemove val = new UndoRemove((IEnumerable<ZDO>)list2);
				UndoManager.Instance.Add("BetterCreative", (IUndoAction)(object)val);
			}
			else if (list.Any())
			{
				Logger.LogWarning((object)$"No ZDOs associated with {list.Count} deleted objects");
			}
		}

		public static void Remove(GameObject obj)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			ZNetView component = obj.GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val != null)
			{
				Logger.LogInfo((object)("Removing " + ((Object)obj).name));
				UndoRemove val2 = new UndoRemove((IEnumerable<ZDO>)(object)new ZDO[1] { val });
				UndoManager.Instance.Add("BetterCreative", (IUndoAction)(object)val2);
			}
			else
			{
				Logger.LogWarning((object)("No ZDO associated with " + ((Object)obj).name));
			}
		}

		public static void Create(IEnumerable<GameObject> objects)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			List<GameObject> list = objects.ToList();
			List<ZDO> list2 = (from zdo in list.Select(delegate(GameObject obj)
				{
					ZNetView component = obj.GetComponent<ZNetView>();
					return (component == null) ? null : component.GetZDO();
				})
				where zdo != null
				select zdo).ToList();
			if (list2.Any())
			{
				Logger.LogInfo((object)$"Creating {list2.Count} objects");
				UndoCreate val = new UndoCreate((IEnumerable<ZDO>)list2);
				UndoManager.Instance.Add("BetterCreative", (IUndoAction)(object)val);
			}
			else if (list.Any())
			{
				Logger.LogWarning((object)$"No ZDOs associated with {list.Count} created objects");
			}
		}

		public static void Create(GameObject obj)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			ZNetView component = obj.GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val != null)
			{
				Logger.LogInfo((object)("Creating " + ((Object)obj).name));
				UndoCreate val2 = new UndoCreate((IEnumerable<ZDO>)(object)new ZDO[1] { val });
				UndoManager.Instance.Add("BetterCreative", (IUndoAction)(object)val2);
			}
			else
			{
				Logger.LogWarning((object)("No ZDO associated with " + ((Object)obj).name));
			}
		}

		public static void Undo()
		{
			UndoManager.Instance.Undo("BetterCreative");
		}

		public static void Redo()
		{
			UndoManager.Instance.Redo("BetterCreative");
		}
	}
}