Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DvergrBuild v0.1.6
plugins/DvergrBuild.dll
Decompiled a week agousing 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; } } } } }