Decompiled source of DvergrBuild v0.1.6

plugins/DvergrBuild.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DvergrBuild.Core;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
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("DvergrBuild")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyInformationalVersion("0.1.6+ce6115e2ccf808e519530f67d4a59cab8a25c51d")]
[assembly: AssemblyProduct("DvergrBuild")]
[assembly: AssemblyTitle("DvergrBuild")]
[assembly: AssemblyVersion("0.1.6.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 DvergrBuild
{
	[BepInPlugin("sansara.DvergrBuild", "Dvergr Build", "0.1.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static class DvergrCategory
		{
			private static readonly FieldRef<ByUsagePieceList, UsageTagFlags[]> Tags = AccessTools.FieldRefAccess<ByUsagePieceList, UsageTagFlags[]>("m_usageTags");

			private static readonly FieldRef<ByUsagePieceList, string[]> Names = AccessTools.FieldRefAccess<ByUsagePieceList, string[]>("m_usageTagDisplayNames");

			private static void Postfix(ByUsagePieceList __instance)
			{
				if (!Tags.Invoke(__instance).Contains((UsageTagFlags)1073741824))
				{
					Tags.Invoke(__instance) = Tags.Invoke(__instance).Concat((IEnumerable<UsageTagFlags>)(object)new UsageTagFlags[1] { (UsageTagFlags)1073741824 }).ToArray();
					Names.Invoke(__instance) = Names.Invoke(__instance).Concat(new string[1] { "Дверги" }).ToArray();
					Log.LogInfo((object)$"Дверги: категория добавлена в меню строительства (всего категорий {Tags.Invoke(__instance).Length}).");
				}
			}
		}

		[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
		private static class LearnQuietly
		{
			private static readonly FieldRef<Player, HashSet<string>> Known = AccessTools.FieldRefAccess<Player, HashSet<string>>("m_knownRecipes");

			private static readonly FieldRef<Player, Dictionary<string, int>> Stations = AccessTools.FieldRefAccess<Player, Dictionary<string, int>>("m_knownStations");

			private static readonly FieldRef<Player, HashSet<string>> Materials = AccessTools.FieldRefAccess<Player, HashSet<string>>("m_knownMaterial");

			private static int _calls;

			private static bool _explained;

			private static void Prefix(HashSet<string> knownRecipies, Player player)
			{
				if ((Object)(object)player == (Object)null || knownRecipies == null || Prepared.Count == 0)
				{
					return;
				}
				HashSet<string> known = knownRecipies;
				int num = 0;
				foreach (GameObject item in Prepared)
				{
					Piece component = item.GetComponent<Piece>();
					if ((Object)(object)component != (Object)null && !known.Contains(component.m_name) && player.HaveRequirements(component, (RequirementMode)1))
					{
						known.Add(component.m_name);
						num++;
					}
				}
				_calls++;
				if (num > 0)
				{
					Log.LogInfo((object)$"Дверги: изучено деталей {num}.");
				}
				else
				{
					if (_explained || Prepared.Count((GameObject p) => !known.Contains(p.GetComponent<Piece>().m_name)) <= 0)
					{
						return;
					}
					_explained = true;
					foreach (GameObject item2 in Prepared.Where((GameObject p) => !known.Contains(p.GetComponent<Piece>().m_name)).Take(4))
					{
						Piece component2 = item2.GetComponent<Piece>();
						string text = (((Object)(object)component2.m_craftingStation != (Object)null) ? component2.m_craftingStation.m_name : "нет");
						bool flag = (Object)(object)component2.m_craftingStation == (Object)null || Stations.Invoke(player).ContainsKey(text);
						string text2 = string.Join(",", from r in component2.m_resources
							where (Object)(object)r.m_resItem != (Object)null && !Materials.Invoke(player).Contains(r.m_resItem.m_itemData.m_shared.m_name)
							select ((Object)r.m_resItem).name + "(" + r.m_resItem.m_itemData.m_shared.m_name + ")");
						Log.LogInfo((object)($"Дверги: {((Object)item2).name} не изучена — enabled={component2.m_enabled}, станция {text} известна={flag}, неизвестные материалы [{text2}]; " + string.Format("известных станций {0}: {1}; вызов №{2}.", Stations.Invoke(player).Count, string.Join(",", Stations.Invoke(player).Keys.Take(12)), _calls)));
					}
				}
			}
		}

		[HarmonyPatch(typeof(ByUsagePieceList), "UpdateAvailableTags")]
		private static class CountAvailable
		{
			private static int _last = -1;

			private static void Postfix(PieceTable pieceTable)
			{
				int num = pieceTable.m_availablePieces.Count((Piece p) => (Object)(object)p != (Object)null && (p.m_usage & 0x40000000) > 0);
				int num2 = pieceTable.m_pieces.Count((GameObject p) => (Object)(object)p != (Object)null && Catalogued.Contains(((Object)p).name));
				if (num != _last)
				{
					_last = num;
					Log.LogInfo((object)$"Дверги: в таблице {((Object)pieceTable).name} наших деталей {num2}, доступных игроку {num}, всего доступно {pieceTable.m_availablePieces.Count}.");
				}
			}
		}

		[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
		private static class GhostCollider
		{
			private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");

			private static void Postfix(Player __instance)
			{
				//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_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0138: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = Ghost.Invoke(__instance);
				if ((Object)(object)val == (Object)null || !Catalogued.Contains(Utils.GetPrefabName(val)) || val.GetComponentsInChildren<Collider>().Any(delegate(Collider c)
				{
					if (c.enabled && !c.isTrigger)
					{
						MeshCollider val2 = (MeshCollider)(object)((c is MeshCollider) ? c : null);
						if (val2 != null)
						{
							return val2.convex;
						}
						return true;
					}
					return false;
				}))
				{
					return;
				}
				Renderer[] array = (from r in val.GetComponentsInChildren<Renderer>()
					where r.enabled && ((Component)r).gameObject.activeInHierarchy
					select r).ToArray();
				if (array.Length == 0)
				{
					return;
				}
				Bounds bounds = array[0].bounds;
				foreach (Renderer item in array.Skip(1))
				{
					((Bounds)(ref bounds)).Encapsulate(item.bounds);
				}
				BoxCollider obj = val.AddComponent<BoxCollider>();
				obj.center = val.transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
				Vector3 lossyScale = val.transform.lossyScale;
				obj.size = new Vector3(((Bounds)(ref bounds)).size.x / Mathf.Max(0.001f, lossyScale.x), ((Bounds)(ref bounds)).size.y / Mathf.Max(0.001f, lossyScale.y), ((Bounds)(ref bounds)).size.z / Mathf.Max(0.001f, lossyScale.z));
			}
		}

		[HarmonyPatch(typeof(Player), "CheckCanRemovePiece")]
		private static class NoRuinRemoval
		{
			private static bool Prefix(Piece piece, ref bool __result)
			{
				if ((Object)(object)piece == (Object)null || piece.IsPlacedByPlayer() || !Added.Contains(Utils.GetPrefabName(((Component)piece).gameObject)))
				{
					return true;
				}
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "Это часть древней постройки — разобрать нельзя.", 0, (Sprite)null, false);
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(DropOnDestroyed), "OnDestroyed")]
		private static class NoDoubleDrop
		{
			private static bool Prefix(DropOnDestroyed __instance)
			{
				Piece component = ((Component)__instance).GetComponent<Piece>();
				if (!((Object)(object)component == (Object)null) && component.IsPlacedByPlayer())
				{
					return !Catalogued.Contains(Utils.GetPrefabName(((Component)__instance).gameObject));
				}
				return true;
			}
		}

		public const string Guid = "sansara.DvergrBuild";

		public const string Name = "Dvergr Build";

		public const string Version = "0.1.6";

		private const string CategoryName = "Дверги";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static readonly HashSet<string> Catalogued = new HashSet<string>(StringComparer.Ordinal);

		internal static readonly HashSet<string> Added = new HashSet<string>(StringComparer.Ordinal);

		private static List<Entry> _entries = new List<Entry>();

		private static readonly List<GameObject> Prepared = new List<GameObject>();

		internal const UsageTagFlags DvergrTag = (UsageTagFlags)1073741824;

		private static bool _ready;

		private void Awake()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Вкладка «Дверги» в молотке.");
			List<string> list = new List<string>();
			_entries = Catalog.Parse("\ndvergrprops_wood_wall|Двергская деревянная стена|F|YggdrasilWood:10,Copper:4|Wood:5,CopperScrap:5\npiece_dvergr_wood_wall|Двергская стена с ригелем|F|YggdrasilWood:20,Copper:10|\npiece_dvergr_wood_door|Двергские ворота|F|YggdrasilWood:8,Copper:8|\ndvergrprops_wood_beam|Двергская балка 6 м|F|YggdrasilWood:6,Copper:2|Wood:1\ndvergrprops_wood_pole|Двергский столб 4 м|F|YggdrasilWood:4,Copper:2|Wood:1,CopperScrap:1\npiece_dvergr_pole|Двергский столб 2 м|F|YggdrasilWood:4,Copper:2|\ndvergrprops_wood_stake|Двергский кол|F|YggdrasilWood:2|Wood:1\ndvergrprops_wood_stakewall|Двергский частокол|F|YggdrasilWood:8,Iron:4|Wood:5\ndvergrprops_wood_floor|Двергский пол 2×2|F|YggdrasilWood:2|\ndvergrprops_wood_stair|Двергская лестница|F|YggdrasilWood:4|\ndvergrtown_stair_corner_wood_left|Двергская угловая лестница|F|YggdrasilWood:5,Copper:2|Wood:3,CopperScrap:3\ndvergrtown_wood_crane|Двергский кран|F|YggdrasilWood:20,Copper:6,Chain:4|Wood:4,CopperScrap:4,Chain:4\ndvergrprops_bed|Двергская кровать (декор)|F|YggdrasilWood:6,Copper:4|Wood:4,CopperScrap:4\ndvergrprops_table|Двергский стол|F|YggdrasilWood:4,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_chair|Двергский стул (декор)|F|YggdrasilWood:2,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_stool|Двергский табурет (декор)|F|YggdrasilWood:2,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_shelf|Двергская полка|F|YggdrasilWood:4,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_banner|Двергский флаг|F|JuteBlue:2|JuteBlue:2\ndvergrprops_curtain|Двергская занавесь|F|JuteBlue:2|JuteBlue:2\ndvergrprops_hooknchain|Двергский крюк на цепи|F|Copper:2,Chain:2|CopperScrap:2,Chain:2\ndvergrprops_lantern|Двергский настенный фонарь|F|Copper:2,SurtlingCore:2|CopperScrap:2,SurtlingCore:2\ndvergrprops_lantern_standing|Двергский малый фонарь|F|Copper:2,SurtlingCore:2|CopperScrap:2,SurtlingCore:2\nblackmarble_2x2x1|Чёрный мрамор 2×2×1|S|BlackMarble:4|\nblackmarble_2x2_enforced|Чёрный мрамор укреплённый 2×2×2|S|BlackMarble:8,Copper:2|\nblackmarble_base_2|Широкий постамент из чёрного мрамора|S|BlackMarble:8|\nblackmarble_column_3|Высокая колонна из чёрного мрамора 8 м|S|BlackMarble:12|\nblackmarble_creep_4x1x1|Чёрный мрамор с плющом 1×4×1|S|BlackMarble:6|\nblackmarble_creep_4x2x1|Чёрный мрамор с плющом 2×4×1|S|BlackMarble:10|\nblackmarble_creep_slope_inverted_1x1x2|Карниз с плющом 1×2|S|BlackMarble:2|\nblackmarble_creep_slope_inverted_2x2x1|Карниз с плющом 2×2|S|BlackMarble:4|\nblackmarble_creep_stair|Ступени с плющом|S|BlackMarble:4|\nblackmarble_floor_large|Пол из чёрного мрамора 8×8|S|BlackMarble:64|\nblackmarble_head01|Бронзовая голова 1|S|Bronze:2|\nblackmarble_head02|Бронзовая голова 2|S|Bronze:2|\nblackmarble_head_big01|Большая мраморная голова 1|S|BlackMarble:8|\nblackmarble_head_big02|Большая мраморная голова 2|S|BlackMarble:8|\nblackmarble_out_2|Широкий карниз из чёрного мрамора|S|BlackMarble:8|\nblackmarble_slope_1x2|Откос из чёрного мрамора|S|BlackMarble:2|\nblackmarble_slope_inverted_1x2|Обратный откос из чёрного мрамора|S|BlackMarble:2|\nblackmarble_stair_corner|Угловые ступени из чёрного мрамора, правые|S|BlackMarble:4|\nblackmarble_stair_corner_left|Угловые ступени из чёрного мрамора, левые|S|BlackMarble:4|\nblackmarble_tile_floor_1x1|Плитка пола из чёрного мрамора 1×1|S|BlackMarble:1|\nblackmarble_tile_floor_2x2|Плитка пола из чёрного мрамора 2×2|S|BlackMarble:2|\nblackmarble_tile_wall_1x1|Плитка стены из чёрного мрамора 1×1|S|BlackMarble:1|\nblackmarble_tile_wall_2x2|Плитка стены из чёрного мрамора 2×2|S|BlackMarble:2|\nblackmarble_tile_wall_2x4|Плитка стены из чёрного мрамора 2×4|S|BlackMarble:4|\nAshlands_Wall_2x2|Стена руин 2×2|S|Grausten:6|\nAshlands_Wall_2x2_top|Стена руин 2×2, верх|S|Grausten:6|\nAshlands_Wall_2x2_edge|Стена руин 2×2, край|S|Grausten:6|\nAshlands_Wall_2x2_edge_top|Стена руин 2×2, край, верх|S|Grausten:6|\nAshlands_Wall_2x2_edge2|Стена руин 2×2, край 2|S|Grausten:6|\nAshlands_Wall_2x2_edge2_top|Стена руин 2×2, край 2, верх|S|Grausten:6|\nAshlands_Wall_2x2_cornerL|Стена руин 2×2, угол левый|S|Grausten:6|\nAshlands_Wall_2x2_cornerL_top|Стена руин 2×2, угол левый, верх|S|Grausten:6|\nAshlands_Wall_2x2_cornerR|Стена руин 2×2, угол правый|S|Grausten:6|\nAshlands_Wall_2x2_cornerR_top|Стена руин 2×2, угол правый, верх|S|Grausten:6|\nAshlands_WallBlock_base|Блок руин 2×2×1|S|Grausten:6|\nAshlands_WallBlock_1x2x2|Блок руин 1×2×2|S|Grausten:6|\nAshlands_Ruins_Wall_Top_wHole|Верх стены руин с проёмом|S|Grausten:12|\nAshlands_Arch1|Арка руин|S|Grausten:8|\nAshlands_Arch2|Большая арка руин|S|Grausten:10|\nAshlands_Ruins_twist_ArchBig|Витая арка руин|S|Grausten:6|Grausten:3\nAshlands_Ruins_twist_PillarBase|Витая колонна руин|S|Grausten:5|Grausten:3\nAshlands_Ruins_twist_PillarBaseSmall|Малая витая колонна руин|S|Grausten:2|Grausten:2\nAshlands_Pillar4|Колонна руин 4 м|S|Grausten:5|Grausten:3\nAshlands_Pillar4_tip|Колонна руин с навершием 6 м|S|Grausten:6|\nAshlands_Pillar4_tip2|Колонна руин с навершием 6 м, вариант 2|S|Grausten:6|\nAshlands_Pillar4_tip3|Колонна руин с навершием 10 м|S|Grausten:8|\nAshlands_PillarBase3_double|Двойное основание колонны|S|Grausten:3|Grausten:3\nAshlands_Boss_Pillar|Огромная колонна руин 8 м|S|Grausten:20|Grausten:8\nAshlands_Floor|Плита пола руин 2×2|S|Grausten:4|\nAshlands_Fortress_Floor|Плита пола крепости 2×2|S|Grausten:4|Stone:3\nAshlands_Ruins_Floor_1point5x1point5|Плита пола руин 1,5×1,5|S|Grausten:2|Grausten:2\nAshlands_Ruins_Floor_3x3|Плита пола руин 3×3|S|Grausten:4|Grausten:2\nAshlands_Ruins_Floor_6x6|Плита пола руин 6×6|S|Grausten:12|Grausten:4\nAshlands_Ruins_TopStone|Камень-навершие руин|S|Grausten:2|Grausten:2\nAshland_Stair|Широкие ступени руин|S|Grausten:10|Stone:5\nAshlands_StairsBroad|Широкая лестница руин|S|Grausten:10|\nAshland_Steepstair|Крутые ступени руин|S|Grausten:5|Grausten:4\nAshlands_Ramp|Пандус руин|S|Grausten:8|\nAshlands_Ruins_Ramp|Пандус руин с обломками|S|Grausten:8|Grausten:4\nAshlands_Ruins_Ramp_Upsidedown|Обратный пандус руин|S|Grausten:8|Grausten:4\n", list);
			list.ForEach(delegate(string e)
			{
				Log.LogWarning((object)("Дверги: каталог — " + e));
			});
			if (Enabled.Value)
			{
				new Harmony("sansara.DvergrBuild").PatchAll();
				PrefabManager.OnVanillaPrefabsAvailable += Prepare;
				PieceManager.OnPiecesRegistered += AddToHammer;
				Log.LogInfo((object)string.Format("{0} {1} загружен, в каталоге {2} деталей.", "Dvergr Build", "0.1.6", _entries.Count));
			}
		}

		private static void Prepare()
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			if (_ready)
			{
				return;
			}
			_ready = true;
			CraftingStation prefab = Cache.GetPrefab<CraftingStation>("blackforge");
			CraftingStation prefab2 = Cache.GetPrefab<CraftingStation>("piece_stonecutter");
			Piece prefab3 = Cache.GetPrefab<Piece>("piece_dvergr_pole");
			Piece prefab4 = Cache.GetPrefab<Piece>("blackmarble_1x1");
			int num = 0;
			int num2 = 0;
			foreach (Entry entry in _entries)
			{
				GameObject prefab5 = Cache.GetPrefab<GameObject>(entry.Prefab);
				if ((Object)(object)prefab5 == (Object)null || (Object)(object)prefab5.GetComponent<ZNetView>() == (Object)null)
				{
					num++;
					Log.LogWarning((object)("Дверги: префаба " + entry.Prefab + " нет в игре — пропущен."));
					continue;
				}
				List<Requirement> list = new List<Requirement>();
				foreach (Cost cost in entry.Costs)
				{
					ItemDrop prefab6 = Cache.GetPrefab<ItemDrop>(cost.Item);
					if ((Object)(object)prefab6 == (Object)null)
					{
						Log.LogWarning((object)("Дверги: предмета " + cost.Item + " нет в игре (" + entry.Prefab + ")."));
					}
					else
					{
						list.Add(new Requirement
						{
							m_resItem = prefab6,
							m_amount = cost.Amount,
							m_recover = true
						});
					}
				}
				if (list.Count == 0)
				{
					num++;
					continue;
				}
				Piece val = prefab5.GetComponent<Piece>();
				if ((Object)(object)val == (Object)null)
				{
					val = prefab5.AddComponent<Piece>();
					Added.Add(entry.Prefab);
				}
				Piece val2 = ((entry.Station == Station.BlackForge) ? prefab3 : prefab4);
				val.m_name = entry.Name;
				val.m_description = "";
				val.m_category = (PieceCategory)0;
				val.m_usage = (UsageTagFlags)1073741824;
				val.m_craftingStation = ((entry.Station == Station.BlackForge) ? prefab : prefab2);
				val.m_resources = list.ToArray();
				val.m_canBeRemoved = true;
				val.m_enabled = true;
				if ((Object)(object)val2 != (Object)null && (val.m_placeEffect == null || val.m_placeEffect.m_effectPrefabs == null || val.m_placeEffect.m_effectPrefabs.Length == 0))
				{
					val.m_placeEffect = val2.m_placeEffect;
				}
				if ((Object)(object)val.m_icon == (Object)null)
				{
					num2++;
					Piece target = val;
					RenderManager.Instance.EnqueueRender(prefab5, (Action<Sprite>)delegate(Sprite sprite)
					{
						target.m_icon = sprite;
					});
				}
				Catalogued.Add(entry.Prefab);
				Prepared.Add(prefab5);
			}
			Log.LogInfo((object)$"Дверги: подготовлено {Prepared.Count} деталей (из них {Added.Count} без строительной части в игре), значков рисуется {num2}, пропущено {num}.");
		}

		private static void AddToHammer()
		{
			Prepare();
			object obj = PieceManager.Instance.GetPieceTable("Hammer");
			if (obj == null)
			{
				ObjectDB instance = ObjectDB.instance;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					GameObject itemPrefab = instance.GetItemPrefab("Hammer");
					obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces);
				}
			}
			PieceTable table = (PieceTable)obj;
			if ((Object)(object)table == (Object)null)
			{
				Log.LogWarning((object)"Дверги: таблица молотка не найдена.");
				return;
			}
			int num = 0;
			foreach (GameObject item in Prepared.Where((GameObject p) => !table.m_pieces.Contains(p)))
			{
				table.m_pieces.Add(item);
				num++;
			}
			if (num > 0)
			{
				Log.LogInfo((object)string.Format("Дверги: в молоток добавлено {0} деталей (категория «{1}»).", num, "Дверги"));
			}
		}
	}
}
namespace DvergrBuild.Core
{
	public enum Station
	{
		BlackForge,
		Stonecutter
	}
	public sealed class Cost
	{
		public string Item = "";

		public int Amount;
	}
	public sealed class Entry
	{
		public string Prefab = "";

		public string Name = "";

		public Station Station;

		public List<Cost> Costs = new List<Cost>();

		public List<Cost> Drops = new List<Cost>();
	}
	public static class Catalog
	{
		public const string Default = "\ndvergrprops_wood_wall|Двергская деревянная стена|F|YggdrasilWood:10,Copper:4|Wood:5,CopperScrap:5\npiece_dvergr_wood_wall|Двергская стена с ригелем|F|YggdrasilWood:20,Copper:10|\npiece_dvergr_wood_door|Двергские ворота|F|YggdrasilWood:8,Copper:8|\ndvergrprops_wood_beam|Двергская балка 6 м|F|YggdrasilWood:6,Copper:2|Wood:1\ndvergrprops_wood_pole|Двергский столб 4 м|F|YggdrasilWood:4,Copper:2|Wood:1,CopperScrap:1\npiece_dvergr_pole|Двергский столб 2 м|F|YggdrasilWood:4,Copper:2|\ndvergrprops_wood_stake|Двергский кол|F|YggdrasilWood:2|Wood:1\ndvergrprops_wood_stakewall|Двергский частокол|F|YggdrasilWood:8,Iron:4|Wood:5\ndvergrprops_wood_floor|Двергский пол 2×2|F|YggdrasilWood:2|\ndvergrprops_wood_stair|Двергская лестница|F|YggdrasilWood:4|\ndvergrtown_stair_corner_wood_left|Двергская угловая лестница|F|YggdrasilWood:5,Copper:2|Wood:3,CopperScrap:3\ndvergrtown_wood_crane|Двергский кран|F|YggdrasilWood:20,Copper:6,Chain:4|Wood:4,CopperScrap:4,Chain:4\ndvergrprops_bed|Двергская кровать (декор)|F|YggdrasilWood:6,Copper:4|Wood:4,CopperScrap:4\ndvergrprops_table|Двергский стол|F|YggdrasilWood:4,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_chair|Двергский стул (декор)|F|YggdrasilWood:2,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_stool|Двергский табурет (декор)|F|YggdrasilWood:2,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_shelf|Двергская полка|F|YggdrasilWood:4,Copper:3|Wood:3,CopperScrap:3\ndvergrprops_banner|Двергский флаг|F|JuteBlue:2|JuteBlue:2\ndvergrprops_curtain|Двергская занавесь|F|JuteBlue:2|JuteBlue:2\ndvergrprops_hooknchain|Двергский крюк на цепи|F|Copper:2,Chain:2|CopperScrap:2,Chain:2\ndvergrprops_lantern|Двергский настенный фонарь|F|Copper:2,SurtlingCore:2|CopperScrap:2,SurtlingCore:2\ndvergrprops_lantern_standing|Двергский малый фонарь|F|Copper:2,SurtlingCore:2|CopperScrap:2,SurtlingCore:2\nblackmarble_2x2x1|Чёрный мрамор 2×2×1|S|BlackMarble:4|\nblackmarble_2x2_enforced|Чёрный мрамор укреплённый 2×2×2|S|BlackMarble:8,Copper:2|\nblackmarble_base_2|Широкий постамент из чёрного мрамора|S|BlackMarble:8|\nblackmarble_column_3|Высокая колонна из чёрного мрамора 8 м|S|BlackMarble:12|\nblackmarble_creep_4x1x1|Чёрный мрамор с плющом 1×4×1|S|BlackMarble:6|\nblackmarble_creep_4x2x1|Чёрный мрамор с плющом 2×4×1|S|BlackMarble:10|\nblackmarble_creep_slope_inverted_1x1x2|Карниз с плющом 1×2|S|BlackMarble:2|\nblackmarble_creep_slope_inverted_2x2x1|Карниз с плющом 2×2|S|BlackMarble:4|\nblackmarble_creep_stair|Ступени с плющом|S|BlackMarble:4|\nblackmarble_floor_large|Пол из чёрного мрамора 8×8|S|BlackMarble:64|\nblackmarble_head01|Бронзовая голова 1|S|Bronze:2|\nblackmarble_head02|Бронзовая голова 2|S|Bronze:2|\nblackmarble_head_big01|Большая мраморная голова 1|S|BlackMarble:8|\nblackmarble_head_big02|Большая мраморная голова 2|S|BlackMarble:8|\nblackmarble_out_2|Широкий карниз из чёрного мрамора|S|BlackMarble:8|\nblackmarble_slope_1x2|Откос из чёрного мрамора|S|BlackMarble:2|\nblackmarble_slope_inverted_1x2|Обратный откос из чёрного мрамора|S|BlackMarble:2|\nblackmarble_stair_corner|Угловые ступени из чёрного мрамора, правые|S|BlackMarble:4|\nblackmarble_stair_corner_left|Угловые ступени из чёрного мрамора, левые|S|BlackMarble:4|\nblackmarble_tile_floor_1x1|Плитка пола из чёрного мрамора 1×1|S|BlackMarble:1|\nblackmarble_tile_floor_2x2|Плитка пола из чёрного мрамора 2×2|S|BlackMarble:2|\nblackmarble_tile_wall_1x1|Плитка стены из чёрного мрамора 1×1|S|BlackMarble:1|\nblackmarble_tile_wall_2x2|Плитка стены из чёрного мрамора 2×2|S|BlackMarble:2|\nblackmarble_tile_wall_2x4|Плитка стены из чёрного мрамора 2×4|S|BlackMarble:4|\nAshlands_Wall_2x2|Стена руин 2×2|S|Grausten:6|\nAshlands_Wall_2x2_top|Стена руин 2×2, верх|S|Grausten:6|\nAshlands_Wall_2x2_edge|Стена руин 2×2, край|S|Grausten:6|\nAshlands_Wall_2x2_edge_top|Стена руин 2×2, край, верх|S|Grausten:6|\nAshlands_Wall_2x2_edge2|Стена руин 2×2, край 2|S|Grausten:6|\nAshlands_Wall_2x2_edge2_top|Стена руин 2×2, край 2, верх|S|Grausten:6|\nAshlands_Wall_2x2_cornerL|Стена руин 2×2, угол левый|S|Grausten:6|\nAshlands_Wall_2x2_cornerL_top|Стена руин 2×2, угол левый, верх|S|Grausten:6|\nAshlands_Wall_2x2_cornerR|Стена руин 2×2, угол правый|S|Grausten:6|\nAshlands_Wall_2x2_cornerR_top|Стена руин 2×2, угол правый, верх|S|Grausten:6|\nAshlands_WallBlock_base|Блок руин 2×2×1|S|Grausten:6|\nAshlands_WallBlock_1x2x2|Блок руин 1×2×2|S|Grausten:6|\nAshlands_Ruins_Wall_Top_wHole|Верх стены руин с проёмом|S|Grausten:12|\nAshlands_Arch1|Арка руин|S|Grausten:8|\nAshlands_Arch2|Большая арка руин|S|Grausten:10|\nAshlands_Ruins_twist_ArchBig|Витая арка руин|S|Grausten:6|Grausten:3\nAshlands_Ruins_twist_PillarBase|Витая колонна руин|S|Grausten:5|Grausten:3\nAshlands_Ruins_twist_PillarBaseSmall|Малая витая колонна руин|S|Grausten:2|Grausten:2\nAshlands_Pillar4|Колонна руин 4 м|S|Grausten:5|Grausten:3\nAshlands_Pillar4_tip|Колонна руин с навершием 6 м|S|Grausten:6|\nAshlands_Pillar4_tip2|Колонна руин с навершием 6 м, вариант 2|S|Grausten:6|\nAshlands_Pillar4_tip3|Колонна руин с навершием 10 м|S|Grausten:8|\nAshlands_PillarBase3_double|Двойное основание колонны|S|Grausten:3|Grausten:3\nAshlands_Boss_Pillar|Огромная колонна руин 8 м|S|Grausten:20|Grausten:8\nAshlands_Floor|Плита пола руин 2×2|S|Grausten:4|\nAshlands_Fortress_Floor|Плита пола крепости 2×2|S|Grausten:4|Stone:3\nAshlands_Ruins_Floor_1point5x1point5|Плита пола руин 1,5×1,5|S|Grausten:2|Grausten:2\nAshlands_Ruins_Floor_3x3|Плита пола руин 3×3|S|Grausten:4|Grausten:2\nAshlands_Ruins_Floor_6x6|Плита пола руин 6×6|S|Grausten:12|Grausten:4\nAshlands_Ruins_TopStone|Камень-навершие руин|S|Grausten:2|Grausten:2\nAshland_Stair|Широкие ступени руин|S|Grausten:10|Stone:5\nAshlands_StairsBroad|Широкая лестница руин|S|Grausten:10|\nAshland_Steepstair|Крутые ступени руин|S|Grausten:5|Grausten:4\nAshlands_Ramp|Пандус руин|S|Grausten:8|\nAshlands_Ruins_Ramp|Пандус руин с обломками|S|Grausten:8|Grausten:4\nAshlands_Ruins_Ramp_Upsidedown|Обратный пандус руин|S|Grausten:8|Grausten:4\n";

		public static List<Entry> Parse(string text, List<string> errors)
		{
			List<Entry> list = new List<Entry>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			string[] array = (text ?? "").Split(new char[1] { '\n' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0 || text2.StartsWith("#", StringComparison.Ordinal))
				{
					continue;
				}
				string[] array2 = text2.Split(new char[1] { '|' });
				if (array2.Length < 4 || array2[0].Trim() == "" || array2[1].Trim() == "" || (array2[2].Trim() != "F" && array2[2].Trim() != "S"))
				{
					errors.Add("строка «" + text2 + "» не разобрана (нужно префаб|название|F или S|стоимость|добыча)");
					continue;
				}
				Entry entry = new Entry
				{
					Prefab = array2[0].Trim(),
					Name = array2[1].Trim(),
					Station = ((!(array2[2].Trim() == "F")) ? Station.Stonecutter : Station.BlackForge)
				};
				if (!TryCosts(array2[3], entry.Costs) || entry.Costs.Count == 0 || !TryCosts((array2.Length > 4) ? array2[4] : "", entry.Drops))
				{
					errors.Add("строка «" + text2 + "»: стоимость или добыча не разобраны (нужно Предмет:число,…)");
				}
				else if (!hashSet.Add(entry.Prefab))
				{
					errors.Add("префаб " + entry.Prefab + " повторяется");
				}
				else
				{
					list.Add(entry);
				}
			}
			return list;
		}

		private static bool TryCosts(string text, List<Cost> into)
		{
			string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Trim().Split(new char[1] { ':' });
				if (array2.Length != 2 || array2[0].Trim() == "" || !int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 1)
				{
					return false;
				}
				into.Add(new Cost
				{
					Item = array2[0].Trim(),
					Amount = result
				});
			}
			return true;
		}

		public static bool CostCoversDrops(Entry e)
		{
			double num = e.Costs.Sum((Cost c) => Worth(c.Item) * (double)c.Amount);
			double num2 = e.Drops.Sum((Cost d) => Worth(d.Item) * (double)d.Amount);
			return num >= num2;
			static double Worth(string item)
			{
				int num3;
				switch (item)
				{
				default:
					num3 = 1;
					goto IL_00c7;
				case "Bronze":
					num3 = 2;
					goto IL_00c7;
				case "Iron":
					num3 = 3;
					goto IL_00c7;
				case "BlackMarble":
					num3 = 1;
					goto IL_00c7;
				case "Grausten":
					num3 = 1;
					goto IL_00c7;
				case "YggdrasilWood":
					num3 = 1;
					goto IL_00c7;
				case "JuteBlue":
					num3 = 3;
					goto IL_00c7;
				case "SurtlingCore":
					num3 = 3;
					goto IL_00c7;
				case "Chain":
					num3 = 3;
					goto IL_00c7;
				case "Copper":
					num3 = 1;
					goto IL_00c7;
				case "CopperScrap":
					num3 = 1;
					goto IL_00c7;
				case "Stone":
					return 0.25;
				case "Wood":
					{
						return 0.25;
					}
					IL_00c7:
					return num3;
				}
			}
		}
	}
}