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 EasyGear v1.0.3
plugins/EasyGear/EasyGear.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; 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("EasyGear")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("EasyGear")] [assembly: AssemblyTitle("EasyGear")] [assembly: AssemblyVersion("1.0.3.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 EasyGear { [HarmonyPatch(typeof(Player), "DamageArmorDurability", new Type[] { typeof(HitData) })] internal static class PlayerDamageArmorDurabilityPatch { private static readonly FieldInfo F_Chest = AccessTools.Field(typeof(Humanoid), "m_chestItem"); private static readonly FieldInfo F_Leg = AccessTools.Field(typeof(Humanoid), "m_legItem"); private static readonly FieldInfo F_Helmet = AccessTools.Field(typeof(Humanoid), "m_helmetItem"); private static readonly FieldInfo F_Shoulder = AccessTools.Field(typeof(Humanoid), "m_shoulderItem"); private static bool reported; internal static bool FieldsResolved { get { if (F_Chest != null && F_Leg != null && F_Helmet != null) { return F_Shoulder != null; } return false; } } private static float mult0 => Mathf.Max(0.01f, EasyGearPlugin.DurabilityLifetimeMultiplier.Value); private static bool Active() { if (!EasyGearPlugin.DurabilityEnabled.Value) { return false; } string value = EasyGearPlugin.DurabilityMode.Value; if (!(value == "LossReduction") && !(value == "Both")) { return false; } return EasyGearPlugin.DurabilityLifetimeMultiplier.Value > 1.0001f; } [HarmonyPrefix] private static void Prefix(Player __instance, out float[] __state) { __state = null; if (!((Object)(object)__instance == (Object)null) && Active() && FieldsResolved && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __state = new float[4] { DurabilityOf(__instance, F_Chest), DurabilityOf(__instance, F_Leg), DurabilityOf(__instance, F_Helmet), DurabilityOf(__instance, F_Shoulder) }; } } [HarmonyPostfix] private static void Postfix(Player __instance, HitData hit, float[] __state) { if (__state != null && !((Object)(object)__instance == (Object)null) && hit != null) { float num = hit.GetTotalPhysicalDamage() + hit.GetTotalElementalDamage(); if (!(num <= 0f)) { float num2 = Mathf.Max(0.01f, EasyGearPlugin.DurabilityLifetimeMultiplier.Value); float cost = num / num2; Correct(__instance, F_Chest, __state[0], cost); Correct(__instance, F_Leg, __state[1], cost); Correct(__instance, F_Helmet, __state[2], cost); Correct(__instance, F_Shoulder, __state[3], cost); } } } private static ItemData ItemAt(Player p, FieldInfo f) { if (f == null) { return null; } try { object? value = f.GetValue(p); return (ItemData)((value is ItemData) ? value : null); } catch { return null; } } private static float DurabilityOf(Player p, FieldInfo f) { return ItemAt(p, f)?.m_durability ?? float.NaN; } private static void Correct(Player p, FieldInfo f, float before, float cost) { if (float.IsNaN(before)) { return; } ItemData val = ItemAt(p, f); if (val == null || val.m_durability >= before - 0.0001f) { return; } float num = Mathf.Max(0f, before - cost); if (!(num <= val.m_durability + 0.0001f)) { val.m_durability = num; if (!reported) { reported = true; EasyGearPlugin.Log.LogInfo((object)string.Format("护甲耐久倍率已生效(LossReduction ÷{0:0.##}):{1} 受击伤害 {2:0.##} → 应扣 {3:0.##}(耐久 {4:0.##} → {5:0.##})", mult0, (val.m_shared != null) ? val.m_shared.m_name : "(?)", cost * mult0, cost, before, num)); } } } } internal static class AutoRepair { private static MethodInfo miCanRepair; private static MethodInfo miUpdateRepair; private static MethodInfo miMessage; private static MethodInfo miRaiseSkill; private static MethodInfo miLocalize; private static Type messageTypeEnum; private static Type skillTypeEnum; private const int VanillaRepairSkillValue = 107; private static bool running; internal static void Init() { Type typeFromHandle = typeof(InventoryGui); miCanRepair = AccessTools.Method(typeFromHandle, "CanRepair", new Type[1] { typeof(ItemData) }, (Type[])null); miUpdateRepair = AccessTools.Method(typeFromHandle, "UpdateRepair", (Type[])null, (Type[])null); if (miCanRepair == null) { EasyGearPlugin.Log.LogError((object)"找不到 InventoryGui.CanRepair —— 自动修理无法生效(游戏版本可能已变更,请反馈)。"); } miMessage = FindMethod(typeof(Character), "Message", 5); if (miMessage != null) { messageTypeEnum = miMessage.GetParameters()[0].ParameterType; } miRaiseSkill = FindMethod(typeof(Character), "RaiseSkill", 2); if (miRaiseSkill != null) { skillTypeEnum = miRaiseSkill.GetParameters()[0].ParameterType; } miLocalize = AccessTools.Method(typeof(Localization), "Localize", new Type[1] { typeof(string) }, (Type[])null); } private static MethodInfo FindMethod(Type type, string name, int paramCount) { try { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < methods.Length; i++) { if (methods[i].Name == name && methods[i].GetParameters().Length == paramCount) { return methods[i]; } } } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("查找 " + type.Name + "." + name + " 失败:" + ex.Message)); } return null; } private static bool CanRepair(InventoryGui gui, ItemData item) { if (miCanRepair == null || (Object)(object)gui == (Object)null || item == null) { return false; } try { object obj = miCanRepair.Invoke(gui, new object[1] { item }); return obj is bool && (bool)obj; } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("调用 InventoryGui.CanRepair 失败:" + ex.Message)); return false; } } private static bool IsDamaged(ItemData item) { if (item == null) { return false; } float maxDurability = item.GetMaxDurability(); if (maxDurability > 0f) { return item.m_durability < maxDurability - 0.001f; } return false; } internal static int Begin(InventoryGui gui, bool includeBackpack, int intervalMs) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 0; } CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation(); if ((Object)(object)currentCraftingStation == (Object)null) { return 0; } if (!currentCraftingStation.CheckUsable(localPlayer, false)) { return 0; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory == null) { return 0; } List<ItemData> allItems = inventory.GetAllItems(); if (allItems == null || allItems.Count == 0) { return 0; } List<ItemData> list = new List<ItemData>(); try { inventory.GetWornItems(list); } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("取「穿戴中的物品」失败,本次按全部物品处理:" + ex.Message)); } List<ItemData> list2 = new List<ItemData>(); for (int i = 0; i < allItems.Count; i++) { ItemData item = allItems[i]; if (IsDamaged(item) && CanRepair(gui, item) && (list.Contains(item) || includeBackpack)) { list2.Add(item); } } if (list2.Count == 0) { return 0; } if (intervalMs <= 0 || (Object)(object)EasyGearPlugin.Instance == (Object)null) { int num = RepairAll(list2, currentCraftingStation, list); running = false; Finish(currentCraftingStation, num, 0); return num; } if (running) { return 0; } running = true; ((MonoBehaviour)EasyGearPlugin.Instance).StartCoroutine(RepairSequence(list2, currentCraftingStation, list, intervalMs)); return list2.Count; } private static IEnumerator RepairSequence(List<ItemData> todo, CraftingStation station, List<ItemData> worn, int intervalMs) { float wait = Mathf.Max(0.01f, (float)intervalMs / 1000f); int done = 0; int aborted = 0; for (int i = 0; i < todo.Count; i++) { ItemData val = todo[i]; if (val != null) { Player localPlayer = Player.m_localPlayer; CraftingStation val2 = (((Object)(object)localPlayer == (Object)null) ? null : localPlayer.GetCurrentCraftingStation()); if ((Object)(object)localPlayer == (Object)null || (Object)(object)val2 != (Object)(object)station || !station.CheckUsable(localPlayer, false)) { aborted = todo.Count - i; break; } try { RepairOne(localPlayer, val, station, worn.Contains(val)); done++; } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("自动修理某件物品时出错(继续修下一件):" + ex.Message)); } if (i < todo.Count - 1) { yield return (object)new WaitForSecondsRealtime(wait); } } } running = false; Finish(station, done, aborted); } private static int RepairAll(List<ItemData> todo, CraftingStation station, List<ItemData> worn) { int num = 0; for (int i = 0; i < todo.Count; i++) { try { if (todo[i] != null) { RepairOne(Player.m_localPlayer, todo[i], station, worn.Contains(todo[i])); num++; } } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("自动修理某件物品时出错:" + ex.Message)); } } return num; } private static void RepairOne(Player player, ItemData item, CraftingStation station, bool announce) { //IL_00b2: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) float maxDurability = item.GetMaxDurability(); if (maxDurability <= 0f) { return; } if (miRaiseSkill != null && skillTypeEnum != null) { try { miRaiseSkill.Invoke(player, new object[2] { Enum.ToObject(skillTypeEnum, 107), 1f - item.m_durability / maxDurability }); } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("加修理熟练度失败(不影响修理):" + ex.Message)); } } item.m_durability = maxDurability; if ((Object)(object)station != (Object)null && station.m_repairItemDoneEffects != null && (Object)(object)((Component)station).transform != (Object)null) { try { station.m_repairItemDoneEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } catch (Exception ex2) { EasyGearPlugin.Log.LogWarning((object)("播放修理特效失败(不影响修理本身):" + ex2.Message)); } } if (announce) { ShowMessage("已修复 " + LocalizeName(item)); } } private static string LocalizeName(ItemData item) { string text = ((item.m_shared == null) ? null : item.m_shared.m_name); if (string.IsNullOrEmpty(text)) { if (!((Object)(object)item.m_dropPrefab != (Object)null)) { return "物品"; } return ((Object)item.m_dropPrefab).name; } if (miLocalize != null) { try { object obj = miLocalize.Invoke(Localization.instance, new object[1] { text }); if (obj is string && !string.IsNullOrEmpty((string)obj)) { return (string)obj; } } catch { } } return text; } private static void Finish(CraftingStation station, int done, int aborted) { string text = (((Object)(object)station == (Object)null) ? "?" : station.m_name); if (aborted > 0) { EasyGearPlugin.Log.LogInfo((object)$"自动修理:「{text}」修好 {done} 件后中断(还剩 {aborted} 件没修)—— 你离开了站点或站点失效。"); } else if (done > 0) { EasyGearPlugin.Log.LogInfo((object)$"自动修理:「{text}」修好 {done} 件(逐件间隔 {EasyGearPlugin.AutoRepairIntervalMs.Value}ms)。"); } if (done > 0 && EasyGearPlugin.AutoRepairShowMessage.Value) { ShowMessage($"自动修理:{done} 件({text})"); } try { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && miUpdateRepair != null) { miUpdateRepair.Invoke(instance, null); } } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("刷新修理面板失败(不影响已修好的物品):" + ex.Message)); } } internal static void ShowMessage(string text) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || miMessage == null || messageTypeEnum == null) { return; } try { miMessage.Invoke(localPlayer, new object[5] { Enum.ToObject(messageTypeEnum, 2), text, 0, null, false }); } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("显示提示失败(不影响修理):" + ex.Message)); } } } [BepInPlugin("easygear.client.only", "EasyGear", "1.0.3")] public class EasyGearPlugin : BaseUnityPlugin { public const string Guid = "easygear.client.only"; public const string PluginName = "EasyGear"; public const string PluginVersion = "1.0.3"; internal static ManualLogSource Log; internal static EasyGearPlugin Instance; internal static ConfigEntry<bool> DurabilityEnabled; internal static ConfigEntry<string> DurabilityMode; internal static ConfigEntry<float> DurabilityLifetimeMultiplier; internal static ConfigEntry<bool> AreaRepairEnabled; internal static ConfigEntry<float> AreaRepairRadius; internal static ConfigEntry<bool> AreaRepairVerbose; internal static ConfigEntry<bool> AutoRepairEnabled; internal static ConfigEntry<bool> AutoRepairIncludeBackpack; internal static ConfigEntry<int> AutoRepairIntervalMs; internal static ConfigEntry<bool> AutoRepairShowMessage; internal static ConfigEntry<bool> AutoRepairVerbose; internal static ConfigEntry<bool> EquipWhileRunningEnabled; private Harmony harmony; private void Awake() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; DurabilityEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Item Durability", "Enabled", true, "耐久修改开关。覆盖武器、工具、弓箭、盾牌、护甲、锤子、锄头等。"); DurabilityMode = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Item Durability", "Mode", "LossReduction", new ConfigDescription("耐久的实现方式:\n LossReduction = 耐久消耗 ÷ 倍率。装备明显更耐用,但物品提示里的耐久数字下降很慢,不容易一眼看出。\n MaxDurability = 耐久上限 × 倍率。物品提示里的上限直接变成 5 倍,一眼可见。\n 注意:已有的装备需要先用锤子修一次才会满。\n Both = 两者都做(寿命约 ×25,慎用)。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "LossReduction", "MaxDurability", "Both" }), Array.Empty<object>())); DurabilityLifetimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Item Durability", "LifetimeMultiplier", 5f, new ConfigDescription("耐久倍率:5 = 同样的装备能用 5 倍久。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); AreaRepairEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Area Repair", "Enabled", true, "锤子「范围修理」开关:用锤子的普通修理动作时,顺带修理附近的建筑部件。"); AreaRepairRadius = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Area Repair", "Radius", 30f, new ConfigDescription("范围修理半径(米),以你鼠标指向的那个部件为中心。默认 30 米。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); AreaRepairVerbose = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Area Repair", "Verbose", true, "打开后在日志里逐次记录修好了几个部件(排查用)。"); AutoRepairEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Auto Repair At Station", "Enabled", true, "打开工作台 / 熔炉(制造站)时,自动把身上受损的装备、工具、武器修满。\n身上穿戴的那批走的是游戏原版的修理函数,所以涨熟练度、修理特效、\n「已修复 xxx」提示都与手动点修理按钮完全一致;修理不消耗材料(原版修理本来就免费)。"); AutoRepairIncludeBackpack = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Auto Repair At Station", "IncludeBackpackItems", true, "顺便修理背包里【没穿戴】的装备/工具/武器。\ntrue(默认)= 背包里的也一起修好;false = 只修身上穿戴的(= 原版修理按钮的范围)。\n注意:原版修理按钮只修身上穿戴的,背包那批是本模组额外补的。"); AutoRepairIntervalMs = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Auto Repair At Station", "IntervalMilliseconds", 150, new ConfigDescription("逐件修理的间隔(毫秒)。装备多的时候一件件修,能看清耐久条一根根回满。\n0 = 一次性全部修好(原来的行为,会一瞬间全满)。建议 100 - 200。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000), Array.Empty<object>())); AutoRepairShowMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Auto Repair At Station", "ShowMessage", false, "在屏幕上再显示一行「自动修理:N 件(站点名)」。\n默认关闭 —— 原版本来就对每件修好的物品各弹一条「已修复 xxx」,够看了。"); AutoRepairVerbose = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Auto Repair At Station", "Verbose", false, "排查用:即使本次没有物品需要修理,也在日志里记一行(确认模组确实触发了)。"); EquipWhileRunningEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Equip While Running", "Enabled", true, "跑步时也能切换武器 / 工具(解除原版限制)。\n原版在奔跑时会每帧清空「装备动作队列」,导致带抽拿动画的武器/工具\n按数字键后动作被取消、看起来完全没反应。\n打开(默认)后:跑步中也能正常拿出/收回。\n⚠\ufe0f 只拦「跑步」发起的取消 —— 攻击、跳跃、翻滚时的取消保持原版行为。"); Log.LogInfo((object)"EasyGear 1.0.3 开始挂载 Harmony 补丁……"); AutoRepair.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("easygear.client.only"); Type[] array = new Type[7] { typeof(ObjectDbAwakePatch), typeof(ZNetSceneAwakePatch), typeof(PlayerRepairPatch), typeof(InventoryGuiShowPatch), typeof(PlayerCheckRunPatch), typeof(ClearActionQueuePatch), typeof(PlayerDamageArmorDurabilityPatch) }; 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() { List<MethodBase> list = new List<MethodBase>(); AddTarget(list, AccessTools.Method(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null), "ObjectDB.Awake(耐久改写入口)"); AddTarget(list, AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), "ZNetScene.Awake(耐久改写兜底)"); AddTarget(list, AccessTools.Method(typeof(Player), "Repair", (Type[])null, (Type[])null), "Player.Repair(范围修理)"); AddTarget(list, AccessTools.Method(typeof(InventoryGui), "Show", new Type[2] { typeof(Container), typeof(int) }, (Type[])null), "InventoryGui.Show(Container,int)(进站自动修理)"); AddTarget(list, AccessTools.Method(typeof(Player), "CheckRun", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null), "Player.CheckRun(Vector3,float)(跑步可切换装备·标记)"); AddTarget(list, AccessTools.Method(typeof(Humanoid), "ClearActionQueue", (Type[])null, (Type[])null), "Humanoid.ClearActionQueue(跑步可切换装备·拦截)"); MethodBase methodBase = AccessTools.Method(typeof(Player), "DamageArmorDurability", new Type[1] { typeof(HitData) }, (Type[])null); AddTarget(list, methodBase, "Player.DamageArmorDurability(HitData)(护甲耐久倍率)"); if (methodBase != null && methodBase.DeclaringType != typeof(Player)) { Log.LogError((object)(" !! DamageArmorDurability 解析到了 " + methodBase.DeclaringType.Name + ",而不是 Player 的重写 —— 护甲倍率可能不会生效")); } if (!PlayerDamageArmorDurabilityPatch.FieldsResolved) { Log.LogError((object)" !! 反射不到护甲槽位字段(m_chestItem/m_legItem/m_helmetItem/m_shoulderItem) —— 护甲耐久倍率不会生效"); } Log.LogInfo((object)"---- 补丁挂载自检 ----"); foreach (MethodBase item in list) { Patches patchInfo = Harmony.GetPatchInfo(item); 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)$" {item.DeclaringType.Name}.{item.Name}() prefix={num} postfix={num2} {text}"); } Log.LogInfo((object)$" (目标方法 {list.Count} 个,全部已核对)"); Log.LogInfo((object)"-----------------------"); } private static void AddTarget(List<MethodBase> targets, MethodBase m, string label) { if (m == null) { Log.LogError((object)(" !! 找不到目标方法,对应功能不会生效:" + label)); } else { targets.Add(m); } } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class ObjectDbApplier { private static readonly Dictionary<SharedData, float> OrigDurabilityDrain = new Dictionary<SharedData, float>(); private static readonly Dictionary<SharedData, float> OrigMaxDurability = new Dictionary<SharedData, float>(); private static bool appliedOnce; internal static bool AppliedOnce => appliedOnce; internal static void ApplyIfReady(string source) { try { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { EasyGearPlugin.Log.LogWarning((object)("[" + source + "] ObjectDB 还没就绪,稍后重试。")); } else if (instance.m_items == null) { EasyGearPlugin.Log.LogWarning((object)("[" + source + "] ObjectDB.m_items 为 null,跳过。")); } else { Apply(instance, source); } } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("[" + source + "] 应用失败(游戏本身不受影响):" + ex)); } } private static void Apply(ObjectDB db, string source) { bool value = EasyGearPlugin.DurabilityEnabled.Value; float num = Mathf.Max(0.01f, EasyGearPlugin.DurabilityLifetimeMultiplier.Value); string value2 = EasyGearPlugin.DurabilityMode.Value; bool flag = value2 == "LossReduction" || value2 == "Both"; bool flag2 = value2 == "MaxDurability" || value2 == "Both"; int num2 = 0; int num3 = 0; StringBuilder stringBuilder = new StringBuilder(); foreach (GameObject item in db.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null) { continue; } SharedData shared = component.m_itemData.m_shared; if (shared == null || !value || !shared.m_useDurability) { continue; } if (flag && shared.m_useDurabilityDrain > 0f) { if (!OrigDurabilityDrain.TryGetValue(shared, out var value3)) { value3 = shared.m_useDurabilityDrain; OrigDurabilityDrain[shared] = value3; } float num4 = (shared.m_useDurabilityDrain = value3 / num); num2++; if (stringBuilder.Length < 1200) { stringBuilder.AppendFormat(" {0}: 每次消耗 {1:0.####} -> {2:0.####}{3}", shared.m_name, value3, num4, Environment.NewLine); } } if (flag2 && shared.m_maxDurability > 0f) { if (!OrigMaxDurability.TryGetValue(shared, out var value4)) { value4 = shared.m_maxDurability; OrigMaxDurability[shared] = value4; } shared.m_maxDurability = value4 * num; num3++; } } appliedOnce = true; string text = ((value2 == "Both") ? string.Format("消耗 ÷{0}({1} 件) + 上限 ×{0}({2} 件)", num, num2, num3) : ((!(value2 == "MaxDurability")) ? $"消耗 ÷{num}({num2} 件)" : $"上限 ×{num}({num3} 件)")); if (!value) { text = "已关闭(Enabled=false)"; } EasyGearPlugin.Log.LogInfo((object)$"[{source}] 已处理 {db.m_items.Count} 件物品 → 耐久 {value2}:{text}"); if (stringBuilder.Length > 0) { EasyGearPlugin.Log.LogInfo((object)("---- 耐久改动明细(前几件)----" + Environment.NewLine + stringBuilder)); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDbAwakePatch { [HarmonyPostfix] private static void Postfix() { ObjectDbApplier.ApplyIfReady("ObjectDB.Awake"); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneAwakePatch { [HarmonyPostfix] private static void Postfix() { ObjectDbApplier.ApplyIfReady("ZNetScene.Awake"); } } [HarmonyPatch(typeof(Player), "Repair")] internal static class PlayerRepairPatch { private static bool repairing; [HarmonyPostfix] private static void Postfix(Player __instance) { //IL_004d: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (repairing || !EasyGearPlugin.AreaRepairEnabled.Value) { return; } try { if ((Object)(object)__instance == (Object)null) { return; } Piece hoveringPiece = __instance.GetHoveringPiece(); if ((Object)(object)hoveringPiece == (Object)null || (Object)(object)((Component)hoveringPiece).transform == (Object)null) { return; } Vector3 position = ((Component)hoveringPiece).transform.position; float value = EasyGearPlugin.AreaRepairRadius.Value; float num = value * value; List<WearNTear> allInstances = WearNTear.GetAllInstances(); if (allInstances == null || allInstances.Count == 0) { return; } repairing = true; int num2 = 0; for (int i = 0; i < allInstances.Count; i++) { WearNTear val = allInstances[i]; if ((Object)(object)val == (Object)null) { continue; } Transform transform = ((Component)val).transform; if (!((Object)(object)transform == (Object)null)) { Vector3 val2 = transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > num) && val.Repair()) { num2++; } } } repairing = false; if (num2 > 0 && EasyGearPlugin.AreaRepairVerbose.Value) { EasyGearPlugin.Log.LogInfo((object)$"范围修理(半径 {value} 米):额外修好 {num2} 个部件。"); } } catch (Exception ex) { repairing = false; EasyGearPlugin.Log.LogError((object)("范围修理失败(普通修理不受影响):" + ex)); } } } [HarmonyPatch(typeof(InventoryGui), "Show", new Type[] { typeof(Container), typeof(int) })] internal static class InventoryGuiShowPatch { private static bool wasVisible; [HarmonyPrefix] private static void Prefix() { try { wasVisible = InventoryGui.IsVisible(); } catch { wasVisible = false; } } [HarmonyPostfix] private static void Postfix(InventoryGui __instance, int activeGroup) { try { if (!wasVisible && activeGroup == 3 && EasyGearPlugin.AutoRepairEnabled.Value && AutoRepair.Begin(__instance, EasyGearPlugin.AutoRepairIncludeBackpack.Value, EasyGearPlugin.AutoRepairIntervalMs.Value) <= 0 && EasyGearPlugin.AutoRepairVerbose.Value) { EasyGearPlugin.Log.LogInfo((object)"自动修理:在制造站触发过检查,本次没有需要修理的物品(或人已不在站点旁)。"); } } catch (Exception ex) { EasyGearPlugin.Log.LogError((object)("自动修理失败(不影响正常游戏):" + ex)); } } } [HarmonyPatch(typeof(Player), "CheckRun", new Type[] { typeof(Vector3), typeof(float) })] internal static class PlayerCheckRunPatch { internal static bool InCheckRun; [HarmonyPrefix] private static void Prefix() { InCheckRun = true; } [HarmonyPostfix] private static void Postfix() { InCheckRun = false; } } [HarmonyPatch(typeof(Humanoid), "ClearActionQueue")] internal static class ClearActionQueuePatch { [HarmonyPrefix] private static bool Prefix(Humanoid __instance) { try { if (!EasyGearPlugin.EquipWhileRunningEnabled.Value) { return true; } if (!PlayerCheckRunPatch.InCheckRun) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || !((Character)val).IsRunning()) { return true; } return false; } catch (Exception ex) { EasyGearPlugin.Log.LogWarning((object)("跑步可切换装备:判定出错,本次交给原版处理:" + ex.Message)); return true; } } } }