Please disclose if your mod was created primarily 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 BuildPiecesCustomized v1.2.0
BuildPiecesCustomized.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using ServerSync; using TMPro; using UnityEngine; using YamlDotNet.Serialization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Build Pieces Customized")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Build Pieces Customized")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("448a53ac-6a9d-47e7-b934-d6ee2b13e7b2")] [assembly: AssemblyFileVersion("1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace BuildPiecesCustomized { [BepInPlugin("shudnal.BuildPiecesCustomized", "Build Pieces Customized", "1.2.0")] [BepInIncompatibility("aedenthorn.BuildPieceTweaks")] [BepInIncompatibility("TheSxW_EditMaterialProperties")] [BepInIncompatibility("lime.plugins.foreverbuild")] [BepInIncompatibility("bonesbro.val.floorsareroofs")] public class BuildPiecesCustomized : BaseUnityPlugin { internal class MaterialPropertiesConfig { public ConfigEntry<float> maxSupport; public ConfigEntry<float> minSupport; public ConfigEntry<float> verticalLoss; public ConfigEntry<float> horizontalLoss; } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_PiecesWntCache { private static void Postfix() { if (modEnabled.Value) { piecesWntComponent.Clear(); } } } [HarmonyPatch(typeof(Piece), "Awake")] private static class Piece_Awake_PiecesWntCache { private static void Prefix(Piece __instance) { if (modEnabled.Value) { piecesWntComponent[__instance] = ((Component)__instance).GetComponent<WearNTear>(); } } } [HarmonyPatch(typeof(Piece), "OnDestroy")] private static class Piece_OnDestroy_PiecesWntCache { private static void Prefix(Piece __instance) { if (modEnabled.Value) { piecesWntComponent.Remove(__instance); } } } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_PiecesConfigWatcher { [HarmonyPriority(0)] private static void Postfix() { if (modEnabled.Value) { SetupConfigWatcher(); } } } [HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")] private static class WearNTear_GetMaterialProperties_MaterialProperties { private static void Postfix(WearNTear __instance, ref float maxSupport, ref float minSupport, ref float horizontalLoss, ref float verticalLoss) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (modEnabled.Value && materialConfigs.ContainsKey(__instance.m_materialType)) { maxSupport *= materialConfigs[__instance.m_materialType].maxSupport.Value; minSupport *= materialConfigs[__instance.m_materialType].minSupport.Value; horizontalLoss /= materialConfigs[__instance.m_materialType].horizontalLoss.Value; verticalLoss /= materialConfigs[__instance.m_materialType].verticalLoss.Value; } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static EventHandler <>9__39_0; public static EventHandler <>9__39_1; public static EventHandler <>9__39_2; public static EventHandler <>9__39_3; public static EventHandler <>9__39_4; public static EventHandler <>9__39_5; public static EventHandler <>9__39_6; public static EventHandler <>9__39_7; public static EventHandler <>9__39_8; public static EventHandler <>9__39_9; public static EventHandler <>9__39_10; public static ConsoleEvent <>9__42_0; public static Func<GameObject, string> <>9__42_6; public static ConsoleOptionsFetcher <>9__42_1; public static ConsoleEvent <>9__42_2; public static Func<GameObject, string> <>9__42_7; public static ConsoleOptionsFetcher <>9__42_3; public static ConsoleEvent <>9__42_4; public static Func<KeyValuePair<int, List<string>>, IEnumerable<global::<>f__AnonymousType0<string, int>>> <>9__44_0; public static Func<global::<>f__AnonymousType0<string, int>, string> <>9__44_1; public static Func<global::<>f__AnonymousType0<string, int>, int> <>9__44_2; internal void <ConfigInit>b__39_0(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_1(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_2(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_3(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_4(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_5(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_6(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_7(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_8(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_9(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <ConfigInit>b__39_10(object s, EventArgs e) { PiecePatches.UpdatePiecesProperties(); } internal void <InitCommands>b__42_0(ConsoleEventArgs args) { bool flag = args.Length >= 2; string value = (flag ? args.FullLine.Substring(args[0].Length + 1) : ""); foreach (GameObject buildPiece in CustomPieceData.GetBuildPieces()) { CustomPieceData byPieceName = CustomPieceData.GetByPieceName(((Object)buildPiece).name); if (byPieceName != null && (!flag || byPieceName.prefabName.IndexOf(value) != -1 || Regex.IsMatch(byPieceName.prefabName, <InitCommands>g__WildCardToRegular|42_5(value)))) { byPieceName.SaveToDirectory(configDirectory.FullName); Terminal context = args.Context; if (context != null) { context.AddString("Saved " + byPieceName.prefabName + " file to config directory"); } } } } internal List<string> <InitCommands>b__42_1() { return (from piece in CustomPieceData.GetBuildPieces() select ((Object)piece).name).ToList(); } internal string <InitCommands>b__42_6(GameObject piece) { return ((Object)piece).name; } internal void <InitCommands>b__42_2(ConsoleEventArgs args) { if (args.Length < 2) { return; } string text = args.FullLine.Substring(args[0].Length + 1); CustomPieceData byPieceName = CustomPieceData.GetByPieceName(text); if (byPieceName == null) { Terminal context = args.Context; if (context != null) { context.AddString("Piece with name " + text + " was not found"); } return; } byPieceName.SaveToDirectory(configDirectory.FullName); Terminal context2 = args.Context; if (context2 != null) { context2.AddString("Saved " + text + " file to config directory"); } } internal List<string> <InitCommands>b__42_3() { return (from piece in CustomPieceData.GetBuildPieces() select ((Object)piece).name).ToList(); } internal string <InitCommands>b__42_7(GameObject piece) { return ((Object)piece).name; } internal void <InitCommands>b__42_4(ConsoleEventArgs args) { DocGen.GenerateDocumentationFile(); } internal IEnumerable<global::<>f__AnonymousType0<string, int>> <ReadConfigs>b__44_0(KeyValuePair<int, List<string>> kv) { <>c__DisplayClass44_0 CS$<>8__locals0 = new <>c__DisplayClass44_0 { kv = kv }; return CS$<>8__locals0.kv.Value.Select((string v) => new { Key = v, Value = CS$<>8__locals0.kv.Key }); } internal string <ReadConfigs>b__44_1(global::<>f__AnonymousType0<string, int> x) { return x.Key.ToLower(); } internal int <ReadConfigs>b__44_2(global::<>f__AnonymousType0<string, int> x) { return x.Value; } } [CompilerGenerated] private sealed class <>c__DisplayClass44_0 { public KeyValuePair<int, List<string>> kv; internal global::<>f__AnonymousType0<string, int> <ReadConfigs>b__3(string v) { return new { Key = v, Value = kv.Key }; } } public const string pluginID = "shudnal.BuildPiecesCustomized"; public const string pluginName = "Build Pieces Customized"; public const string pluginVersion = "1.2.0"; private readonly Harmony harmony = new Harmony("shudnal.BuildPiecesCustomized"); internal static readonly ConfigSync configSync = new ConfigSync("shudnal.BuildPiecesCustomized") { DisplayName = "Build Pieces Customized", CurrentVersion = "1.2.0", MinimumRequiredVersion = "1.2.0" }; internal static ConfigEntry<bool> modEnabled; internal static ConfigEntry<bool> configLocked; internal static ConfigEntry<bool> loggingEnabled; internal static ConfigEntry<bool> saveAsYAML; internal static ConfigEntry<string> toolsToPatchPieces; internal static ConfigEntry<string> prefabListClipEverything; internal static ConfigEntry<string> prefabListAllowedInDungeons; internal static ConfigEntry<string> prefabListRepairPiece; internal static ConfigEntry<string> prefabListCanBeRemoved; internal static ConfigEntry<string> prefabListIsRoof; internal static ConfigEntry<string> prefabListIsLeaky; internal static ConfigEntry<string> prefabListDisabled; internal static ConfigEntry<string> prefabListAshDamageImmune; internal static ConfigEntry<string> prefabListNoRoofWear; internal static ConfigEntry<string> prefabListNoSupportWear; internal static readonly Dictionary<MaterialType, MaterialPropertiesConfig> materialConfigs = new Dictionary<MaterialType, MaterialPropertiesConfig>(); internal static BuildPiecesCustomized instance; internal static readonly CustomSyncedValue<Dictionary<string, string>> configsJSON = new CustomSyncedValue<Dictionary<string, string>>(configSync, "JSON configs", new Dictionary<string, string>()); internal static readonly CustomSyncedValue<Dictionary<string, int>> pieceCategories = new CustomSyncedValue<Dictionary<string, int>>(configSync, "Pieces categories", new Dictionary<string, int>()); internal static readonly Dictionary<string, CustomPieceData> pieceData = new Dictionary<string, CustomPieceData>(); internal static readonly Dictionary<string, CraftingStation> craftingStations = new Dictionary<string, CraftingStation>(); internal static readonly Dictionary<string, CustomPieceData> defaultPieceData = new Dictionary<string, CustomPieceData>(); internal static DirectoryInfo pluginDirectory; internal static DirectoryInfo configDirectory; private static FileSystemWatcher fileSystemWatcherPlugin; private static FileSystemWatcher fileSystemWatcherConfig; internal static readonly IDeserializer YamlDeserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build(); internal static readonly ISerializer YamlSerializer = new SerializerBuilder().Build(); internal static readonly Dictionary<Piece, WearNTear> piecesWntComponent = new Dictionary<Piece, WearNTear>(); private void Awake() { harmony.PatchAll(); instance = this; pluginDirectory = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent; configDirectory = new DirectoryInfo(Path.Combine(Paths.ConfigPath, "shudnal.BuildPiecesCustomized")); ConfigInit(); configSync.AddLockingConfigEntry<bool>(configLocked); configsJSON.ValueChanged += LoadConfigs; pieceCategories.ValueChanged += PiecePatches.UpdatePiecesProperties; Game.isModded = true; } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } instance = null; } public static void LogInfo(object data) { if (loggingEnabled.Value) { ((BaseUnityPlugin)instance).Logger.LogInfo(data); } } public static void LogWarning(object data) { ((BaseUnityPlugin)instance).Logger.LogWarning(data); } private ConfigDescription GetDescriptionSeparatedStrings(string description) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown return Chainloader.PluginInfos.ContainsKey("_shudnal.ConfigurationManager") ? new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()) : new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { new CustomConfigs.ConfigurationManagerAttributes { CustomDrawer = CustomConfigs.DrawSeparatedStrings(",") } }); } public void ConfigInit() { //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) config("General", "NexusID", 2782, "Nexus mod ID for updates", synchronizedSetting: false); modEnabled = config("General", "Enabled", defaultValue: true, "Enable the mod."); configLocked = config("General", "Lock Configuration", defaultValue: true, "Configuration is locked and can be changed by server admins only."); loggingEnabled = config("General", "Logging enabled", defaultValue: false, "Enable logging. [Not Synced with Server]", synchronizedSetting: false); saveAsYAML = config("General", "Save piece data as YAML", defaultValue: false, "Save piece data in YAML format. [Not Synced with Server]", synchronizedSetting: false); toolsToPatchPieces = config("General", "Tools list", "Hammer,Hoe,Cultivator", "Comma-separated list of tool prefab name to get build pieces from"); toolsToPatchPieces.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListClipEverything = config("List - Global setting", "Clip everything", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will clip through each other. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListAllowedInDungeons = config("List - Global setting", "Allow in dungeons", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will be allowed to build in dungeons. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListRepairPiece = config("List - Global setting", "Can be repaired", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will be repairable. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListCanBeRemoved = config("List - Global setting", "Can be removed", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will be removeable. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListDisabled = config("List - Global setting", "Disabled pieces", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will be disabled.")); prefabListIsRoof = config("List - Global setting", "Is Roof", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will work as a roof. Set \"AllPieces\" identifier to apply for all pieces.\nLeaky -> Roof transition will be applied immediately. \nRestart the game if you need Roof -> Leaky transition of updated pieces.")); prefabListIsLeaky = config("List - Global setting", "Is Leaky", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will not work as a roof. Set \"AllPieces\" identifier to apply for all pieces.\nRoof -> Leaky transition will be applied immediately. \nRestart the game if you need Leaky -> Roof transition of updated pieces.")); prefabListClipEverything.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListAllowedInDungeons.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListRepairPiece.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListCanBeRemoved.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListDisabled.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListIsRoof.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListIsLeaky.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListAshDamageImmune = config("List - Immune to", "Ash and lava", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will be immune to ash and lava damage. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListNoRoofWear = config("List - Immune to", "Water damage", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will be immune to water damage. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListNoSupportWear = config("List - Immune to", "Structural integrity", "", GetDescriptionSeparatedStrings("Comma-separated list of pieces that will not be needed support. Set \"AllPieces\" identifier to apply for all pieces.")); prefabListAshDamageImmune.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListNoRoofWear.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; prefabListNoSupportWear.SettingChanged += delegate { PiecePatches.UpdatePiecesProperties(); }; foreach (MaterialType value in Enum.GetValues(typeof(MaterialType))) { materialConfigs.Add(value, new MaterialPropertiesConfig { maxSupport = config($"Material - {(object)value}", "Max support multiplier", 1f, "Multiplier of maximum support value material can provide."), minSupport = config($"Material - {(object)value}", "Min support multiplier", 1f, "Multiplier of minimum support value material can provide."), verticalLoss = config($"Material - {(object)value}", "Vertical stability multiplier", 1f, "Multiplier of vertical support value. Increase to be able to build higher."), horizontalLoss = config($"Material - {(object)value}", "Horizontal stability multiplier", 1f, "Multiplier of horizontal support value. Increase to be able to build longer hanging beams.") }); } InitCommands(); } private ConfigEntry<T> config<T>(string group, string name, T defaultValue, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, defaultValue, description); SyncedConfigEntry<T> syncedConfigEntry = configSync.AddConfigEntry<T>(val); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val; } private ConfigEntry<T> config<T>(string group, string name, T defaultValue, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } public static void InitCommands() { //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_0039: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown string text = "[Prefab partial name or wildcard *] - save data of ALL pieces into JSON files to config directory " + configDirectory.Name; object obj = <>c.<>9__42_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { bool flag = args.Length >= 2; string value2 = (flag ? args.FullLine.Substring(args[0].Length + 1) : ""); foreach (GameObject buildPiece in CustomPieceData.GetBuildPieces()) { CustomPieceData byPieceName2 = CustomPieceData.GetByPieceName(((Object)buildPiece).name); if (byPieceName2 != null && (!flag || byPieceName2.prefabName.IndexOf(value2) != -1 || Regex.IsMatch(byPieceName2.prefabName, WildCardToRegular(value2)))) { byPieceName2.SaveToDirectory(configDirectory.FullName); Terminal context3 = args.Context; if (context3 != null) { context3.AddString("Saved " + byPieceName2.prefabName + " file to config directory"); } } } }; <>c.<>9__42_0 = val; obj = (object)val; } object obj2 = <>c.<>9__42_1; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => (from piece in CustomPieceData.GetBuildPieces() select ((Object)piece).name).ToList(); <>c.<>9__42_1 = val2; obj2 = (object)val2; } new ConsoleCommand("bpcsaveall", text, (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); string text2 = "[Prefab name] - save piece data into JSON file to config directory " + configDirectory.Name; object obj3 = <>c.<>9__42_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { if (args.Length >= 2) { string text3 = args.FullLine.Substring(args[0].Length + 1); CustomPieceData byPieceName = CustomPieceData.GetByPieceName(text3); if (byPieceName == null) { Terminal context = args.Context; if (context != null) { context.AddString("Piece with name " + text3 + " was not found"); } } else { byPieceName.SaveToDirectory(configDirectory.FullName); Terminal context2 = args.Context; if (context2 != null) { context2.AddString("Saved " + text3 + " file to config directory"); } } } }; <>c.<>9__42_2 = val3; obj3 = (object)val3; } object obj4 = <>c.<>9__42_3; if (obj4 == null) { ConsoleOptionsFetcher val4 = () => (from piece in CustomPieceData.GetBuildPieces() select ((Object)piece).name).ToList(); <>c.<>9__42_3 = val4; obj4 = (object)val4; } new ConsoleCommand("bpcsave", text2, (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)obj4, false, false, false); object obj5 = <>c.<>9__42_4; if (obj5 == null) { ConsoleEvent val5 = delegate { DocGen.GenerateDocumentationFile(); }; <>c.<>9__42_4 = val5; obj5 = (object)val5; } new ConsoleCommand("bpcdocs", "Save documentation file Pieces and properties.md to config directory", (ConsoleEvent)obj5, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); static string WildCardToRegular(string value) { return "^" + Regex.Escape(value).Replace("\\*", ".*") + "$"; } } public static void SetupConfigWatcher() { if (fileSystemWatcherPlugin == null) { fileSystemWatcherPlugin = new FileSystemWatcher(pluginDirectory.FullName, "*.*"); fileSystemWatcherPlugin.Changed += ReadConfigs; fileSystemWatcherPlugin.Created += ReadConfigs; fileSystemWatcherPlugin.Renamed += ReadConfigs; fileSystemWatcherPlugin.Deleted += ReadConfigs; fileSystemWatcherPlugin.IncludeSubdirectories = true; fileSystemWatcherPlugin.SynchronizingObject = ThreadingHelper.SynchronizingObject; } fileSystemWatcherPlugin.EnableRaisingEvents = modEnabled.Value; if (fileSystemWatcherConfig == null && configDirectory.Exists) { fileSystemWatcherConfig = new FileSystemWatcher(configDirectory.FullName, "*.*"); fileSystemWatcherConfig.Changed += ReadConfigs; fileSystemWatcherConfig.Created += ReadConfigs; fileSystemWatcherConfig.Renamed += ReadConfigs; fileSystemWatcherConfig.Deleted += ReadConfigs; fileSystemWatcherConfig.IncludeSubdirectories = true; fileSystemWatcherConfig.SynchronizingObject = ThreadingHelper.SynchronizingObject; } if (fileSystemWatcherConfig != null) { fileSystemWatcherConfig.EnableRaisingEvents = modEnabled.Value; } ReadConfigs(null, null); } private static void ReadConfigs(object sender, FileSystemEventArgs eargs) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); List<FileInfo> list = new List<FileInfo>(); if (pluginDirectory.Exists) { list.AddRange(pluginDirectory.GetFiles("*.json", SearchOption.AllDirectories)); list.AddRange(pluginDirectory.GetFiles("*.yaml", SearchOption.AllDirectories)); list.AddRange(pluginDirectory.GetFiles("*.yml", SearchOption.AllDirectories)); } if (configDirectory.Exists) { list.AddRange(configDirectory.GetFiles("*.json", SearchOption.AllDirectories)); list.AddRange(configDirectory.GetFiles("*.yaml", SearchOption.AllDirectories)); list.AddRange(configDirectory.GetFiles("*.yml", SearchOption.AllDirectories)); } foreach (FileInfo item in list) { if (item.Name == "manifest.json") { continue; } LogInfo("Found " + item.FullName); try { using FileStream fileStream = new FileStream(item.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); using StreamReader streamReader = new StreamReader(fileStream); string text = streamReader.ReadToEnd(); streamReader.Close(); fileStream.Dispose(); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item.Name); if (fileNameWithoutExtension == "Piece categories") { Dictionary<int, List<string>> source = ((item.Extension != ".json") ? YamlDeserializer.Deserialize<Dictionary<int, List<string>>>(text) : JsonConvert.DeserializeObject<Dictionary<int, List<string>>>(text)); pieceCategories.AssignLocalValue(source.SelectMany((KeyValuePair<int, List<string>> kv) => kv.Value.Select((string v) => new { Key = v, Value = kv.Key })).ToDictionary(x => x.Key.ToLower(), x => x.Value)); } else { if (item.Extension != ".json") { text = JsonConvert.SerializeObject((object)YamlDeserializer.Deserialize<CustomPieceData>(text)); } dictionary.Add(fileNameWithoutExtension, text); } } catch (Exception ex) { LogWarning("Error reading file (" + item.FullName + ")! Error: " + ex.Message); } } configsJSON.AssignLocalValue(dictionary); } private static void LoadConfigs() { pieceData.Clear(); foreach (KeyValuePair<string, string> item in configsJSON.Value) { try { pieceData.Add(item.Key, JsonConvert.DeserializeObject<CustomPieceData>(item.Value)); } catch (Exception ex) { LogWarning("Error parsing item (" + item.Key + ")! Error: " + ex.Message); } } PiecePatches.UpdatePiecesProperties(); } internal static WearNTear GetWearNTearComponent(Piece piece) { if (piecesWntComponent.TryGetValue(piece, out var value)) { return value; } WearNTear component = ((Component)piece).GetComponent<WearNTear>(); piecesWntComponent[piece] = component; return component; } [CompilerGenerated] internal static string <InitCommands>g__WildCardToRegular|42_5(string value) { return "^" + Regex.Escape(value).Replace("\\*", ".*") + "$"; } } internal class CustomConfigs { internal class ConfigurationManagerAttributes { [UsedImplicitly] public Action<ConfigEntryBase>? CustomDrawer; } internal static object? configManager; internal static Type? configManagerStyles; internal static GUIStyle GetStyle(GUIStyle other) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown if (configManagerStyles == null) { return other; } FieldInfo fieldInfo = AccessTools.Field(configManagerStyles, "fontSize"); if (fieldInfo == null) { return other; } return new GUIStyle(other) { fontSize = (int)fieldInfo.GetValue(configManagerStyles) }; } internal static void Awake() { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager"); Type type = assembly?.GetType("ConfigurationManager.ConfigurationManager"); configManager = ((type == null) ? null : Chainloader.ManagerObject.GetComponent(type)); configManagerStyles = assembly?.GetType("ConfigurationManager.ConfigurationManagerStyles"); } internal static Action<ConfigEntryBase> DrawSeparatedStrings(string splitString) { string splitString2 = splitString; return delegate(ConfigEntryBase cfg) { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select((object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : null).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault(); bool flag = false; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); List<string> list = new List<string>(); List<string> list2 = ((string)cfg.BoxedValue).Split(new string[1] { splitString2 }, StringSplitOptions.None).ToList(); for (int i = 0; i < list2.Count; i++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = list2[i]; string text2 = GUILayout.TextField(text, GetStyle(GUI.skin.textArea), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (text2 != text && !valueOrDefault) { flag = true; } if (GUILayout.Button("x", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; } else { list.Add(text2); } if (GUILayout.Button("+", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; list.Add(""); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = string.Join(splitString2, list); } }; } internal static Action<ConfigEntryBase> DrawOrderedFixedStrings(string splitString) { string splitString2 = splitString; return delegate(ConfigEntryBase cfg) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select((object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : null).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault(); bool flag = false; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); string[] array = ((string)cfg.BoxedValue).Split(new string[1] { splitString2 }, StringSplitOptions.None).ToArray(); for (int i = 0; i < array.Length; i++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = array[i]; GUILayout.Label(text, GetStyle(GUI.skin.textArea), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button("ʌ", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault && (flag = i > 0)) { ref string reference = ref array[i]; ref string reference2 = ref array[i - 1]; string text2 = array[i - 1]; string text3 = array[i]; reference = text2; reference2 = text3; } if (GUILayout.Button("v", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault && (flag = i < array.Length - 1)) { ref string reference = ref array[i]; ref string reference3 = ref array[i + 1]; string text3 = array[i + 1]; string text2 = array[i]; reference = text3; reference3 = text2; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = string.Join(splitString2, array); } }; } } [Serializable] internal class CustomPieceData { public string? prefabName; public string? name; public string? description; public bool? enabled; public PieceCategory? category; public ComfortGroup? comfortGroup; public int? comfort; public bool? groundOnly; public bool? cultivatedGroundOnly; public bool? waterPiece; public bool? clipGround; public bool? clipEverything; public bool? noInWater; public bool? notOnWood; public bool? notOnTiltingSurface; public bool? inCeilingOnly; public bool? notOnFloor; public bool? noClipping; public bool? onlyInTeleportArea; public bool? allowedInDungeons; public float? spaceRequirement; public bool? repairPiece; public bool? canBeRemoved; public bool? allowRotatedOverlap; public bool? vegetationGroundOnly; public float? blockRadius; public int? extraPlacementDistance; public string? station; public Biome? onlyInBiome; public bool? targetNonPlayerBuilt; public bool? primaryTarget; public bool? randomTarget; public float? health; public bool? noRoofWear; public bool? noSupportWear; public MaterialType? materialType; public bool? supports; public float? hitNoise; public float? destroyNoise; public bool? autoCreateFragments; public List<string>? damageModifiers; public bool? ashDamageImmune; public bool? ashDamageResist; public bool? burnable; public int? minToolTier; public bool? triggerPrivateArea; public List<string>? resources; internal void PatchPiece(Piece piece) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Expected O, but got Unknown //IL_06d3: Unknown result type (might be due to invalid IL or missing references) //IL_06d8: Unknown result type (might be due to invalid IL or missing references) //IL_0770: Unknown result type (might be due to invalid IL or missing references) //IL_0772: Unknown result type (might be due to invalid IL or missing references) //IL_0774: Unknown result type (might be due to invalid IL or missing references) //IL_0776: Unknown result type (might be due to invalid IL or missing references) //IL_0778: Unknown result type (might be due to invalid IL or missing references) //IL_077c: Invalid comparison between Unknown and I4 //IL_07bb: Unknown result type (might be due to invalid IL or missing references) //IL_07c2: Invalid comparison between Unknown and I4 //IL_077e: Unknown result type (might be due to invalid IL or missing references) //IL_0781: Invalid comparison between Unknown and I4 //IL_07da: Unknown result type (might be due to invalid IL or missing references) //IL_07e1: Invalid comparison between Unknown and I4 //IL_07c4: Unknown result type (might be due to invalid IL or missing references) //IL_07c8: Invalid comparison between Unknown and I4 //IL_07a8: Unknown result type (might be due to invalid IL or missing references) //IL_07ac: Invalid comparison between Unknown and I4 //IL_0783: Unknown result type (might be due to invalid IL or missing references) //IL_0786: Unknown result type (might be due to invalid IL or missing references) //IL_079c: Expected I4, but got Unknown //IL_084a: Unknown result type (might be due to invalid IL or missing references) //IL_084c: Unknown result type (might be due to invalid IL or missing references) //IL_0834: Unknown result type (might be due to invalid IL or missing references) //IL_0836: Unknown result type (might be due to invalid IL or missing references) //IL_081e: Unknown result type (might be due to invalid IL or missing references) //IL_0820: Unknown result type (might be due to invalid IL or missing references) //IL_07f2: Unknown result type (might be due to invalid IL or missing references) //IL_07f4: Unknown result type (might be due to invalid IL or missing references) //IL_07fd: Unknown result type (might be due to invalid IL or missing references) //IL_07ff: Unknown result type (might be due to invalid IL or missing references) //IL_0808: Unknown result type (might be due to invalid IL or missing references) //IL_080a: Unknown result type (might be due to invalid IL or missing references) //IL_07e5: Unknown result type (might be due to invalid IL or missing references) //IL_07ec: Invalid comparison between Unknown and I4 //IL_07cc: Unknown result type (might be due to invalid IL or missing references) //IL_07d3: Invalid comparison between Unknown and I4 //IL_07b0: Unknown result type (might be due to invalid IL or missing references) //IL_07b4: Invalid comparison between Unknown and I4 //IL_079e: Unknown result type (might be due to invalid IL or missing references) //IL_07a1: Invalid comparison between Unknown and I4 //IL_0855: Unknown result type (might be due to invalid IL or missing references) //IL_0857: Unknown result type (might be due to invalid IL or missing references) //IL_083f: Unknown result type (might be due to invalid IL or missing references) //IL_0841: Unknown result type (might be due to invalid IL or missing references) //IL_0829: Unknown result type (might be due to invalid IL or missing references) //IL_082b: Unknown result type (might be due to invalid IL or missing references) //IL_0813: Unknown result type (might be due to invalid IL or missing references) //IL_0815: Unknown result type (might be due to invalid IL or missing references) if (enabled.HasValue) { piece.m_enabled = enabled.Value; } if (name != null) { piece.m_name = name; } if (description != null) { piece.m_description = description; } if (category.HasValue) { piece.m_category = category.Value; } if (comfort.HasValue) { piece.m_comfort = comfort.Value; } if (comfortGroup.HasValue) { piece.m_comfortGroup = comfortGroup.Value; } if (groundOnly.HasValue) { piece.m_groundOnly = groundOnly.Value; } if (cultivatedGroundOnly.HasValue) { piece.m_cultivatedGroundOnly = cultivatedGroundOnly.Value; } if (waterPiece.HasValue) { piece.m_waterPiece = waterPiece.Value; } if (clipGround.HasValue) { piece.m_clipGround = clipGround.Value; } if (clipEverything.HasValue) { piece.m_clipEverything = clipEverything.Value; } if (noInWater.HasValue) { piece.m_noInWater = noInWater.Value; } if (notOnWood.HasValue) { piece.m_notOnWood = notOnWood.Value; } if (notOnTiltingSurface.HasValue) { piece.m_notOnTiltingSurface = notOnTiltingSurface.Value; } if (inCeilingOnly.HasValue) { piece.m_inCeilingOnly = inCeilingOnly.Value; } if (notOnFloor.HasValue) { piece.m_notOnFloor = notOnFloor.Value; } if (noClipping.HasValue) { piece.m_noClipping = noClipping.Value; } if (onlyInTeleportArea.HasValue) { piece.m_onlyInTeleportArea = onlyInTeleportArea.Value; } if (allowedInDungeons.HasValue) { piece.m_allowedInDungeons = allowedInDungeons.Value; } if (spaceRequirement.HasValue) { piece.m_spaceRequirement = spaceRequirement.Value; } if (repairPiece.HasValue) { piece.m_repairPiece = repairPiece.Value; } if (canBeRemoved.HasValue) { piece.m_canBeRemoved = canBeRemoved.Value; } if (allowRotatedOverlap.HasValue) { piece.m_allowRotatedOverlap = allowRotatedOverlap.Value; } if (vegetationGroundOnly.HasValue) { piece.m_vegetationGroundOnly = vegetationGroundOnly.Value; } if (blockRadius.HasValue) { piece.m_blockRadius = blockRadius.Value; } if (extraPlacementDistance.HasValue) { piece.m_extraPlacementDistance = extraPlacementDistance.Value; } if (station != null) { piece.m_craftingStation = GeneralExtensions.GetValueSafe<string, CraftingStation>(BuildPiecesCustomized.craftingStations, station); } if (onlyInBiome.HasValue) { piece.m_onlyInBiome = onlyInBiome.Value; } if (targetNonPlayerBuilt.HasValue) { piece.m_targetNonPlayerBuilt = targetNonPlayerBuilt.Value; } if (primaryTarget.HasValue) { ((StaticTarget)piece).m_primaryTarget = primaryTarget.Value; } if (randomTarget.HasValue) { ((StaticTarget)piece).m_randomTarget = randomTarget.Value; } if (resources != null) { List<Requirement> list = new List<Requirement>(); foreach (string resource in resources) { string[] array = resource.Split(new char[1] { ':' }); if (array.Length >= 1) { ObjectDB instance = ObjectDB.instance; object obj; if (instance == null) { obj = null; } else { GameObject itemPrefab = instance.GetItemPrefab(array[0]); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } ItemDrop val = (ItemDrop)obj; if (!((Object)(object)val == (Object)null)) { list.Add(new Requirement { m_resItem = val, m_amount = ((array.Length <= 1) ? 1 : int.Parse(array[1])), m_recover = (array.Length < 3 || bool.Parse(array[2])) }); } } } piece.m_resources = list.ToArray(); } WearNTear wearNTearComponent = BuildPiecesCustomized.GetWearNTearComponent(piece); if (wearNTearComponent == null) { return; } if (health.HasValue) { wearNTearComponent.m_health = health.Value; } if (noRoofWear.HasValue) { wearNTearComponent.m_noRoofWear = noRoofWear.Value; } if (noSupportWear.HasValue) { wearNTearComponent.m_noSupportWear = noSupportWear.Value; } if (supports.HasValue) { wearNTearComponent.m_supports = supports.Value; } if (hitNoise.HasValue) { wearNTearComponent.m_hitNoise = hitNoise.Value; } if (destroyNoise.HasValue) { wearNTearComponent.m_destroyNoise = destroyNoise.Value; } if (autoCreateFragments.HasValue) { wearNTearComponent.m_autoCreateFragments = autoCreateFragments.Value; } if (ashDamageImmune.HasValue) { wearNTearComponent.m_ashDamageImmune = ashDamageImmune.Value; } if (ashDamageResist.HasValue) { wearNTearComponent.m_ashDamageResist = ashDamageResist.Value; } if (burnable.HasValue) { wearNTearComponent.m_burnable = burnable.Value; } if (minToolTier.HasValue) { wearNTearComponent.m_minToolTier = minToolTier.Value; } if (triggerPrivateArea.HasValue) { wearNTearComponent.m_triggerPrivateArea = triggerPrivateArea.Value; } if (materialType.HasValue) { wearNTearComponent.m_materialType = materialType.Value; } if (damageModifiers == null) { return; } foreach (string damageModifier in damageModifiers) { string[] array2 = damageModifier.Split(new char[1] { ':' }); if (array2.Length != 2 || !Enum.TryParse<DamageType>(array2[0], out DamageType result) || !Enum.TryParse<DamageModifier>(array2[1], out DamageModifier result2)) { continue; } ref DamageModifiers damages = ref wearNTearComponent.m_damages; DamageType val2 = result; DamageType val3 = val2; if ((int)val3 <= 32) { if ((int)val3 <= 8) { switch (val3 - 1) { case 0: damages.m_blunt = result2; continue; case 1: damages.m_slash = result2; continue; case 3: damages.m_pierce = result2; continue; case 2: continue; } if ((int)val3 == 8) { damages.m_chop = result2; } } else if ((int)val3 != 16) { if ((int)val3 == 32) { damages.m_fire = result2; } } else { damages.m_pickaxe = result2; } } else if ((int)val3 <= 128) { if ((int)val3 != 64) { if ((int)val3 == 128) { damages.m_lightning = result2; } } else { damages.m_frost = result2; } } else if ((int)val3 != 256) { if ((int)val3 == 512) { damages.m_spirit = result2; } } else { damages.m_poison = result2; } } } internal void SaveToDirectory(string directory) { Directory.CreateDirectory(directory); string path = Path.Combine(directory, prefabName + "." + (BuildPiecesCustomized.saveAsYAML.Value ? "yaml" : "json")); File.WriteAllText(path, BuildPiecesCustomized.saveAsYAML.Value ? BuildPiecesCustomized.YamlSerializer.Serialize((object)this) : JsonConvert.SerializeObject((object)this, (Formatting)1)); } internal CustomPieceData() { } internal CustomPieceData(Piece piece) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Unknown result type (might be due to invalid IL or missing references) //IL_0614: Unknown result type (might be due to invalid IL or missing references) prefabName = ((Object)((Component)piece).gameObject).name; enabled = piece.m_enabled; name = piece.m_name; description = piece.m_description; category = piece.m_category; comfortGroup = piece.m_comfortGroup; comfort = piece.m_comfort; groundOnly = piece.m_groundOnly; cultivatedGroundOnly = piece.m_cultivatedGroundOnly; waterPiece = piece.m_waterPiece; clipGround = piece.m_clipGround; clipEverything = piece.m_clipEverything; noInWater = piece.m_noInWater; notOnWood = piece.m_notOnWood; notOnTiltingSurface = piece.m_notOnTiltingSurface; inCeilingOnly = piece.m_inCeilingOnly; notOnFloor = piece.m_notOnFloor; noClipping = piece.m_noClipping; onlyInTeleportArea = piece.m_onlyInTeleportArea; allowedInDungeons = piece.m_allowedInDungeons; spaceRequirement = piece.m_spaceRequirement; repairPiece = piece.m_repairPiece; canBeRemoved = piece.m_canBeRemoved; station = (Object.op_Implicit((Object)(object)piece.m_craftingStation) ? piece.m_craftingStation.m_name : ""); onlyInBiome = piece.m_onlyInBiome; allowRotatedOverlap = piece.m_allowRotatedOverlap; vegetationGroundOnly = piece.m_vegetationGroundOnly; blockRadius = piece.m_blockRadius; extraPlacementDistance = piece.m_extraPlacementDistance; targetNonPlayerBuilt = piece.m_targetNonPlayerBuilt; primaryTarget = ((StaticTarget)piece).m_primaryTarget; randomTarget = ((StaticTarget)piece).m_randomTarget; resources = new List<string>(); resources.AddRange(piece.m_resources.Select((Requirement req) => $"{((Object)req.m_resItem).name}:{req.m_amount}:{req.m_recover}")); WearNTear wearNTearComponent = BuildPiecesCustomized.GetWearNTearComponent(piece); if ((Object)(object)wearNTearComponent != (Object)null) { health = wearNTearComponent.m_health; noRoofWear = wearNTearComponent.m_noRoofWear; noSupportWear = wearNTearComponent.m_noSupportWear; materialType = wearNTearComponent.m_materialType; supports = wearNTearComponent.m_supports; hitNoise = wearNTearComponent.m_hitNoise; destroyNoise = wearNTearComponent.m_destroyNoise; autoCreateFragments = wearNTearComponent.m_autoCreateFragments; ashDamageImmune = wearNTearComponent.m_ashDamageImmune; ashDamageResist = wearNTearComponent.m_ashDamageResist; burnable = wearNTearComponent.m_burnable; minToolTier = wearNTearComponent.m_minToolTier; triggerPrivateArea = wearNTearComponent.m_triggerPrivateArea; damageModifiers = new List<string> { Enum.GetName(typeof(DamageType), (object)(DamageType)1) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_blunt), Enum.GetName(typeof(DamageType), (object)(DamageType)2) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_slash), Enum.GetName(typeof(DamageType), (object)(DamageType)4) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_pierce), Enum.GetName(typeof(DamageType), (object)(DamageType)8) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_chop), Enum.GetName(typeof(DamageType), (object)(DamageType)16) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_pickaxe), Enum.GetName(typeof(DamageType), (object)(DamageType)32) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_fire), Enum.GetName(typeof(DamageType), (object)(DamageType)64) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_frost), Enum.GetName(typeof(DamageType), (object)(DamageType)128) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_lightning), Enum.GetName(typeof(DamageType), (object)(DamageType)256) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_poison), Enum.GetName(typeof(DamageType), (object)(DamageType)512) + ":" + Enum.GetName(typeof(DamageModifier), wearNTearComponent.m_damages.m_spirit) }; } } internal static CustomPieceData? GetByPieceName(string pieceName) { string pieceName2 = pieceName; if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { return null; } GameObject val = ((IEnumerable<GameObject>)GetBuildPieces()).FirstOrDefault((Func<GameObject, bool>)((GameObject buildPiece) => ((Object)buildPiece).name == pieceName2)); if ((Object)(object)val == (Object)null) { return null; } Piece piece = default(Piece); if (!val.TryGetComponent<Piece>(ref piece)) { return null; } return new CustomPieceData(piece); } internal static List<GameObject> GetBuildPieces() { List<GameObject> list = new List<GameObject>(); HashSet<string> hashSet = new HashSet<string>(from c in BuildPiecesCustomized.toolsToPatchPieces.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select c.Trim()); foreach (string item in hashSet) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (!((Object)(object)val == (Object)null)) { list.AddRange(val.m_itemData.m_shared.m_buildPieces.m_pieces); } } return list; } } internal static class DocGen { [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPriority(0)] private static class ObjectDB_Awake_DocGen { private static void Postfix() { if (BuildPiecesCustomized.modEnabled.Value) { GenerateDocumentationFile(); } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyPriority(0)] private static class ObjectDB_CopyOtherDB_DocGen { private static void Postfix() { if (BuildPiecesCustomized.modEnabled.Value) { GenerateDocumentationFile(); } } } [HarmonyPatch(typeof(ZoneSystem), "Start")] [HarmonyPriority(0)] private static class ZoneSystem_Start_DocGen { private static void Postfix() { if (BuildPiecesCustomized.modEnabled.Value) { GenerateDocumentationFile(); } } } private static readonly StringBuilder sb = new StringBuilder(); internal const string filename = "Pieces and properties.md"; internal static void GenerateDocumentationFile() { string text = Path.Combine(BuildPiecesCustomized.configDirectory.FullName, "Pieces and properties.md"); try { Directory.CreateDirectory(BuildPiecesCustomized.configDirectory.FullName); File.WriteAllText(text, GetFileText()); } catch (Exception ex) { BuildPiecesCustomized.LogWarning("Error when writing file (" + text + ")! Error: " + ex.Message); } } private static void LogPieceCategories() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected I4, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) Dictionary<PieceCategory, string> dictionary = new Dictionary<PieceCategory, string>(); PieceTable buildPieces = Player.m_localPlayer.m_buildPieces; PieceTable[] array = Resources.FindObjectsOfTypeAll<PieceTable>(); foreach (PieceTable val in array) { if (!Object.op_Implicit((Object)(object)val)) { continue; } Player.m_localPlayer.m_buildPieces = val; Hud instance = Hud.instance; if (instance != null) { instance.LateUpdate(); } int num = Mathf.Min(val.m_categories.Count, val.m_categoryLabels.Count); for (int j = 0; j < num; j++) { PieceCategory val2 = val.m_categories[j]; if (!dictionary.ContainsKey(val2)) { string text = val.m_categoryLabels[j]; if (!string.IsNullOrWhiteSpace(text) && Localization.instance != null) { text = Localization.instance.Localize(text); } if (string.IsNullOrWhiteSpace(text)) { text = Enum.GetName(typeof(PieceCategory), val2); } if (string.IsNullOrWhiteSpace(text)) { text = ((object)(PieceCategory)(ref val2)).ToString(); } dictionary[val2] = text; } } } Player.m_localPlayer.m_buildPieces = buildPieces; Hud instance2 = Hud.instance; if (instance2 != null) { instance2.LateUpdate(); } foreach (KeyValuePair<PieceCategory, string> item in dictionary.OrderBy((KeyValuePair<PieceCategory, string> p) => (int)p.Key)) { sb.AppendLine($"* {(int)item.Key} - {item.Value}"); } } private static string GetFileText() { sb.Clear(); sb.AppendLine("This documentation generated automatically. It contains all available pieces and enumerations identifiers used to configure pieces."); sb.AppendLine(); sb.AppendLine("# Properties and available values"); sb.AppendLine(); sb.AppendLine("## category"); if ((Object)(object)Player.m_localPlayer != (Object)null) { LogPieceCategories(); } else { EnumToList(typeof(PieceCategory)); } sb.AppendLine(); sb.AppendLine("## comfortGroup"); EnumToList(typeof(ComfortGroup)); sb.AppendLine(); sb.AppendLine("## onlyInBiome"); EnumToList(typeof(Biome)); sb.AppendLine(); sb.AppendLine("## materialType"); EnumToList(typeof(MaterialType)); sb.AppendLine(); sb.AppendLine("## damageModifiers"); sb.AppendLine(); sb.AppendLine("### type"); EnumToList(typeof(DamageType), noID: true); sb.AppendLine(); sb.AppendLine("### modifier"); EnumToList(typeof(DamageModifier), noID: true); if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { sb.AppendLine(); sb.AppendLine("## station"); Dictionary<string, CraftingStation> dictionary = new Dictionary<string, CraftingStation>(); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_craftingStation == (Object)null)) { dictionary[((Object)recipe.m_craftingStation).name] = recipe.m_craftingStation; } } foreach (KeyValuePair<string, CraftingStation> item in dictionary) { sb.AppendLine("* " + item.Key + " - " + Localization.instance.Localize(item.Value.m_name)); } sb.AppendLine(); sb.AppendLine("# Piece prefab names"); sb.AppendLine("Format \"Prefab name - Token - Localized name\""); sb.AppendLine("List given in order as it appears in the game"); Piece val = default(Piece); foreach (ItemDrop allItem in ObjectDB.instance.GetAllItems((ItemType)19, "")) { if ((Object)(object)allItem == (Object)null || (Object)(object)allItem.m_itemData.m_shared.m_buildPieces == (Object)null || allItem.m_itemData.m_shared.m_buildPieces.m_pieces.Count == 0) { continue; } sb.AppendLine(); sb.AppendLine("## " + ((Object)allItem).name + " - " + allItem.m_itemData.m_shared.m_name + " - " + Localization.instance.Localize(allItem.m_itemData.m_shared.m_name)); foreach (GameObject piece in allItem.m_itemData.m_shared.m_buildPieces.m_pieces) { if (piece.TryGetComponent<Piece>(ref val)) { sb.AppendLine("* " + ((Object)val).name + " - " + val.m_name + " - " + Localization.instance.Localize(val.m_name)); } } } } return sb.ToString(); } private static void EnumToList(Type enumType, bool noID = false) { foreach (object value in Enum.GetValues(enumType)) { sb.AppendLine(noID ? $"* {value}" : $"* {(int)value} - {value}"); } } } public static class PiecePatches { [HarmonyPatch(typeof(Piece), "Awake")] private static class Piece_Awake_PatchPiece { private static void Postfix(Piece __instance) { if (BuildPiecesCustomized.modEnabled.Value) { PatchPiece(__instance); } } } [HarmonyPatch(typeof(PieceTable), "IsPieceAvailable")] private static class PieceTable_IsPieceAvailable_PieceDisabled { private static void Postfix(PieceTable __instance, Piece piece, ref bool __result) { if (BuildPiecesCustomized.modEnabled.Value && __result && GlobalPatches.IsPieceForceDisabled(piece)) { __result = false; } } } [HarmonyPatch(typeof(PieceTable), "UpdateAvailable")] private static class PieceTable_UpdateAvailable_PieceDisabled { [HarmonyPriority(800)] private static void Prefix(PieceTable __instance, ref List<GameObject> __state) { if (BuildPiecesCustomized.modEnabled.Value) { __state = __instance.m_pieces.ToList(); int num = __instance.m_pieces.RemoveAll(GlobalPatches.IsPieceForceDisabled); if (num > 0) { BuildPiecesCustomized.LogInfo($"Removed pieces {((Object)__instance).name}: {num}/{__state.Count}"); } else { __state = null; } } } private static void Finalizer(PieceTable __instance, List<GameObject> __state) { if (BuildPiecesCustomized.modEnabled.Value && __state != null) { __instance.m_pieces.Clear(); __instance.m_pieces.AddRange(__state); BuildPiecesCustomized.LogInfo($"Restored pieces {((Object)__instance).name}: {__instance.m_pieces.Count}"); } } } public static class GlobalPatches { public const string allPiecesIdentifier = "AllPieces"; private static readonly string allPiecesListIdentifier = "AllPieces".ToLower(); private static bool clipEverything; private static bool allowedInDungeons; private static bool repairPiece; private static bool canBeRemoved; private static bool isRoof; private static bool isLeaky; private static bool ashDamageImmune; private static bool noRoofWear; private static bool noSupportWear; private static HashSet<string> listClipEverything; private static HashSet<string> listAllowedInDungeons; private static HashSet<string> listRepairPiece; private static HashSet<string> listCanBeRemoved; private static HashSet<string> listIsRoof; private static HashSet<string> listIsLeaky; private static HashSet<string> listAshDamageImmune; private static HashSet<string> listNoRoofWear; private static HashSet<string> listNoSupportWear; private static HashSet<string> listDisabled; private static HashSet<string> ConfigToHashSet(string configString) { return new HashSet<string>((from p in configString.Split(new char[1] { ',' }) select p.Trim().ToLower() into p where !string.IsNullOrWhiteSpace(p) select p).ToList()); } public static void UpdateProperties() { listClipEverything = ConfigToHashSet(BuildPiecesCustomized.prefabListClipEverything.Value); listAllowedInDungeons = ConfigToHashSet(BuildPiecesCustomized.prefabListAllowedInDungeons.Value); listRepairPiece = ConfigToHashSet(BuildPiecesCustomized.prefabListRepairPiece.Value); listCanBeRemoved = ConfigToHashSet(BuildPiecesCustomized.prefabListCanBeRemoved.Value); listIsRoof = ConfigToHashSet(BuildPiecesCustomized.prefabListIsRoof.Value); listIsLeaky = ConfigToHashSet(BuildPiecesCustomized.prefabListIsLeaky.Value); listAshDamageImmune = ConfigToHashSet(BuildPiecesCustomized.prefabListAshDamageImmune.Value); listNoRoofWear = ConfigToHashSet(BuildPiecesCustomized.prefabListNoRoofWear.Value); listNoSupportWear = ConfigToHashSet(BuildPiecesCustomized.prefabListNoSupportWear.Value); listDisabled = ConfigToHashSet(BuildPiecesCustomized.prefabListDisabled.Value); clipEverything = listClipEverything.Contains(allPiecesListIdentifier); allowedInDungeons = listAllowedInDungeons.Contains(allPiecesListIdentifier); repairPiece = listRepairPiece.Contains(allPiecesListIdentifier); canBeRemoved = listCanBeRemoved.Contains(allPiecesListIdentifier); isRoof = listIsRoof.Contains(allPiecesListIdentifier); isLeaky = listIsLeaky.Contains(allPiecesListIdentifier); ashDamageImmune = listAshDamageImmune.Contains(allPiecesListIdentifier); noRoofWear = listNoRoofWear.Contains(allPiecesListIdentifier); noSupportWear = listNoSupportWear.Contains(allPiecesListIdentifier); } public static bool IsPieceForceDisabled(Piece piece) { return !piece.m_enabled && listDisabled.Contains(((Object)piece).name.ToLower()); } public static bool IsPieceForceDisabled(GameObject gameObject) { Piece piece = default(Piece); return gameObject.TryGetComponent<Piece>(ref piece) && IsPieceForceDisabled(piece); } public static void PatchGlobalProperties(Piece piece, string pieceName) { //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) string text = pieceName.ToLower(); if (clipEverything) { piece.m_clipEverything = true; } else if (listClipEverything.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " clip everything"); piece.m_clipEverything = true; } if (allowedInDungeons) { piece.m_allowedInDungeons = true; } else if (listAllowedInDungeons.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " allowed in dungeons"); piece.m_allowedInDungeons = true; } if (repairPiece) { piece.m_repairPiece = true; } else if (listRepairPiece.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " can be repaired"); piece.m_repairPiece = true; } if (canBeRemoved) { piece.m_canBeRemoved = true; } else if (listCanBeRemoved.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " can be removed"); piece.m_canBeRemoved = true; } int value; if (listDisabled.Contains(text)) { piece.m_enabled = false; piece.m_category = (PieceCategory)0; } else if (BuildPiecesCustomized.pieceCategories.Value.TryGetValue(text, out value) && value >= 0) { piece.m_category = (PieceCategory)value; } WearNTear wearNTearComponent = BuildPiecesCustomized.GetWearNTearComponent(piece); if (!((Object)(object)wearNTearComponent != (Object)null)) { return; } if (ashDamageImmune) { wearNTearComponent.m_ashDamageImmune = true; } else if (listAshDamageImmune.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " ash and lava immune"); wearNTearComponent.m_ashDamageImmune = true; } if (noRoofWear) { wearNTearComponent.m_noRoofWear = false; } else if (listNoRoofWear.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " no water damage"); wearNTearComponent.m_noRoofWear = false; } if (noSupportWear) { wearNTearComponent.m_noSupportWear = false; } else if (listNoSupportWear.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " no structural integrity"); wearNTearComponent.m_noSupportWear = false; } if (isRoof) { CollectionExtensions.Do<Collider>(from col in ((Component)((Component)wearNTearComponent).transform.root).GetComponentsInChildren<Collider>(true) where ((Component)col).tag == "leaky" select col, (Action<Collider>)delegate(Collider col) { ((Component)col).tag = "roof"; }); } else if (listIsRoof.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " leaky -> roof"); CollectionExtensions.Do<Collider>(from col in ((Component)((Component)wearNTearComponent).transform.root).GetComponentsInChildren<Collider>(true) where ((Component)col).tag == "leaky" select col, (Action<Collider>)delegate(Collider col) { ((Component)col).tag = "roof"; }); } if (isLeaky) { CollectionExtensions.Do<Collider>(from col in ((Component)((Component)wearNTearComponent).transform.root).GetComponentsInChildren<Collider>(true) where ((Component)col).tag == "roof" select col, (Action<Collider>)delegate(Collider col) { ((Component)col).tag = "leaky"; }); } else if (listIsLeaky.Contains(text)) { BuildPiecesCustomized.LogInfo("Patching " + pieceName + " roof -> leaky"); CollectionExtensions.Do<Collider>(from col in ((Component)((Component)wearNTearComponent).transform.root).GetComponentsInChildren<Collider>(true) where ((Component)col).tag == "roof" select col, (Action<Collider>)delegate(Collider col) { ((Component)col).tag = "leaky"; }); } } } [CompilerGenerated] private sealed class <PatchPieces>d__3 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private List<GameObject>.Enumerator <>s__1; private GameObject <go>5__2; private Piece <piece>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PatchPieces>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>s__1 = default(List<GameObject>.Enumerator); <go>5__2 = null; <piece>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)ObjectDB.instance != (Object)null)); <>1__state = 1; return true; case 1: <>1__state = -1; FillCraftingStations(); <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 2; return true; case 2: <>1__state = -1; <>s__1 = CustomPieceData.GetBuildPieces().GetEnumerator(); try { while (<>s__1.MoveNext()) { <go>5__2 = <>s__1.Current; if ((Object)(object)<go>5__2 != (Object)null && <go>5__2.TryGetComponent<Piece>(ref <piece>5__3)) { PatchPiece(<piece>5__3); } <piece>5__3 = null; <go>5__2 = null; } } finally { ((IDisposable)<>s__1).Dispose(); } <>s__1 = default(List<GameObject>.Enumerator); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static void UpdatePiecesProperties() { GlobalPatches.UpdateProperties(); if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { ((MonoBehaviour)BuildPiecesCustomized.instance).StartCoroutine(PatchPieces()); } List<Piece> s_allPieces = Piece.s_allPieces; if (s_allPieces != null) { CollectionExtensions.Do<Piece>((IEnumerable<Piece>)s_allPieces, (Action<Piece>)delegate(Piece piece) { PatchPiece(piece); }); } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { localPlayer.UpdateAvailablePiecesList(); } } private static void FillCraftingStations() { BuildPiecesCustomized.craftingStations.Clear(); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (!((Object)(object)recipe?.m_craftingStation == (Object)null) && !BuildPiecesCustomized.craftingStations.ContainsKey(((Object)recipe.m_craftingStation).name)) { BuildPiecesCustomized.craftingStations[((Object)recipe.m_craftingStation).name] = recipe.m_craftingStation; BuildPiecesCustomized.craftingStations[recipe.m_craftingStation.m_name] = recipe.m_craftingStation; BuildPiecesCustomized.craftingStations[recipe.m_craftingStation.m_name.Substring(1)] = recipe.m_craftingStation; } } } private static void PatchPiece(Piece piece) { if ((Object)(object)piece == (Object)null || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } string name = Utils.GetPrefabName(((Component)piece).gameObject); if (!BuildPiecesCustomized.defaultPieceData.ContainsKey(name)) { GameObject prefab = ZNetScene.instance.GetPrefab(name); Piece val = (Piece)(((Object)(object)prefab == (Object)null) ? ((object)((IEnumerable<Piece>)Resources.FindObjectsOfTypeAll<Piece>()).FirstOrDefault((Func<Piece, bool>)((Piece p) => ((Object)p).name == name))) : ((object)prefab.GetComponent<Piece>())); if (!Object.op_Implicit((Object)(object)val)) { return; } BuildPiecesCustomized.defaultPieceData[name] = new CustomPieceData(val); } BuildPiecesCustomized.defaultPieceData[name].PatchPiece(piece); if (BuildPiecesCustomized.pieceData.ContainsKey(name)) { BuildPiecesCustomized.LogInfo("Patching " + ((Object)piece).name); BuildPiecesCustomized.pieceData[name].PatchPiece(piece); } GlobalPatches.PatchGlobalProperties(piece, name); if ((Object)(object)piece.m_nview != (Object)null && piece.m_nview.IsValid()) { piece.m_nview.LoadFields(); } } [IteratorStateMachine(typeof(<PatchPieces>d__3))] private static IEnumerator PatchPieces() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PatchPieces>d__3(0); } } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<ConfigSync> configSyncs; private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>(); private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>(); private static bool isServer; private static bool lockExempt; private OwnConfigEntryBase? lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>(); private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; public event Action<bool>? SourceOfTruthChanged; private event Action? lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet<ConfigSync>(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry) { ConfigEntry<T> configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv) { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value)) { value = new SortedDictionary<int, byte[]>(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteArray()); if (value.Count < num2) { return false; } configValueCache.Remove(text2); package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray()); b = package.ReadByte(); } ProcessingServerUpdate = true; if ((b & 4u) != 0) { byte[] buffer = package.ReadByteArray(); MemoryStream stream = new MemoryStream(buffer); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress)) { deflateStream.CopyTo(memoryStream); } package = new ZPackage(memoryStream.ToArray()); b = package.ReadByte(); } if ((b & 1) == 0) { resetConfigsFromServer(); } ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package); ConfigFile val2 = null; bool saveOnConfigSet = false; foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues) { if (!isServer && configValue.Key.LocalBaseValue == null) { configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue; } if (val2 == null) { val2 = configValue.Key.BaseConfig.ConfigFile; saveOnConfigSet = val2.SaveOnConfigSet; val2.SaveOnConfigSet = false; } configValue.Key.BaseConfig.BoxedValue = configValue.Value; } if (val2 != null) { val2.SaveOnConfigSet = saveOnConfigSet; val2.Save(); } foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues) { if (!isServer) { CustomSyncedValueBase key2 = customValue.Key; if (key2.LocalBaseValue == null) { key2.LocalBaseValue = customValue.Key.BoxedValue; } } customValue.Key.BoxedValue = customValue.Value; } Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name)); if (!isServer) { serverLockedSettingChanged(); } return true; } finally { ProcessingServerUpdate = false; } } private ParsedConfigs ReadConfigsFromPackage(