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 PlantEasilyFix v1.2.2
plugins/PlantEasilyFix/PlantEasilyFix.dll
Decompiled 3 hours agousing System; using System.Collections; 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("PlantEasilyFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.2.0")] [assembly: AssemblyInformationalVersion("1.2.2")] [assembly: AssemblyProduct("PlantEasilyFix")] [assembly: AssemblyTitle("PlantEasilyFix")] [assembly: AssemblyVersion("1.2.2.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 PlantEasilyFix { [BepInPlugin("s6652289.PlantEasilyFix", "PlantEasily Fix", "1.2.2")] public class PlantEasilyFixPlugin : BaseUnityPlugin { public const string Guid = "s6652289.PlantEasilyFix"; public const string Version = "1.2.2"; internal static ManualLogSource L; private Harmony _harmony; private bool _patchedGrid; private bool _patchedReplant; private bool _gridGaveUp; private bool _replantGaveUp; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> VerboseLog; internal static ConfigEntry<bool> SameCropReplant; private static FieldInfo _gridVersionField; private static int _fixCount; private static FieldInfo _extraGhostsField; private static FieldInfo _lastUpdatedField; private static MethodInfo _maxActiveGhostsGetter; private static MethodInfo _columnsGetter; private static FieldInfo _modConfigInstanceField; private static MethodInfo _getGhostObject; private static MethodInfo _getGhostCache; private static MethodInfo _getGhostPosition; private static MethodInfo _updateGhostTransform; private static int _repositionCalls; private static int _repositionTotal; private static FieldInfo _lastSelectedField; private static int _replantOverrideCount; private void Awake() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown L = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "启用本补丁。关闭后重启游戏即等同于未安装。\nEnable this patch. Turn off and restart to disable entirely."); VerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLog", false, "每次修正网格版本号 / 补摆幽灵时输出日志(排查问题用;正常游玩建议保持关闭)。\nLog every grid-version bump and ghost reposition (for troubleshooting; keep off for normal play)."); SameCropReplant = ((BaseUnityPlugin)this).Config.Bind<bool>("Replant", "SameCropReplant", true, "自动补种时,按【被收获的那种作物】补种,而不是统一补成你最近选中的那一种。\n关掉 → 恢复 PlantEasily 原行为(收什么都补成你当前手持耕耘机选中的作物)。\n改动本项无需重启游戏,下一次补种立即生效。\nReplant each crop as the very crop you harvested, instead of always using the plant you last selected with the cultivator. Turn off to restore the original PlantEasily behaviour."); if (!Enabled.Value) { L.LogInfo((object)"已在配置中禁用,补丁未挂载。"); return; } _harmony = new Harmony("s6652289.PlantEasilyFix"); ((MonoBehaviour)this).StartCoroutine(PatchWhenReady()); } private IEnumerator PatchWhenReady() { for (int i = 0; i < 120; i++) { if (_patchedGrid && _patchedReplant) { break; } try { if (!_patchedGrid && !_gridGaveUp) { Type type = AccessTools.TypeByName("Advize_PlantEasily.GhostGrid"); if (type != null) { PatchGrid(type); } } if (!_patchedReplant && !_replantGaveUp) { Type type2 = AccessTools.TypeByName("Advize_PlantEasily.PlacementState"); if (type2 != null) { PatchReplant(type2); } } } catch (Exception ex) { L.LogError((object)("挂载补丁时异常:" + ex)); } yield return (object)new WaitForSecondsRealtime(1f); } if (!_patchedGrid || !_patchedReplant) { L.LogWarning((object)string.Format("补丁挂载结果:网格幽灵坐标={0}、按作物补种={1}。未挂上的通常是「没装 PlantEasily」这一正常情况(可忽略);若已安装请检查 PlantEasily 是否加载失败或版本已变化。", _patchedGrid ? "已生效" : "未生效", _patchedReplant ? "已生效" : "未生效")); } } private void PatchGrid(Type ghostGrid) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(ghostGrid, "BuildGrid", (Type[])null, (Type[])null); if (methodInfo == null) { _gridGaveUp = true; L.LogError((object)"找不到 GhostGrid.BuildGrid —— 补丁 1/3 未挂上(PlantEasily 版本可能已变化)"); return; } _gridVersionField = AccessTools.Field(ghostGrid, "_gridVersion"); if (_gridVersionField == null) { _gridGaveUp = true; L.LogError((object)"找不到 GhostGrid._gridVersion —— 补丁 1/3 未挂上(PlantEasily 版本可能已变化)"); return; } ResolveRepositionHandles(ghostGrid); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PlantEasilyFixPlugin), "BuildGridPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patchedGrid = true; if (_getGhostPosition != null && _updateGhostTransform != null && _lastUpdatedField != null) { L.LogInfo((object)"补丁 1/3 已生效:网格重建后强制刷新幽灵坐标,并当场补摆全部网格格位(避免大网格下部分幽灵叠在同一点)。"); } else { L.LogInfo((object)"补丁 1/3 已生效:网格重建后强制刷新幽灵坐标。(补摆所需的 PlantEasily 内部方法未全部找到,大网格补摆已降级关闭;若仍出现重叠请回报版本号。)"); } } private static bool RequireArity(MethodInfo method, int expected, bool hasInstance, string label) { if (method == null) { L.LogWarning((object)("补摆降级:未找到 " + label)); return false; } int num = method.GetParameters().Length; if (num != expected) { L.LogError((object)$"补摆降级:{label} 的参数个数不符 —— PlantEasily 给的是 {num} 个,本补丁按 {expected} 个调用;继续调用会抛 TargetParameterCountException 并被静默吞掉。已停用大网格补摆(补丁 1/2 不受影响)。请把 PlantEasily 版本号回报给补丁作者。"); return false; } if (!method.IsStatic && !hasInstance) { L.LogError((object)$"补摆降级:{label} 是**实例**成员,但调用时没有 target 实例;继续调用会抛 TargetException(Non-static method requires a target.)并被静默吞掉。已停用大网格补摆(补丁 1/2 不受影响)。请把 PlantEasily 版本号回报给补丁作者。"); return false; } return true; } private static void ResolveRepositionHandles(Type ghostGrid) { try { _extraGhostsField = AccessTools.Field(ghostGrid, "ExtraGhosts"); if (_extraGhostsField == null) { L.LogWarning((object)"补摆降级:未找到 GhostGrid.ExtraGhosts"); } _maxActiveGhostsGetter = AccessTools.PropertyGetter(ghostGrid, "MaxActiveGhosts"); if (_maxActiveGhostsGetter == null) { _maxActiveGhostsGetter = AccessTools.Method(ghostGrid, "get_MaxActiveGhosts", (Type[])null, (Type[])null); } if (!RequireArity(_maxActiveGhostsGetter, 0, hasInstance: false, "GhostGrid.MaxActiveGhosts")) { _maxActiveGhostsGetter = null; } Type type = AccessTools.TypeByName("Advize_PlantEasily.ModContext"); if (type != null) { _modConfigInstanceField = AccessTools.Field(type, "config"); } if (_modConfigInstanceField == null) { L.LogWarning((object)"补摆降级:未找到 ModContext.config(拿不到 ModConfig 实例)"); } Type type2 = AccessTools.TypeByName("Advize_PlantEasily.ModConfig"); if (type2 != null) { _columnsGetter = AccessTools.PropertyGetter(type2, "Columns"); } if (!RequireArity(_columnsGetter, 0, _modConfigInstanceField != null, "ModConfig.Columns")) { _columnsGetter = null; } _getGhostObject = AccessTools.Method(ghostGrid, "GetGhostObject", (Type[])null, (Type[])null); if (!RequireArity(_getGhostObject, 1, hasInstance: false, "GhostGrid.GetGhostObject")) { _getGhostObject = null; } _getGhostCache = AccessTools.Method(ghostGrid, "GetGhostCache", (Type[])null, (Type[])null); if (!RequireArity(_getGhostCache, 1, hasInstance: false, "GhostGrid.GetGhostCache")) { _getGhostCache = null; } _getGhostPosition = AccessTools.Method(ghostGrid, "GetGhostPosition", (Type[])null, (Type[])null); if (!RequireArity(_getGhostPosition, 3, hasInstance: false, "GhostGrid.GetGhostPosition")) { _getGhostPosition = null; } _updateGhostTransform = AccessTools.Method(ghostGrid, "UpdateGhostTransform", (Type[])null, (Type[])null); if (!RequireArity(_updateGhostTransform, 2, hasInstance: false, "GhostGrid.UpdateGhostTransform")) { _updateGhostTransform = null; } Type type3 = AccessTools.TypeByName("Advize_PlantEasily.GhostCache"); if (type3 != null) { _lastUpdatedField = AccessTools.Field(type3, "lastUpdatedVersion"); } if (_lastUpdatedField == null) { L.LogWarning((object)"补摆降级:未找到 GhostCache.lastUpdatedVersion"); } } catch (Exception ex) { L.LogError((object)("解析补摆所需的 PlantEasily 成员时异常(补摆将降级关闭):" + ex.Message)); } } internal static void BuildGridPostfix() { try { if (_gridVersionField == null) { return; } int num = (int)_gridVersionField.GetValue(null); _gridVersionField.SetValue(null, num + 1); _fixCount++; if (VerboseLog != null && VerboseLog.Value) { L.LogInfo((object)$"[修复 {_fixCount}] BuildGrid → _gridVersion {num} → {num + 1}(幽灵坐标缓存已失效)"); } } catch (Exception ex) { L.LogError((object)("修正网格版本号失败(本次不影响游戏,重叠可能复现):" + ex.Message)); } RepositionAllGhosts(_fixCount.ToString()); } private static void RepositionAllGhosts(string tag) { if (_getGhostPosition == null || _updateGhostTransform == null || _lastUpdatedField == null || _getGhostObject == null || _getGhostCache == null || _maxActiveGhostsGetter == null || _columnsGetter == null || _modConfigInstanceField == null) { return; } try { object value = _modConfigInstanceField.GetValue(null); if (value == null) { return; } int num = (int)_maxActiveGhostsGetter.Invoke(null, null); int num2 = (int)_columnsGetter.Invoke(value, null); if (num <= 0 || num2 <= 0) { return; } int num3 = ((_gridVersionField != null) ? ((int)_gridVersionField.GetValue(null)) : 0); int num4 = 0; int num5 = 0; for (int i = 1; i <= num; i++) { object? obj = _getGhostObject.Invoke(null, new object[1] { i }); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { continue; } int num6 = i / num2; int num7 = i % num2; object obj2 = _getGhostPosition.Invoke(null, new object[3] { num6, num7, i }); if (obj2 != null) { _updateGhostTransform.Invoke(null, new object[2] { val, obj2 }); num4++; object obj3 = _getGhostCache.Invoke(null, new object[1] { val }); if (obj3 != null) { _lastUpdatedField.SetValue(obj3, num3); num5++; } } } _repositionTotal += num4; _repositionCalls++; if (_repositionCalls == 1 || (VerboseLog != null && VerboseLog.Value)) { L.LogInfo((object)$"[补摆 {tag}] 网格 {num + 1} 格(MaxActiveGhosts={num}, Columns={num2})→ 已摆正 {num4} 个幽灵、同步 {num5} 个坐标缓存;累计补摆 {_repositionCalls} 次 / {_repositionTotal} 个。"); } } catch (Exception ex) { L.LogError((object)("补摆幽灵坐标失败(本次退回原分批节奏,重叠可能复现):" + ex.Message)); } } private void PatchReplant(Type placementState) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(placementState, "SetReferences", (Type[])null, (Type[])null); if (methodInfo == null) { _replantGaveUp = true; L.LogError((object)"找不到 PlacementState.SetReferences —— 补丁 2 未挂上(PlantEasily 版本可能已变化)"); return; } _lastSelectedField = AccessTools.Field(placementState, "LastSelectedPlantName"); if (_lastSelectedField == null) { _replantGaveUp = true; L.LogError((object)"找不到 PlacementState.LastSelectedPlantName —— 补丁 2 未挂上(PlantEasily 版本可能已变化)"); } else { _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PlantEasilyFixPlugin), "SetReferencesPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patchedReplant = true; L.LogInfo((object)"补丁 2/3 已生效:自动补种将按【被收获的那种作物】进行(原行为是统一补成最近选中的那一种)。"); } } internal static void SetReferencesPostfix() { try { if ((SameCropReplant != null && !SameCropReplant.Value) || _lastSelectedField == null) { return; } object value = _lastSelectedField.GetValue(null); if (value != null) { _lastSelectedField.SetValue(null, null); _replantOverrideCount++; if (_replantOverrideCount == 1) { L.LogInfo((object)$"首次拦截成功:LastSelectedPlantName「{value}」→ 置空,此后补种按实际收获的作物进行。"); } else if (VerboseLog != null && VerboseLog.Value) { L.LogInfo((object)$"[补种修正 {_replantOverrideCount}] LastSelectedPlantName「{value}」→ 置空"); } } } catch (Exception ex) { L.LogError((object)("压制补种覆盖失败(本次补种可能仍沿用原行为):" + ex.Message)); } } } }