Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RepairEnemyStuctures v1.0.1
RepairEnemyStructures.dll
Decompiled 10 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSync; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RepairEnemyStructures")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("RepairEnemyStructures")] [assembly: AssemblyTitle("RepairEnemyStructures")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RepairEnemyStructures { public enum Station { None, Workbench, Cauldron, Forge, ArtisanTable, Stonecutter, MageTable, BlackForge } internal class RepairRequiresStation : MonoBehaviour { public string StationName; } [BepInPlugin("com.dreich.repairenemystructures", "Repair Enemy Structures", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class RepairEnemyStructuresPlugin : BaseUnityPlugin { public const string PluginGuid = "com.dreich.repairenemystructures"; public const string PluginName = "Repair Enemy Structures"; public const string PluginVersion = "1.0.1"; internal const string ConfigSyncGuid = "_shudnal.ConditionalConfigSync"; internal static bool ConfigSyncAvailable; private static ConfigEntry<bool> lockConfigurationSetting; internal static ManualLogSource Log; internal static ConfigEntry<bool> RepairDvergr; internal static ConfigEntry<bool> RepairFuling; internal static ConfigEntry<string> DvergrPrefabKeywords; internal static ConfigEntry<string> FulingPrefabKeywords; internal static ConfigEntry<Station> FulingStation; internal static ConfigEntry<Station> DvergrDefaultStation; internal static ConfigEntry<string> DvergrGroupAKeywords; internal static ConfigEntry<Station> DvergrGroupAStation; internal static ConfigEntry<string> DvergrGroupBKeywords; internal static ConfigEntry<Station> DvergrGroupBStation; internal static ConfigEntry<string> StationOverrides; internal static ConfigEntry<string> RepairEffectPrefab; internal static ConfigEntry<bool> LogPatched; internal static ConfigEntry<bool> LogUnmatchedStructures; private static Harmony harmony; private void Awake() { //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ConfigSyncAvailable = Chainloader.PluginInfos.ContainsKey("_shudnal.ConditionalConfigSync"); if (ConfigSyncAvailable) { ConfigSyncCompat.Initialize("com.dreich.repairenemystructures", "Repair Enemy Structures", "1.0.1"); } else { Log.LogInfo((object)"ConditionalConfigSync not found; configuration will not be synced from the server."); } lockConfigurationSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock Configuration", true, "If on, the configuration is locked and can be changed by server admins only. Requires ConditionalConfigSync."); if (ConfigSyncAvailable) { ConfigSyncCompat.AddLockingConfigEntry(lockConfigurationSetting); } RepairDvergr = BindServerControlled("General", "RepairDvergr", defaultValue: true, "Allow hammer repair on Dvergr structures."); RepairFuling = BindServerControlled("General", "RepairFuling", defaultValue: true, "Allow hammer repair on Fuling structures."); DvergrPrefabKeywords = BindServerControlled("General", "DvergrPrefabKeywords", "dvergr,dverger", "Comma-separated keywords; a structure prefab whose name contains any of them counts as a Dvergr structure."); FulingPrefabKeywords = BindServerControlled("General", "FulingPrefabKeywords", "goblin", "Comma-separated keywords; a structure prefab whose name contains any of them counts as a Fuling structure."); FulingStation = BindServerControlled("Stations", "FulingStation", Station.Workbench, "Station that must be nearby to repair Fuling structures. None = no station needed."); DvergrDefaultStation = BindServerControlled("Stations", "DvergrDefaultStation", Station.Workbench, "Station needed for Dvergr structures unless a keyword list below matches."); DvergrGroupAKeywords = BindServerControlled("Stations", "DvergrGroupAKeywords", "door,wisp,ferment", "Comma-separated prefab-name keywords for Dvergr group A (default: doors, wisp torch, fermenter)."); DvergrGroupAStation = BindServerControlled("Stations", "DvergrGroupAStation", Station.Forge, "Station needed for Dvergr structures matching group A."); DvergrGroupBKeywords = BindServerControlled("Stations", "DvergrGroupBKeywords", "marble,crown", "Comma-separated prefab-name keywords for Dvergr group B (default: marble, crown)."); DvergrGroupBStation = BindServerControlled("Stations", "DvergrGroupBStation", Station.Stonecutter, "Station needed for Dvergr structures matching group B."); StationOverrides = BindServerControlled("Stations", "StationOverrides", "", "Exact per-prefab overrides, comma-separated, as prefabname=Station (e.g. dvergrtown_creep_door=Forge,dvergrprops_marble_wall=Stonecutter). Checked before keywords."); RepairEffectPrefab = BindClientControlled("Effects", "RepairEffectPrefab", "wood_floor", "Name of a vanilla build piece whose placement sound and effects play when a Dvergr or Fuling structure is repaired. Leave empty for no effects."); LogPatched = BindClientControlled("Debug", "LogPatchedPrefabs", defaultValue: false, "Log every prefab that gets patched."); LogUnmatchedStructures = BindClientControlled("Debug", "LogUnmatchedStructures", defaultValue: false, "Log the names of structure prefabs that have no Piece and did not match the Dvergr/Fuling keywords, to help find the right names."); harmony = new Harmony("com.dreich.repairenemystructures"); harmony.PatchAll(); } private ConfigEntry<T> BindServerControlled<T>(string section, string key, T defaultValue, string description) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description); if (ConfigSyncAvailable) { ConfigSyncCompat.AddConfigEntry<T>(val, serverControlled: true); } return val; } private ConfigEntry<T> BindClientControlled<T>(string section, string key, T defaultValue, string description) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description); if (ConfigSyncAvailable) { ConfigSyncCompat.AddConfigEntry<T>(val, serverControlled: false); } return val; } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } harmony = null; } internal static bool IsRepairablePrefab(string prefabName) { string name = prefabName.ToLowerInvariant(); if (RepairDvergr.Value && ContainsAnyKeyword(name, DvergrPrefabKeywords.Value)) { return true; } if (RepairFuling.Value && ContainsAnyKeyword(name, FulingPrefabKeywords.Value)) { return true; } return false; } internal static Station GetStationFor(string prefabName) { string text = prefabName.ToLowerInvariant(); string[] array = StationOverrides.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }); if (array2.Length == 2 && !(array2[0].Trim().ToLowerInvariant() != text) && Enum.TryParse<Station>(array2[1].Trim(), ignoreCase: true, out var result)) { return result; } } if (ContainsAnyKeyword(text, FulingPrefabKeywords.Value)) { return FulingStation.Value; } if (ContainsAnyKeyword(text, DvergrGroupAKeywords.Value)) { return DvergrGroupAStation.Value; } if (ContainsAnyKeyword(text, DvergrGroupBKeywords.Value)) { return DvergrGroupBStation.Value; } return DvergrDefaultStation.Value; } private static bool ContainsAnyKeyword(string name, string keywordList) { string[] array = keywordList.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim().ToLowerInvariant(); if (text.Length > 0 && name.Contains(text)) { return true; } } return false; } internal static string GetStationPrefabName(Station station) { return station switch { Station.Workbench => "piece_workbench", Station.Cauldron => "piece_cauldron", Station.Forge => "forge", Station.ArtisanTable => "piece_artisanstation", Station.Stonecutter => "piece_stonecutter", Station.MageTable => "piece_magetable", Station.BlackForge => "blackforge", _ => null, }; } } internal static class ConfigSyncCompat { private static object configSync; [MethodImpl(MethodImplOptions.NoInlining)] internal static void Initialize(string guid, string name, string version) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown configSync = (object)new ConfigSync(guid) { DisplayName = name, CurrentVersion = version, MinimumRequiredVersion = version, ModRequired = false, ModRequirementMode = (ModRequirementMode)1 }; } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddLockingConfigEntry(ConfigEntry<bool> entry) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ((ConditionalConfigSync)(ConfigSync)configSync).AddLockingConfigEntry<bool>(entry); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddConfigEntry<T>(ConfigEntry<T> entry, bool serverControlled) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ((ConditionalConfigSync)(ConfigSync)configSync).AddConfigEntry<T>(entry, (ConfigSyncMode)((!serverControlled) ? 2 : 0)); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class EnemyStructurePrefabPatch { private static Piece FindEffectSource(ZNetScene scene) { string text = RepairEnemyStructuresPlugin.RepairEffectPrefab.Value.Trim(); if (text.Length == 0) { return null; } GameObject prefab = scene.GetPrefab(text); if (!((Object)(object)prefab != (Object)null)) { return null; } return prefab.GetComponent<Piece>(); } private static string FindStationName(ZNetScene scene, Station station, string prefabName) { string stationPrefabName = RepairEnemyStructuresPlugin.GetStationPrefabName(station); if (stationPrefabName == null) { return null; } GameObject prefab = scene.GetPrefab(stationPrefabName); CraftingStation val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CraftingStation>() : null); if ((Object)(object)val == (Object)null) { RepairEnemyStructuresPlugin.Log.LogWarning((object)("Station prefab '" + stationPrefabName + "' not found for " + prefabName)); return null; } return val.m_name; } private static void Postfix(ZNetScene __instance) { Piece val = FindEffectSource(__instance); int num = 0; List<string> list = new List<string>(); foreach (GameObject prefab in __instance.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } bool flag = (Object)(object)prefab.GetComponent<WearNTear>() != (Object)null; RepairRequiresStation repairRequiresStation = prefab.GetComponent<RepairRequiresStation>(); bool flag2 = (Object)(object)prefab.GetComponent<Piece>() != (Object)null; if (!RepairEnemyStructuresPlugin.IsRepairablePrefab(((Object)prefab).name)) { if ((Object)(object)repairRequiresStation != (Object)null) { repairRequiresStation.StationName = null; } else if (flag && !flag2) { list.Add(((Object)prefab).name); } } else { if (!flag) { continue; } if (!flag2) { Piece val2 = prefab.AddComponent<Piece>(); val2.m_name = ((Object)prefab).name; val2.m_canBeRemoved = false; ((StaticTarget)val2).m_primaryTarget = false; ((StaticTarget)val2).m_randomTarget = false; val2.m_targetNonPlayerBuilt = false; if ((Object)(object)val != (Object)null) { val2.m_placeEffect = val.m_placeEffect; } } Station stationFor = RepairEnemyStructuresPlugin.GetStationFor(((Object)prefab).name); string stationName = FindStationName(__instance, stationFor, ((Object)prefab).name); if ((Object)(object)repairRequiresStation == (Object)null) { repairRequiresStation = prefab.AddComponent<RepairRequiresStation>(); } repairRequiresStation.StationName = stationName; num++; if (RepairEnemyStructuresPlugin.LogPatched.Value) { RepairEnemyStructuresPlugin.Log.LogInfo((object)$"Patched {((Object)prefab).name} (needs {stationFor}, Piece already existed: {flag2})"); } } } RepairEnemyStructuresPlugin.Log.LogInfo((object)$"Patched {num} prefabs."); if (RepairEnemyStructuresPlugin.LogUnmatchedStructures.Value && list.Count > 0) { list.Sort(); RepairEnemyStructuresPlugin.Log.LogInfo((object)("Structures without a Piece that did not match: " + string.Join(", ", list.ToArray()))); } } } [HarmonyPatch(typeof(Player), "Repair")] internal static class RepairStationRequirementPatch { private static bool Prefix(Player __instance, Piece repairPiece) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)repairPiece == (Object)null) { return true; } RepairRequiresStation component = ((Component)repairPiece).GetComponent<RepairRequiresStation>(); if ((Object)(object)component == (Object)null || string.IsNullOrEmpty(component.StationName)) { return true; } if (Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(component.StationName, ((Component)__instance).transform.position))) { return true; } string text = Localization.instance.Localize(component.StationName); ((Character)__instance).Message((MessageType)2, "Requires a nearby " + text + " to repair", 0, (Sprite)null, false); return false; } } }