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 AutoExtractionPoint v1.0.0
Zichen-AutoExtractionPoint.dll
Decompiled 14 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.Configuration; 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("Zichen-AutoExtractionPoint")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+dc375af9d5c35b5e6a48e905223c04d40e17b965")] [assembly: AssemblyProduct("Zichen-AutoExtractionPoint")] [assembly: AssemblyTitle("Zichen-AutoExtractionPoint")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } 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; } } } [BepInPlugin("zichen.autoextractionpoint", "A.Auto Extraction Point", "1.0.0")] public sealed class WzcAutoExtractionPointPlugin : BaseUnityPlugin { public const string PluginGuid = "zichen.autoextractionpoint"; public const string PluginName = "A.Auto Extraction Point"; public const string PluginVersion = "1.0.0"; private const string InfoSection = "模组信息"; private const string FeatureSection = "A.自动开启提取点"; private const string PriorityFarthest = "最远"; private const string PriorityNearest = "最近"; private static readonly FieldInfo RoundDirectorExtractionPointListField = typeof(RoundDirector).GetField("extractionPointList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorExtractionPointActiveField = typeof(RoundDirector).GetField("extractionPointActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorExtractionPointsCompletedField = typeof(RoundDirector).GetField("extractionPointsCompleted", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorExtractionPointsField = typeof(RoundDirector).GetField("extractionPoints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorAllExtractionPointsCompletedField = typeof(RoundDirector).GetField("allExtractionPointsCompleted", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorExtractionPointCurrentField = typeof(RoundDirector).GetField("extractionPointCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ExtractionPointCurrentStateField = typeof(ExtractionPoint).GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ExtractionPointIsShopField = typeof(ExtractionPoint).GetField("isShop", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ExtractionPointIsLockedField = typeof(ExtractionPoint).GetField("isLocked", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo ExtractionPointOnClickMethod = typeof(ExtractionPoint).GetMethod("OnClick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private readonly Dictionary<int, float> extractionDistanceMap = new Dictionary<int, float>(); private ConfigEntry<string> moduleNameInfo; private ConfigEntry<string> moduleVersionInfo; private ConfigEntry<string> contactInfo; private ConfigEntry<bool> featureEnabled; private ConfigEntry<string> priorityMode; private Harmony harmony; private RoundDirector lastRoundDirector; private bool firstExtractionPointCaptured; private Vector3 firstExtractionPointPosition; private bool activationQueued; private ExtractionPoint queuedExtractionPoint; private float queuedActivationTime; private float nextAutoScanTime; private const float AutoScanInterval = 0.75f; private const float QueuedActivationDelay = 0.35f; public static WzcAutoExtractionPointPlugin Instance { get; private set; } private void Awake() { Instance = this; BindConfig(); ApplyPatches(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"zichen-auto-extraction-point loaded."); } private void Update() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)RoundDirector.instance != (Object)(object)lastRoundDirector) { lastRoundDirector = RoundDirector.instance; ResetRuntimeState(); } if (!IsHostAuthority()) { return; } if (!IsFeatureEnabled()) { ResetQueuedActivation(); } else if ((Object)(object)RoundDirector.instance == (Object)null || !SemiFunc.RunIsLevel()) { ResetQueuedActivation(); } else if (!activationQueued) { TryAutoQueueNextExtractionPoint(); } else { if (Time.time < queuedActivationTime || GetExtractionPointActive(RoundDirector.instance) || GetAllExtractionPointsCompleted(RoundDirector.instance)) { return; } ExtractionPoint val = queuedExtractionPoint; ResetQueuedActivation(); if (!((Object)(object)val == (Object)null)) { State val3 = (State)((ExtractionPointCurrentStateField?.GetValue(val) is State val2) ? ((int)val2) : 0); object obj = ExtractionPointIsLockedField?.GetValue(val); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0; try { ExtractionPointOnClickMethod?.Invoke(val, null); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Auto activated next extraction point via native OnClick. Candidate={((Object)val).name}, State={val3}, Locked={flag2}"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to auto activate next extraction point: " + ex.GetType().Name + ": " + ex.Message)); } } } } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } if (Instance == this) { Instance = null; } } private void BindConfig() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown moduleNameInfo = ((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组名称", "Zichen_自动开启提取点", new ConfigDescription("当前模组的中文名称。此处仅用于显示,不影响功能。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1000, CustomDrawer = DrawInfo, ReadOnly = true } })); moduleNameInfo.Value = "Auto Extraction Point / 自动开启提取点"; moduleVersionInfo = ((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组版本号", "1.0.0", new ConfigDescription("当前模组版本号。此处仅用于显示,不影响功能。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 990, CustomDrawer = DrawInfo, ReadOnly = true } })); moduleVersionInfo.Value = "1.0.0"; contactInfo = ((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "REPO交流QQ群", "824639225", new ConfigDescription("REPO 游戏交流、BUG 反馈、优化建议、功能请求请加 QQ 群。此处仅用于显示,不影响功能。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 980, CustomDrawer = DrawInfo, ReadOnly = true } })); contactInfo.Value = "824639225"; featureEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("A.自动开启提取点", "启用", true, ConfigDescriptionWithOrder("只需主机安装即可生效。第一个提取点仍然手动开启,完成后自动开启下一个提取点。", 900)); priorityMode = ((BaseUnityPlugin)this).Config.Bind<string>("A.自动开启提取点", "打开提取点优先", "最远", new ConfigDescription("以第一个手动开启的提取点作为距离映射原点,后续自动开启下一个提取点时按最远或最近优先。默认最远。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "最远", "最近" }), new object[1] { new ConfigurationManagerAttributes { Order = 890 } })); } private void ApplyPatches() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown harmony = new Harmony("zichen.autoextractionpoint.patch"); MethodInfo methodInfo = AccessTools.Method(typeof(RoundDirector), "ExtractionPointsUnlockRPC", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(ExtractionPoint), "OnClick", (Type[])null, (Type[])null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(WzcAutoExtractionPointPlugin), "ExtractionPointOnClickPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(WzcAutoExtractionPointPlugin), "ExtractionPointsUnlockRpcPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private bool IsFeatureEnabled() { if (featureEnabled != null) { return featureEnabled.Value; } return false; } private static bool IsHostAuthority() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return false; } } private void ResetRuntimeState() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) extractionDistanceMap.Clear(); firstExtractionPointCaptured = false; firstExtractionPointPosition = Vector3.zero; ResetQueuedActivation(); nextAutoScanTime = 0f; } private void ResetQueuedActivation() { activationQueued = false; queuedExtractionPoint = null; queuedActivationTime = 0f; } private void TryAutoQueueNextExtractionPoint() { if ((Object)(object)RoundDirector.instance == (Object)null || Time.time < nextAutoScanTime) { return; } nextAutoScanTime = Time.time + 0.75f; if (firstExtractionPointCaptured) { int extractionPointsCompleted = GetExtractionPointsCompleted(RoundDirector.instance); int extractionPointsTotal = GetExtractionPointsTotal(RoundDirector.instance); if (extractionPointsCompleted > 0 && extractionPointsTotal > 0 && extractionPointsCompleted < extractionPointsTotal && !GetAllExtractionPointsCompleted(RoundDirector.instance) && !GetExtractionPointActive(RoundDirector.instance)) { QueueNextExtractionPointActivation(fromUnlockEvent: false); } } } private void CaptureFirstExtractionPoint(ExtractionPoint extractionPoint) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!firstExtractionPointCaptured && !((Object)(object)extractionPoint == (Object)null)) { firstExtractionPointCaptured = true; firstExtractionPointPosition = ((Component)extractionPoint).transform.position; RebuildDistanceMap(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Captured first manual extraction point as distance origin."); } } private void RebuildDistanceMap() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) extractionDistanceMap.Clear(); List<ExtractionPoint> extractionPoints = GetExtractionPoints(); for (int i = 0; i < extractionPoints.Count; i++) { ExtractionPoint val = extractionPoints[i]; if (!((Object)(object)val == (Object)null) && !IsShopExtractionPoint(val)) { extractionDistanceMap[((Object)val).GetInstanceID()] = Vector3.Distance(firstExtractionPointPosition, ((Component)val).transform.position); } } } private List<ExtractionPoint> GetExtractionPoints() { List<ExtractionPoint> list = new List<ExtractionPoint>(); if ((Object)(object)RoundDirector.instance == (Object)null || !(RoundDirectorExtractionPointListField?.GetValue(RoundDirector.instance) is List<GameObject> list2)) { return list; } for (int i = 0; i < list2.Count; i++) { GameObject val = list2[i]; if (!((Object)(object)val == (Object)null)) { ExtractionPoint component = val.GetComponent<ExtractionPoint>(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } return list; } private ExtractionPoint ChooseNextExtractionPoint() { List<ExtractionPoint> extractionPoints = GetExtractionPoints(); ExtractionPoint val = null; float num = 0f; bool flag = string.Equals(priorityMode?.Value, "最近", StringComparison.Ordinal); for (int i = 0; i < extractionPoints.Count; i++) { ExtractionPoint val2 = extractionPoints[i]; if (!IsCandidateExtractionPoint(val2)) { continue; } float mappedDistance = GetMappedDistance(val2); if ((Object)(object)val == (Object)null) { val = val2; num = mappedDistance; } else if (flag) { if (mappedDistance < num) { val = val2; num = mappedDistance; } } else if (mappedDistance > num) { val = val2; num = mappedDistance; } } return val; } private bool IsCandidateExtractionPoint(ExtractionPoint extractionPoint) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //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_003b: Invalid comparison between Unknown and I4 if ((Object)(object)extractionPoint == (Object)null || IsShopExtractionPoint(extractionPoint)) { return false; } if (!(ExtractionPointCurrentStateField?.GetValue(extractionPoint) is State val)) { return false; } return (int)val == 1; } private float GetMappedDistance(ExtractionPoint extractionPoint) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)extractionPoint == (Object)null) { return float.MaxValue; } int instanceID = ((Object)extractionPoint).GetInstanceID(); if (extractionDistanceMap.TryGetValue(instanceID, out var value)) { return value; } value = Vector3.Distance(firstExtractionPointPosition, ((Component)extractionPoint).transform.position); extractionDistanceMap[instanceID] = value; return value; } private bool GetExtractionPointActive(RoundDirector roundDirector) { bool flag = default(bool); int num; if ((Object)(object)roundDirector != (Object)null && RoundDirectorExtractionPointActiveField != null) { object value = RoundDirectorExtractionPointActiveField.GetValue(roundDirector); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private int GetExtractionPointsCompleted(RoundDirector roundDirector) { if ((Object)(object)roundDirector != (Object)null) { object obj = RoundDirectorExtractionPointsCompletedField?.GetValue(roundDirector); if (obj is int) { return (int)obj; } } return 0; } private int GetExtractionPointsTotal(RoundDirector roundDirector) { if ((Object)(object)roundDirector != (Object)null && RoundDirectorExtractionPointsField?.GetValue(roundDirector) is int num && num > 0) { return num; } int num2 = 0; List<ExtractionPoint> extractionPoints = GetExtractionPoints(); for (int i = 0; i < extractionPoints.Count; i++) { if ((Object)(object)extractionPoints[i] != (Object)null) { num2++; } } return num2; } private bool GetAllExtractionPointsCompleted(RoundDirector roundDirector) { bool flag = default(bool); int num; if ((Object)(object)roundDirector != (Object)null && RoundDirectorAllExtractionPointsCompletedField != null) { object value = RoundDirectorAllExtractionPointsCompletedField.GetValue(roundDirector); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool IsShopExtractionPoint(ExtractionPoint extractionPoint) { bool flag = default(bool); int num; if ((Object)(object)extractionPoint != (Object)null && ExtractionPointIsShopField != null) { object value = ExtractionPointIsShopField.GetValue(extractionPoint); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private void QueueNextExtractionPointActivation(bool fromUnlockEvent) { if (!firstExtractionPointCaptured || (Object)(object)RoundDirector.instance == (Object)null) { return; } ExtractionPoint val = ChooseNextExtractionPoint(); if (!((Object)(object)val == (Object)null)) { if (ExtractionPointOnClickMethod == null) { float mappedDistance = GetMappedDistance(val); ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed to queue next extraction point because native OnClick method was unavailable. Candidate={((Object)val).name}, Distance={mappedDistance:0.##}"); } else if (!activationQueued || !((Object)(object)queuedExtractionPoint == (Object)(object)val)) { queuedExtractionPoint = val; queuedActivationTime = Time.time + 0.35f; activationQueued = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Queued next extraction point auto activation. Source={0}, Priority={1}, Candidate={2}, Distance={3:0.##}", fromUnlockEvent ? "UnlockEvent" : "PeriodicScan", priorityMode?.Value, ((Object)val).name, GetMappedDistance(val))); } } } private void DrawInfo(ConfigEntryBase entry) { GUILayout.Label(entry.BoxedValue?.ToString() ?? string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) }); } private static ConfigDescription ConfigDescriptionWithOrder(string description, int order) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = order } }); } private static void ExtractionPointOnClickPostfix(ExtractionPoint __instance) { WzcAutoExtractionPointPlugin instance = Instance; if (!((Object)(object)instance == (Object)null) && instance.IsFeatureEnabled() && IsHostAuthority() && !((Object)(object)__instance == (Object)null) && !((Object)(object)RoundDirector.instance == (Object)null) && SemiFunc.RunIsLevel() && !instance.firstExtractionPointCaptured && instance.GetExtractionPointsCompleted(RoundDirector.instance) <= 0) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)"ExtractionPoint.OnClick observed on first extraction point candidate."); instance.CaptureFirstExtractionPoint(__instance); } } private static void ExtractionPointsUnlockRpcPostfix(RoundDirector __instance) { WzcAutoExtractionPointPlugin instance = Instance; if (!((Object)(object)instance == (Object)null) && instance.IsFeatureEnabled() && IsHostAuthority() && !((Object)(object)__instance == (Object)null) && SemiFunc.RunIsLevel()) { int extractionPointsCompleted = instance.GetExtractionPointsCompleted(__instance); int extractionPointsTotal = instance.GetExtractionPointsTotal(__instance); bool allExtractionPointsCompleted = instance.GetAllExtractionPointsCompleted(__instance); ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Extraction points unlocked. Completed={extractionPointsCompleted}, Total={extractionPointsTotal}, Active={instance.GetExtractionPointActive(__instance)}, AllCompleted={allExtractionPointsCompleted}"); if (!(extractionPointsCompleted <= 0 || extractionPointsTotal <= 0 || extractionPointsCompleted >= extractionPointsTotal || allExtractionPointsCompleted)) { instance.QueueNextExtractionPointActivation(fromUnlockEvent: true); } } } } internal sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; }