Decompiled source of EasyBuild v1.0.0

plugins/EasyBuild/EasyBuild.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("EasyBuild")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EasyBuild")]
[assembly: AssemblyTitle("EasyBuild")]
[assembly: AssemblyVersion("1.0.0.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 EasyBuild
{
	[BepInPlugin("easybuild.client.only", "EasyBuild", "1.0.0")]
	public class EasyBuildPlugin : BaseUnityPlugin
	{
		public const string Guid = "easybuild.client.only";

		public const string PluginName = "EasyBuild";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> SweepPrefabsOnSceneLoad;

		internal static ConfigEntry<bool> VerboseLog;

		private Harmony harmony;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - 随处建造", "Enabled", true, "总开关。开启后:建造、修复(含船)、拆除都不再要求工作台/熔炉/石匠台在附近。\n关闭则完全是原版行为。");
			SweepPrefabsOnSceneLoad = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - 随处建造", "SweepAllPrefabsOnSceneLoad", true, "场景加载时再把所有建筑部件扫一遍(兜底)。\n主逻辑是挂在 Piece.Awake 上的,正常情况下已经够用;\n如果以后装了别的模组往部件上动态塞工作台需求,这一项能补上。");
			VerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - 日志", "VerboseLog", false, "详细日志:每剥离一个部件就打一行(部件很多,平时建议关掉)。\n无论开关如何,每次启动都会打印一行汇总(处理了多少个部件 + 几个例子),\n方便你确认模组到底有没有生效。");
			Log.LogInfo((object)"EasyBuild 1.0.0 开始挂载 Harmony 补丁……");
			StationStripper.Init();
			ApplyPatches();
			VerifyPatches();
		}

		private void ApplyPatches()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony = new Harmony("easybuild.client.only");
			Type[] array = new Type[2]
			{
				typeof(PieceAwakePatch),
				typeof(ZNetSceneAwakePatch)
			};
			int num = 0;
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				try
				{
					harmony.CreateClassProcessor(type).Patch();
					Log.LogInfo((object)("  已挂载补丁类:" + type.Name));
					num++;
				}
				catch (Exception ex)
				{
					Log.LogError((object)("  挂载失败 " + type.Name + ":" + ex.Message));
				}
			}
			Log.LogInfo((object)$"Harmony 补丁挂载完成:{num}/{array.Length} 成功。");
		}

		private void VerifyPatches()
		{
			MethodBase[] obj = new MethodBase[2]
			{
				AccessTools.Method(typeof(Piece), "Awake", (Type[])null, (Type[])null),
				AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null)
			};
			Log.LogInfo((object)"---- 补丁挂载自检 ----");
			MethodBase[] array = obj;
			foreach (MethodBase methodBase in array)
			{
				if (methodBase == null)
				{
					Log.LogWarning((object)"  找不到目标方法(可能游戏版本变了)");
					continue;
				}
				Patches patchInfo = Harmony.GetPatchInfo(methodBase);
				int num = ((patchInfo != null && patchInfo.Prefixes != null) ? patchInfo.Prefixes.Count : 0);
				int num2 = ((patchInfo != null && patchInfo.Postfixes != null) ? patchInfo.Postfixes.Count : 0);
				string text = ((num + num2 > 0) ? "OK" : "!! 未挂上 !!");
				Log.LogInfo((object)$"  {methodBase.DeclaringType.Name}.{methodBase.Name}()  prefix={num} postfix={num2}  {text}");
			}
			Log.LogInfo((object)"-----------------------");
		}

		private void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class StationStripper
	{
		private static FieldInfo stationField;

		private static bool unavailable;

		internal static int StrippedCount;

		internal static int SeenCount;

		private static readonly List<string> Samples = new List<string>();

		private static float lastSummaryAt = -999f;

		internal static void Init()
		{
			stationField = AccessTools.Field(typeof(Piece), "m_craftingStation");
			if (stationField == null)
			{
				unavailable = true;
				EasyBuildPlugin.Log.LogError((object)"找不到字段 Piece.m_craftingStation —— 模组无法生效(游戏版本可能已变更,请反馈)。");
			}
		}

		internal static void Strip(Piece piece)
		{
			if ((Object)(object)piece == (Object)null)
			{
				return;
			}
			SeenCount++;
			if (!unavailable && EasyBuildPlugin.Enabled.Value && stationField.GetValue(piece) != null)
			{
				stationField.SetValue(piece, null);
				StrippedCount++;
				string name = ((Object)piece).name;
				if (Samples.Count < 8 && !Samples.Contains(name))
				{
					Samples.Add(name);
				}
				if (EasyBuildPlugin.VerboseLog.Value)
				{
					EasyBuildPlugin.Log.LogInfo((object)("  剥离工作台需求:" + name));
				}
				else
				{
					LogSummaryThrottled();
				}
			}
		}

		private static void LogSummaryThrottled()
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (!(realtimeSinceStartup - lastSummaryAt < 3f))
			{
				lastSummaryAt = realtimeSinceStartup;
				LogSummary();
			}
		}

		internal static void LogSummary()
		{
			if (StrippedCount == 0)
			{
				EasyBuildPlugin.Log.LogWarning((object)("已剥离工作台需求:0 个(见过的部件 " + SeenCount + " 个)。如果你确实需要工作台的部件照样要工作台,说明没生效,请把日志发我。"));
			}
			else
			{
				EasyBuildPlugin.Log.LogInfo((object)string.Format("已剥离工作台需求:{0} 个部件(见过的部件共 {1} 个)。例:{2}", StrippedCount, SeenCount, string.Join(" / ", Samples.ToArray())));
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "Awake")]
	internal static class PieceAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Piece __instance)
		{
			try
			{
				StationStripper.Strip(__instance);
			}
			catch (Exception ex)
			{
				EasyBuildPlugin.Log.LogError((object)("Piece.Awake postfix 出错:" + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(ZNetScene __instance)
		{
			try
			{
				if (!EasyBuildPlugin.Enabled.Value)
				{
					return;
				}
				if (!EasyBuildPlugin.SweepPrefabsOnSceneLoad.Value)
				{
					EasyBuildPlugin.Log.LogInfo((object)"(SweepAllPrefabsOnSceneLoad 已关闭,跳过兜底扫描)");
					return;
				}
				List<GameObject> prefabs = __instance.m_prefabs;
				int num = 0;
				if (prefabs != null)
				{
					foreach (GameObject item in prefabs)
					{
						if (!((Object)(object)item == (Object)null))
						{
							Piece component = item.GetComponent<Piece>();
							if (!((Object)(object)component == (Object)null))
							{
								num++;
								StationStripper.Strip(component);
							}
						}
					}
				}
				EasyBuildPlugin.Log.LogInfo((object)("兜底扫描完成:检查了 " + num + " 个部件 prefab。"));
				StationStripper.LogSummary();
			}
			catch (Exception ex)
			{
				EasyBuildPlugin.Log.LogError((object)("ZNetScene.Awake postfix 出错:" + ex.Message));
			}
		}
	}
}