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 RemoveAllCosmetics v1.0.0
Zichen-RemoveAllCosmetics-1.0.0.dll
Decompiled 11 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; 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-RemoveAllCosmetics-1.0.0")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+78877d59e6688a3c44dc2491e364ee0e0878e78d")] [assembly: AssemblyProduct("Zichen-RemoveAllCosmetics-1.0.0")] [assembly: AssemblyTitle("Zichen-RemoveAllCosmetics-1.0.0")] [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; } } } namespace Zichen_RemoveAllCosmetics { [BepInPlugin("zichen.removeallcosmetics", "RemoveAllCosmetics", "1.0.0")] public class Plugin : BaseUnityPlugin { private sealed class CompatibilityReport { private readonly List<string> affectedFeatures = new List<string>(); private readonly List<string> details = new List<string>(); public bool AutomaticRemovalAvailable = true; public bool VisualFilterAvailable = true; public bool VisualRefreshAvailable = true; public bool ResultPopupAvailable = true; public bool HasIssues => affectedFeatures.Count > 0; public static CompatibilityReport CreateHealthy() { return new CompatibilityReport(); } public static CompatibilityReport Build() { CompatibilityReport compatibilityReport = new CompatibilityReport(); if ((1u & (RequireField(MetaManagerInstanceField, "MetaManager.instance", compatibilityReport, "启动自动清理") ? 1u : 0u) & (RequireField(MetaSaveReadyField, "MetaManager.saveReady", compatibilityReport, "启动自动清理") ? 1u : 0u) & (RequireField(MetaSavePathField, "MetaManager.savePath", compatibilityReport, "装饰存档写回") ? 1u : 0u) & (RequireField(MetaCosmeticTokensField, "MetaManager.cosmeticTokens", compatibilityReport, "装饰硬币保留") ? 1u : 0u) & (RequireField(MetaCosmeticUnlocksField, "MetaManager.cosmeticUnlocks", compatibilityReport, "解锁装饰清理") ? 1u : 0u) & (RequireField(MetaCosmeticHistoryField, "MetaManager.cosmeticHistory", compatibilityReport, "历史装饰清理") ? 1u : 0u) & (RequireField(MetaCosmeticEquippedField, "MetaManager.cosmeticEquipped", compatibilityReport, "已装备装饰清理") ? 1u : 0u) & (RequireField(MetaCosmeticPresetsField, "MetaManager.cosmeticPresets", compatibilityReport, "装饰预设清理") ? 1u : 0u) & (RequireField(MetaColorPresetsField, "MetaManager.colorPresets", compatibilityReport, "装饰颜色预设清理") ? 1u : 0u) & (RequireField(MetaColorsEquippedField, "MetaManager.colorsEquipped", compatibilityReport, "装饰颜色重置") ? 1u : 0u) & (RequireField(MetaCosmeticAssetsField, "MetaManager.cosmeticAssets", compatibilityReport, "装饰资源索引匹配") ? 1u : 0u) & (RequireField(CosmeticAssetTypeField, "CosmeticAsset.type", compatibilityReport, "装饰类型识别") ? 1u : 0u) & (RequireField(StatsManagerInstanceField, "StatsManager.instance", compatibilityReport, "装饰存档加密写回") ? 1u : 0u) & (RequireField(StatsManagerPasswordField, "StatsManager.totallyNormalString", compatibilityReport, "装饰存档加密写回") ? 1u : 0u)) == 0) { compatibilityReport.AutomaticRemovalAvailable = false; } if (!RequireField(MetaPresetSlotsField, "MetaManager.presetSlots", compatibilityReport, "装饰预设槽数量读取")) { compatibilityReport.details.Add("MetaManager.presetSlots missing; fallback preset slot count 28 will be used."); } if ((1u & (RequireMethod(PlayerCosmeticsSetupCosmeticsLogicMethod, "PlayerCosmetics.SetupCosmeticsLogic(int[], bool)", compatibilityReport, "视觉层装饰过滤") ? 1u : 0u) & (RequireField(MetaCosmeticAssetsField, "MetaManager.cosmeticAssets", compatibilityReport, "视觉层装饰过滤") ? 1u : 0u) & (RequireField(CosmeticAssetTypeField, "CosmeticAsset.type", compatibilityReport, "视觉层装饰过滤") ? 1u : 0u)) == 0) { compatibilityReport.VisualFilterAvailable = false; } if ((1u & (RequireMethod(MetaCosmeticPreviewSetMethod, "MetaManager.CosmeticPreviewSet(bool)", compatibilityReport, "清理后视觉刷新") ? 1u : 0u) & (RequireMethod(MetaCosmeticPlayerUpdateLocalMethod, "MetaManager.CosmeticPlayerUpdateLocal(bool, bool)", compatibilityReport, "清理后视觉刷新") ? 1u : 0u) & (RequireMethod(PlayerCosmeticsSetupCosmeticsMethod, "PlayerCosmetics.SetupCosmetics(bool, bool, List<int>)", compatibilityReport, "清理后视觉刷新") ? 1u : 0u) & (RequireMethod(PlayerCosmeticsSetupColorsMethod, "PlayerCosmetics.SetupColors(bool, int[])", compatibilityReport, "清理后视觉刷新") ? 1u : 0u)) == 0) { compatibilityReport.VisualRefreshAvailable = false; } if ((1u & (RequireField(MenuManagerInstanceField, "MenuManager.instance", compatibilityReport, "启动结果弹窗") ? 1u : 0u) & (RequireField(MenuManagerCurrentMenuPageField, "MenuManager.currentMenuPage", compatibilityReport, "启动结果弹窗") ? 1u : 0u) & (RequireField(MenuManagerPagePopUpScheduledField, "MenuManager.pagePopUpScheduled", compatibilityReport, "启动结果弹窗") ? 1u : 0u) & (RequireField(MenuManagerCurrentMenuPageIndexField, "MenuManager.currentMenuPageIndex", compatibilityReport, "启动结果弹窗") ? 1u : 0u) & (RequireMethod(MenuManagerPagePopUpMethod, "MenuManager.PagePopUp(string, Color, string, string, bool)", compatibilityReport, "启动结果弹窗") ? 1u : 0u)) == 0) { compatibilityReport.ResultPopupAvailable = false; } return compatibilityReport; } public void AddPatchFailure(string featureName, string patchName, string reason) { AddAffectedFeature(featureName); details.Add("Patch failed: " + patchName + " -> " + reason); } public string BuildLogMessage() { if (!HasIssues) { return "Compatibility self-check passed."; } return "Compatibility self-check found possible game API changes. Affected features: " + string.Join(";", affectedFeatures.Distinct().ToArray()); } public string BuildPopupMessage() { if (!HasIssues) { return null; } string text = "检测到游戏接口可能已变化,RemoveAllCosmetics 已进入兼容模式。\n以下功能可能不可用:"; foreach (string item in affectedFeatures.Distinct().Take(6)) { text = text + "\n- " + item; } text += "\n\n为避免损坏存档,缺少关键接口时不会执行清理。"; return text + "\n如需使用这些功能,请等待作者适配最新版本。"; } public string BuildPopupAppendix() { if (!HasIssues) { return null; } string text = "兼容提示:检测到部分游戏接口可能已变化。"; foreach (string item in affectedFeatures.Distinct().Take(4)) { text = text + "\n- " + item; } return text + "\n如清理结果异常,请等待作者适配最新版本。"; } public IEnumerable<string> GetDetailMessages() { return details.Distinct().ToArray(); } private static bool RequireField(FieldInfo field, string apiName, CompatibilityReport report, string affectedFeature) { if (field != null) { return true; } report.AddAffectedFeature(affectedFeature); report.details.Add("Missing field: " + apiName); return false; } private static bool RequireMethod(MethodInfo method, string apiName, CompatibilityReport report, string affectedFeature) { if (method != null) { return true; } report.AddAffectedFeature(affectedFeature); report.details.Add("Missing method: " + apiName); return false; } private void AddAffectedFeature(string feature) { if (!affectedFeatures.Contains(feature)) { affectedFeatures.Add(feature); } } } private sealed class CosmeticSaveData { public string SavePath; public List<int> Tokens; public List<int> Unlocks; public List<int> History; public List<int> Equipped; public List<List<int>> CosmeticPresets; public List<List<int>> ColorPresets; public int[] Colors; public List<CosmeticAsset> Assets; } [Serializable] private sealed class ExtBackup { public List<int> cosmeticUnlocks = new List<int>(); public List<int> cosmeticEquipped = new List<int>(); public List<int> colorsEquipped = new List<int>(); } [CompilerGenerated] private sealed class <NukeCosmetics>d__52 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private MetaManager <meta>5__2; private bool <saveReady>5__3; private float <deadline>5__4; private int <i>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NukeCosmetics>d__52(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <meta>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; Plugin plugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <meta>5__2 = null; <saveReady>5__3 = false; <deadline>5__4 = Time.unscaledTime + 60f; goto IL_009c; case 1: <>1__state = -1; goto IL_009c; case 2: { <>1__state = -1; <i>5__5++; break; } IL_009c: if (Time.unscaledTime < <deadline>5__4) { <meta>5__2 = GetMetaManagerInstance(); if (!(((Object)(object)<meta>5__2 != (Object)null && TryGetFieldValue<bool>(MetaSaveReadyField, <meta>5__2, out <saveReady>5__3)) & <saveReady>5__3)) { <>2__current = null; <>1__state = 1; return true; } } if ((Object)(object)<meta>5__2 == (Object)null || !<saveReady>5__3) { plugin.ShowRemovalFailure("等待游戏装饰存档就绪超时,本次未执行清理。"); return false; } <i>5__5 = 0; break; } if (<i>5__5 < 10) { <>2__current = null; <>1__state = 2; return true; } <meta>5__2 = GetMetaManagerInstance(); if ((Object)(object)<meta>5__2 == (Object)null) { plugin.ShowRemovalFailure("MetaManager 在清理前失效,本次未执行清理。"); return false; } if (!TryGetEncryptionPassword(out var encryptionPassword)) { plugin.ShowRemovalFailure("无法读取游戏存档加密密码,本次未修改装饰存档。"); return false; } if (!TryReadCosmeticSaveData(<meta>5__2, out var data, out var error)) { plugin.ShowRemovalFailure(error); return false; } ((BaseUnityPlugin)plugin).Logger.LogInfo((object)"=== RemoveAllCosmetics START ==="); int num2 = RemoveMatchingCosmeticIndexes(data.Unlocks, data.Assets, AllRemovalTypes); int num3 = RemoveMatchingCosmeticIndexes(data.History, data.Assets, AllRemovalTypes); int num4 = RemoveMatchingCosmeticIndexesFromPresets(data.CosmeticPresets, data.Assets, AllRemovalTypes); ResetColorsForTypes(data.Colors, AllRemovalTypes); ResetColorPresetsForTypes(data.ColorPresets, AllRemovalTypes); int num5 = RemoveMatchingCosmeticIndexes(data.Equipped, data.Assets, AllRemovalTypes); List<int> finalEquipped = data.Equipped ?? new List<int>(); int[] finalColors = data.Colors ?? CreateEmptyColorsArray(); int presetSlotCount = GetPresetSlotCount(<meta>5__2); bool flag = plugin.WriteVanillaMetaSave(data, finalEquipped, finalColors, presetSlotCount, encryptionPassword); bool flag2 = plugin.WriteModdedMetaSave(data.SavePath, finalColors, presetSlotCount, encryptionPassword); plugin.SyncUnlockAllCosmeticsBackup(finalEquipped, finalColors); plugin.RefreshCosmeticVisuals(<meta>5__2); ((BaseUnityPlugin)plugin).Logger.LogInfo((object)("=== RemoveAllCosmetics DONE === " + $"equipped={num5}, unlocks={num2}, history={num3}, presetItems={num4}, " + $"tokensKept={data.Tokens?.Count ?? 0}, vanillaSaved={flag}, moddedSaved={flag2}")); string text = (flag ? "已移除全部装饰并保存\n" : "已尝试移除全部装饰,但写入存档失败\n"); text += "本模组每次启动游戏都会移除全部装饰。\n"; text += "如不需要此功能,请卸载本模组。\n"; text += "已保留装饰硬币。\n"; text += $"已装备移除:{num5}件 解锁:{num2} 历史:{num3} 预设:{num4}项"; if (!flag) { text += "\n请查看 BepInEx 日志,确认存档是否被其他程序占用或游戏接口是否已变化。"; } string text2 = _compatibilityReport.BuildPopupAppendix(); if (!string.IsNullOrWhiteSpace(text2)) { text = text + "\n\n" + text2; } Color color = ((_compatibilityReport.HasIssues || !flag) ? Color.yellow : Color.green); TryShowPopup("移除全部装饰", color, text); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <WaitAndShowPopup>d__82 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitAndShowPopup>d__82(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_013a; case 1: { <>1__state = -1; MenuManager menuManagerInstance = GetMenuManagerInstance(); if ((Object)(object)menuManagerInstance != (Object)null && !IsPopupSlotBusy(menuManagerInstance)) { try { Plugin instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)"Showing popup after menu is ready."); } if (!TryInvoke(MenuManagerPagePopUpMethod, menuManagerInstance, _pendingPopupTitle, _pendingPopupColor, _pendingPopupBody, "OK", false)) { _popupWaiting = false; return false; } _popupShown = true; _popupWaiting = false; } catch (Exception ex) { _popupShown = false; _popupWaiting = false; Plugin instance2 = _instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("Failed to show popup: " + ex.Message)); } } return false; } goto IL_0123; } case 2: { <>1__state = -1; goto IL_013a; } IL_013a: if (!_popupShown) { MenuManager menuManagerInstance = GetMenuManagerInstance(); if ((Object)(object)menuManagerInstance != (Object)null && !IsPopupSlotBusy(menuManagerInstance)) { <>2__current = null; <>1__state = 1; return true; } goto IL_0123; } _popupWaiting = false; return false; IL_0123: <>2__current = null; <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "zichen.removeallcosmetics"; public const string PluginName = "RemoveAllCosmetics"; public const string PluginVersion = "1.0.0"; private const int MetaReadyTimeoutSeconds = 60; private const int PostReadyDelayFrames = 10; private static Plugin _instance; private static Harmony _harmony; private static CompatibilityReport _compatibilityReport = CompatibilityReport.CreateHealthy(); private static bool _popupShown; private static bool _popupWaiting; private static string _pendingPopupTitle; private static Color _pendingPopupColor; private static string _pendingPopupBody; private static readonly FieldInfo MetaManagerInstanceField = AccessTools.Field(typeof(MetaManager), "instance"); private static readonly FieldInfo MetaSaveReadyField = AccessTools.Field(typeof(MetaManager), "saveReady"); private static readonly FieldInfo MetaSavePathField = AccessTools.Field(typeof(MetaManager), "savePath"); private static readonly FieldInfo MetaCosmeticTokensField = AccessTools.Field(typeof(MetaManager), "cosmeticTokens"); private static readonly FieldInfo MetaCosmeticUnlocksField = AccessTools.Field(typeof(MetaManager), "cosmeticUnlocks"); private static readonly FieldInfo MetaCosmeticHistoryField = AccessTools.Field(typeof(MetaManager), "cosmeticHistory"); private static readonly FieldInfo MetaCosmeticEquippedField = AccessTools.Field(typeof(MetaManager), "cosmeticEquipped"); private static readonly FieldInfo MetaCosmeticPresetsField = AccessTools.Field(typeof(MetaManager), "cosmeticPresets"); private static readonly FieldInfo MetaColorPresetsField = AccessTools.Field(typeof(MetaManager), "colorPresets"); private static readonly FieldInfo MetaColorsEquippedField = AccessTools.Field(typeof(MetaManager), "colorsEquipped"); private static readonly FieldInfo MetaCosmeticAssetsField = AccessTools.Field(typeof(MetaManager), "cosmeticAssets"); private static readonly FieldInfo MetaPresetSlotsField = AccessTools.Field(typeof(MetaManager), "presetSlots"); private static readonly FieldInfo CosmeticAssetTypeField = AccessTools.Field(typeof(CosmeticAsset), "type"); private static readonly FieldInfo StatsManagerInstanceField = AccessTools.Field(typeof(StatsManager), "instance"); private static readonly FieldInfo StatsManagerPasswordField = AccessTools.Field(typeof(StatsManager), "totallyNormalString"); private static readonly FieldInfo MenuManagerInstanceField = AccessTools.Field(typeof(MenuManager), "instance"); private static readonly FieldInfo MenuManagerPagePopUpScheduledField = AccessTools.Field(typeof(MenuManager), "pagePopUpScheduled"); private static readonly FieldInfo MenuManagerCurrentMenuPageIndexField = AccessTools.Field(typeof(MenuManager), "currentMenuPageIndex"); private static readonly FieldInfo MenuManagerCurrentMenuPageField = AccessTools.Field(typeof(MenuManager), "currentMenuPage"); private static readonly MethodInfo PlayerCosmeticsSetupCosmeticsLogicMethod = AccessTools.Method(typeof(PlayerCosmetics), "SetupCosmeticsLogic", new Type[2] { typeof(int[]), typeof(bool) }, (Type[])null); private static readonly MethodInfo PlayerCosmeticsSetupCosmeticsMethod = AccessTools.Method(typeof(PlayerCosmetics), "SetupCosmetics", new Type[3] { typeof(bool), typeof(bool), typeof(List<int>) }, (Type[])null); private static readonly MethodInfo PlayerCosmeticsSetupColorsMethod = AccessTools.Method(typeof(PlayerCosmetics), "SetupColors", new Type[2] { typeof(bool), typeof(int[]) }, (Type[])null); private static readonly MethodInfo MetaCosmeticPreviewSetMethod = AccessTools.Method(typeof(MetaManager), "CosmeticPreviewSet", new Type[1] { typeof(bool) }, (Type[])null); private static readonly MethodInfo MetaCosmeticPlayerUpdateLocalMethod = AccessTools.Method(typeof(MetaManager), "CosmeticPlayerUpdateLocal", new Type[2] { typeof(bool), typeof(bool) }, (Type[])null); private static readonly MethodInfo MenuManagerPagePopUpMethod = AccessTools.Method(typeof(MenuManager), "PagePopUp", new Type[5] { typeof(string), typeof(Color), typeof(string), typeof(string), typeof(bool) }, (Type[])null); private static readonly MethodInfo SetupCosmeticsLogicPrefixMethod = AccessTools.Method(typeof(Plugin), "SetupCosmeticsLogic_Prefix", (Type[])null, (Type[])null); private static readonly HashSet<CosmeticType> HeadTypes = new HashSet<CosmeticType> { (CosmeticType)0, (CosmeticType)5, (CosmeticType)6, (CosmeticType)14, (CosmeticType)15, (CosmeticType)17, (CosmeticType)18, (CosmeticType)24, (CosmeticType)25, (CosmeticType)30, (CosmeticType)31, (CosmeticType)32 }; private static readonly HashSet<CosmeticType> BodyTypes = new HashSet<CosmeticType> { (CosmeticType)7, (CosmeticType)8, (CosmeticType)16, (CosmeticType)20, (CosmeticType)21, (CosmeticType)23 }; private static readonly HashSet<CosmeticType> ArmsTypes = new HashSet<CosmeticType> { (CosmeticType)1, (CosmeticType)2, (CosmeticType)9, (CosmeticType)10, (CosmeticType)26, (CosmeticType)27 }; private static readonly HashSet<CosmeticType> LegsFeetTypes = new HashSet<CosmeticType> { (CosmeticType)3, (CosmeticType)4, (CosmeticType)11, (CosmeticType)12, (CosmeticType)19, (CosmeticType)22, (CosmeticType)28, (CosmeticType)29 }; private static readonly HashSet<CosmeticType> GrabberTypes = new HashSet<CosmeticType> { (CosmeticType)13 }; private static readonly HashSet<CosmeticType> AllRemovalTypes = BuildAllRemovalSet(); private void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown _instance = this; DetachFromManager(); _compatibilityReport = CompatibilityReport.Build(); _harmony = new Harmony("zichen.removeallcosmetics.patch"); PatchHarmonySafely(); LogCompatibilityReport(); StartAutomaticRemoval(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"RemoveAllCosmetics v1.0.0 loaded."); } private void OnDestroy() { try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Harmony unpatch failed: " + ex.Message)); } _harmony = null; if (_instance == this) { _instance = null; } } private void DetachFromManager() { ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private void PatchHarmonySafely() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (!_compatibilityReport.VisualFilterAvailable) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Skipped visual cosmetic filter patch because compatibility self-check failed."); return; } try { _harmony.Patch((MethodBase)PlayerCosmeticsSetupCosmeticsLogicMethod, new HarmonyMethod(SetupCosmeticsLogicPrefixMethod), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { _compatibilityReport.AddPatchFailure("视觉层装饰过滤", "PlayerCosmetics.SetupCosmeticsLogic", ex.Message); _compatibilityReport.VisualFilterAvailable = false; ((BaseUnityPlugin)this).Logger.LogWarning((object)("Skipped visual cosmetic filter patch: " + ex.Message)); } } private void LogCompatibilityReport() { if (!_compatibilityReport.HasIssues) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Compatibility self-check passed."); return; } ((BaseUnityPlugin)this).Logger.LogWarning((object)_compatibilityReport.BuildLogMessage()); foreach (string detailMessage in _compatibilityReport.GetDetailMessages()) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Compatibility detail: " + detailMessage)); } } private static void SetupCosmeticsLogic_Prefix(ref int[] _cosmeticEquipped) { if (!_compatibilityReport.VisualFilterAvailable) { return; } try { if (_cosmeticEquipped == null || _cosmeticEquipped.Length == 0) { return; } List<CosmeticAsset> cosmeticAssets = GetCosmeticAssets(GetMetaManagerInstance()); if (cosmeticAssets == null || cosmeticAssets.Count == 0) { return; } List<int> list = new List<int>(_cosmeticEquipped.Length); int[] array = _cosmeticEquipped; foreach (int num in array) { if (!ShouldRemoveCosmeticIndex(num, cosmeticAssets, AllRemovalTypes)) { list.Add(num); } } if (list.Count != _cosmeticEquipped.Length) { Plugin instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"[SetupCosmeticsLogic] filtered {_cosmeticEquipped.Length} -> {list.Count}"); } _cosmeticEquipped = list.ToArray(); } } catch (Exception ex) { Plugin instance2 = _instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("[SetupCosmeticsLogic] visual filter failed: " + ex.Message)); } } } private void StartAutomaticRemoval() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) _popupShown = false; _popupWaiting = false; if (!_compatibilityReport.AutomaticRemovalAvailable) { string body = _compatibilityReport.BuildPopupMessage(); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Automatic cosmetic removal is disabled by compatibility self-check."); TryShowPopup("RemoveAllCosmetics 兼容提示", Color.yellow, body); } else { ((MonoBehaviour)this).StartCoroutine(NukeCosmetics()); } } [IteratorStateMachine(typeof(<NukeCosmetics>d__52))] private IEnumerator NukeCosmetics() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NukeCosmetics>d__52(0) { <>4__this = this }; } private static bool TryReadCosmeticSaveData(MetaManager meta, out CosmeticSaveData data, out string error) { data = null; error = null; if ((Object)(object)meta == (Object)null) { error = "MetaManager 不可用,本次未执行清理。"; return false; } List<CosmeticAsset> cosmeticAssets = GetCosmeticAssets(meta); if (cosmeticAssets == null) { error = "无法读取游戏装饰资源列表,本次未执行清理。"; return false; } if (!TryGetFieldValue<string>(MetaSavePathField, meta, out var value) || string.IsNullOrWhiteSpace(value)) { error = "无法读取装饰存档路径,本次未修改存档。"; return false; } TryGetFieldValue<List<int>>(MetaCosmeticTokensField, meta, out var value2); List<int> value3; bool num = TryGetFieldValue<List<int>>(MetaCosmeticUnlocksField, meta, out value3); List<int> value4; bool flag = TryGetFieldValue<List<int>>(MetaCosmeticHistoryField, meta, out value4); List<int> value5; bool flag2 = TryGetFieldValue<List<int>>(MetaCosmeticEquippedField, meta, out value5); List<List<int>> value6; bool flag3 = TryGetFieldValue<List<List<int>>>(MetaCosmeticPresetsField, meta, out value6); List<List<int>> value7; bool flag4 = TryGetFieldValue<List<List<int>>>(MetaColorPresetsField, meta, out value7); int[] value8; bool flag5 = TryGetFieldValue<int[]>(MetaColorsEquippedField, meta, out value8); if (!num || !flag || !flag2 || !flag3 || !flag4 || !flag5) { error = "游戏装饰存档结构可能已变化,本次未修改存档。"; return false; } data = new CosmeticSaveData { SavePath = value, Tokens = value2, Unlocks = value3, History = value4, Equipped = value5, CosmeticPresets = value6, ColorPresets = value7, Colors = value8, Assets = cosmeticAssets }; return true; } private bool WriteVanillaMetaSave(CosmeticSaveData saveData, List<int> finalEquipped, int[] finalColors, int presetSlotCount, string encryptionPassword) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) try { ES3Settings val = new ES3Settings(new Enum[1] { (Enum)(object)(Location)4 }); val.encryptionType = (EncryptionType)1; val.encryptionPassword = encryptionPassword; val.path = saveData.SavePath + ".es3"; List<int> list = saveData.Tokens ?? TryLoadTokensFromSave(val); if (list != null) { ES3.Save<List<int>>("cosmeticTokens", list, val); } ES3.Save<List<int>>("cosmeticUnlocks", saveData.Unlocks ?? new List<int>(), val); ES3.Save<List<int>>("cosmeticHistory", saveData.History ?? new List<int>(), val); ES3.Save<List<int>>("cosmeticEquipped", finalEquipped ?? new List<int>(), val); ES3.Save<List<List<int>>>("cosmeticPresets", saveData.CosmeticPresets ?? CreateEmptyIntPresetSlots(presetSlotCount), val); ES3.Save<List<List<int>>>("colorPresets", saveData.ColorPresets ?? CreateEmptyIntPresetSlots(presetSlotCount), val); ES3.Save<int[]>("colorsEquipped", finalColors ?? CreateEmptyColorsArray(), val); ES3.StoreCachedFile(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)($"ES3 write {val.path}: tokensKept={list?.Count ?? 0}, " + $"unlocks={saveData.Unlocks?.Count ?? 0}, history={saveData.History?.Count ?? 0}, equipped={finalEquipped?.Count ?? 0}")); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("ES3 write MetaSave failed: " + ex)); return false; } } private bool WriteModdedMetaSave(string savePath, int[] finalColors, int presetSlotCount, string encryptionPassword) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown try { ES3Settings val = new ES3Settings(savePath + "Modded.es3", (EncryptionType)1, encryptionPassword, (ES3Settings)null); if (!ES3.FileExists(val)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"MetaSaveModded.es3 not found, skipping."); return false; } ES3.Save<List<string>>("cosmeticUnlocks", new List<string>(), val); ES3.Save<List<string>>("cosmeticHistory", new List<string>(), val); ES3.Save<List<string>>("cosmeticEquipped", new List<string>(), val); ES3.Save<List<List<string>>>("cosmeticPresets", CreateEmptyStringPresetSlots(presetSlotCount), val); ES3.Save<List<List<int>>>("colorPresets", CreateEmptyIntPresetSlots(presetSlotCount), val); ES3.Save<int[]>("colorsEquipped", finalColors ?? CreateEmptyColorsArray(), val); ((BaseUnityPlugin)this).Logger.LogInfo((object)"ES3 write MetaSaveModded.es3: cosmetic data cleared."); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("ES3 write MetaSaveModded failed: " + ex.Message)); return false; } } private void SyncUnlockAllCosmeticsBackup(List<int> finalEquipped, int[] finalColors) { try { string path = Path.Combine(Paths.ConfigPath, "UnlockAllCosmetics_save.json"); if (File.Exists(path)) { string text = File.ReadAllText(path); if (!string.IsNullOrWhiteSpace(text)) { ExtBackup extBackup = JsonUtility.FromJson<ExtBackup>(text) ?? new ExtBackup(); extBackup.cosmeticUnlocks = new List<int>(); extBackup.cosmeticEquipped = ((finalEquipped != null) ? new List<int>(finalEquipped) : new List<int>()); extBackup.colorsEquipped = ((finalColors != null) ? finalColors.ToList() : new List<int>()); File.WriteAllText(path, JsonUtility.ToJson((object)extBackup)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"UnlockAllCosmetics_save.json synced."); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Sync UnlockAllCosmetics backup failed: " + ex.Message)); } } private void RefreshCosmeticVisuals(MetaManager meta) { if (!_compatibilityReport.VisualRefreshAvailable) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Skipped cosmetic visual refresh because compatibility self-check failed."); return; } TryInvoke(MetaCosmeticPreviewSetMethod, meta, false); TryInvoke(MetaCosmeticPlayerUpdateLocalMethod, meta, true, true); PlayerCosmetics[] array = Object.FindObjectsOfType<PlayerCosmetics>(); foreach (PlayerCosmetics val in array) { if (!((Object)(object)val == (Object)null)) { TryInvoke(PlayerCosmeticsSetupCosmeticsMethod, val, false, true, null); TryInvoke(PlayerCosmeticsSetupColorsMethod, val, false, null); } } } private static List<int> TryLoadTokensFromSave(ES3Settings settings) { try { return ES3.KeyExists("cosmeticTokens", settings) ? ES3.Load<List<int>>("cosmeticTokens", settings) : null; } catch { return null; } } private void ShowRemovalFailure(string reason) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) ((BaseUnityPlugin)this).Logger.LogWarning((object)reason); string text = reason + "\n"; text += "本模组每次启动游戏都会尝试移除全部装饰。\n"; text += "但当前游戏接口可能已变化,为避免损坏存档,本次没有执行清理。\n"; text += "如不需要此功能,请卸载本模组。"; string text2 = _compatibilityReport.BuildPopupAppendix(); if (!string.IsNullOrWhiteSpace(text2)) { text = text + "\n\n" + text2; } TryShowPopup("RemoveAllCosmetics 兼容提示", Color.yellow, text); } private static int RemoveMatchingCosmeticIndexes(List<int> indexes, List<CosmeticAsset> assets, HashSet<CosmeticType> typesToRemove) { if (indexes == null || assets == null || typesToRemove == null || typesToRemove.Count == 0) { return 0; } int num = 0; for (int num2 = indexes.Count - 1; num2 >= 0; num2--) { if (ShouldRemoveCosmeticIndex(indexes[num2], assets, typesToRemove)) { indexes.RemoveAt(num2); num++; } } return num; } private static int RemoveMatchingCosmeticIndexesFromPresets(List<List<int>> presets, List<CosmeticAsset> assets, HashSet<CosmeticType> typesToRemove) { if (presets == null) { return 0; } int num = 0; foreach (List<int> preset in presets) { num += RemoveMatchingCosmeticIndexes(preset, assets, typesToRemove); } return num; } private static bool ShouldRemoveCosmeticIndex(int index, List<CosmeticAsset> assets, HashSet<CosmeticType> typesToRemove) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (index < 0 || assets == null || index >= assets.Count) { return false; } if (TryGetCosmeticType(assets[index], out var type)) { return typesToRemove.Contains(type); } return false; } private static void ResetColorsForTypes(int[] colors, HashSet<CosmeticType> typesToRemove) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown if (colors == null || typesToRemove == null) { return; } foreach (CosmeticType item in typesToRemove) { int num = (int)item; if (num >= 0 && num < colors.Length) { colors[num] = 0; } } } private static void ResetColorPresetsForTypes(List<List<int>> colorPresets, HashSet<CosmeticType> typesToRemove) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown if (colorPresets == null || typesToRemove == null) { return; } foreach (List<int> colorPreset in colorPresets) { if (colorPreset == null) { continue; } foreach (CosmeticType item in typesToRemove) { int num = (int)item; if (num >= 0 && num < colorPreset.Count) { colorPreset[num] = 0; } } } } private static int GetPresetSlotCount(MetaManager meta) { if (TryGetFieldValue<int>(MetaPresetSlotsField, meta, out var value) && value > 0) { return value; } return 28; } private static List<List<int>> CreateEmptyIntPresetSlots(int count) { List<List<int>> list = new List<List<int>>(); for (int i = 0; i < count; i++) { list.Add(new List<int>()); } return list; } private static List<List<string>> CreateEmptyStringPresetSlots(int count) { List<List<string>> list = new List<List<string>>(); for (int i = 0; i < count; i++) { list.Add(new List<string>()); } return list; } private static int[] CreateEmptyColorsArray() { return new int[Enum.GetValues(typeof(CosmeticType)).Length]; } private static HashSet<CosmeticType> BuildAllRemovalSet() { HashSet<CosmeticType> hashSet = new HashSet<CosmeticType>(); hashSet.UnionWith(HeadTypes); hashSet.UnionWith(BodyTypes); hashSet.UnionWith(ArmsTypes); hashSet.UnionWith(LegsFeetTypes); hashSet.UnionWith(GrabberTypes); return hashSet; } private static bool TryGetFieldValue<T>(FieldInfo field, object instance, out T value) { value = default(T); if (field == null || instance == null) { return false; } try { object value2 = field.GetValue(instance); if (value2 is T) { T val = (T)value2; value = val; return true; } } catch { return false; } return false; } private static List<CosmeticAsset> GetCosmeticAssets(MetaManager meta) { if (!TryGetFieldValue<List<CosmeticAsset>>(MetaCosmeticAssetsField, meta, out var value)) { return null; } return value; } private static MetaManager GetMetaManagerInstance() { if (!TryGetStaticFieldValue<MetaManager>(MetaManagerInstanceField, out var value)) { return null; } return value; } private static StatsManager GetStatsManagerInstance() { if (!TryGetStaticFieldValue<StatsManager>(StatsManagerInstanceField, out var value)) { return null; } return value; } private static MenuManager GetMenuManagerInstance() { if (!TryGetStaticFieldValue<MenuManager>(MenuManagerInstanceField, out var value)) { return null; } return value; } private static bool TryGetStaticFieldValue<T>(FieldInfo field, out T value) { value = default(T); if (field == null) { return false; } try { object value2 = field.GetValue(null); if (value2 is T) { T val = (T)value2; value = val; return true; } } catch { return false; } return false; } private static bool TryGetCosmeticType(CosmeticAsset asset, out CosmeticType type) { type = (CosmeticType)0; return TryGetFieldValue<CosmeticType>(CosmeticAssetTypeField, asset, out type); } private static bool TryGetEncryptionPassword(out string encryptionPassword) { encryptionPassword = null; try { StatsManager statsManagerInstance = GetStatsManagerInstance(); if ((Object)(object)statsManagerInstance != (Object)null && TryGetFieldValue<string>(StatsManagerPasswordField, statsManagerInstance, out var value) && !string.IsNullOrWhiteSpace(value)) { encryptionPassword = value; return true; } } catch { return false; } return false; } private static bool TryInvoke(MethodInfo method, object instance, params object[] args) { if (method == null || instance == null) { return false; } try { method.Invoke(instance, args); return true; } catch (Exception ex) { Plugin instance2 = _instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("Invoke failed: " + method.Name + " -> " + ex.Message)); } return false; } } private static bool IsPopupSlotBusy(MenuManager menuManager) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 if (!_compatibilityReport.ResultPopupAvailable || (Object)(object)menuManager == (Object)null) { return true; } if (!TryGetFieldValue<MenuPage>(MenuManagerCurrentMenuPageField, menuManager, out var value) || (Object)(object)value == (Object)null) { return true; } if (!TryGetFieldValue<bool>(MenuManagerPagePopUpScheduledField, menuManager, out var value2) || value2) { return true; } if (!TryGetFieldValue<MenuPageIndex>(MenuManagerCurrentMenuPageIndexField, menuManager, out var value3)) { return true; } if ((int)value3 != 9) { return (int)value3 == 7; } return true; } private static void TryShowPopup(string title, Color color, string body) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (_popupShown) { return; } if (!_compatibilityReport.ResultPopupAvailable) { Plugin instance = _instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Popup skipped because MenuManager popup API is unavailable. Message: " + body)); } } else { StartPopupWait(title, color, body); } } private static void StartPopupWait(string title, Color color, string body) { //IL_0021: 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) if (!_popupWaiting && !((Object)(object)_instance == (Object)null)) { _popupWaiting = true; _pendingPopupTitle = title; _pendingPopupColor = color; _pendingPopupBody = body; ((MonoBehaviour)_instance).StartCoroutine(WaitAndShowPopup()); } } [IteratorStateMachine(typeof(<WaitAndShowPopup>d__82))] private static IEnumerator WaitAndShowPopup() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitAndShowPopup>d__82(0); } } }