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 ShareChest v1.0.2
ShareChest.dll
Decompiled 2 weeks 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.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using R2API; using RoR2; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ShareChest")] [assembly: AssemblyDescription("共享宝箱 - Risk of Rain 2 模组")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Muskmelovon")] [assembly: AssemblyProduct("ShareChest")] [assembly: AssemblyCopyright("Copyright © Muskmelovon 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f2eff138-24ee-4741-88c1-c6ff8bf1d179")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace ShareChest { public abstract class ArtifactBase { public ArtifactDef ArtifactDef; public abstract string ArtifactName { get; } public abstract string ArtifactLangTokenName { get; } public abstract string ArtifactDescription { get; } public abstract Sprite ArtifactEnabledIcon { get; } public abstract Sprite ArtifactDisabledIcon { get; } public virtual string DisplayName => ArtifactName; public bool ArtifactEnabled { get { RunArtifactManager instance = RunArtifactManager.instance; return instance != null && instance.IsArtifactEnabled(ArtifactDef); } } public abstract void Init(ConfigFile config); protected void CreateLang() { LanguageAPI.Add("ARTIFACT_" + ArtifactLangTokenName + "_NAME", DisplayName); LanguageAPI.Add("ARTIFACT_" + ArtifactLangTokenName + "_DESCRIPTION", ArtifactDescription); } protected bool CreateArtifact() { ArtifactDef = ScriptableObject.CreateInstance<ArtifactDef>(); ArtifactDef.cachedName = "ARTIFACT_" + ArtifactLangTokenName; ArtifactDef.nameToken = "ARTIFACT_" + ArtifactLangTokenName + "_NAME"; ArtifactDef.descriptionToken = "ARTIFACT_" + ArtifactLangTokenName + "_DESCRIPTION"; ArtifactDef.smallIconSelectedSprite = ArtifactEnabledIcon; ArtifactDef.smallIconDeselectedSprite = ArtifactDisabledIcon; bool flag = ContentAddition.AddArtifactDef(ArtifactDef); if (!flag) { ShareChestPlugin.LogError("神器 " + ArtifactName + " 添加失败!可能图标为null或重复。"); } return flag; } public abstract void Hooks(); } internal class ArtifactOfEquilibrium : ArtifactBase { public override string ArtifactName => "Artifact of Equilibrium"; public override string ArtifactLangTokenName => "EQUILIBRIUM"; public override string DisplayName => "Artifact of Equilibrium - 均衡神器"; public override string ArtifactDescription => "开启后,宝箱会掉落多倍物品(根据玩家数量动态调整或固定倍率,需前往配置文件修改配置)。\n启用此神器以激活共享宝箱Mod的多倍掉落。\n\nOnce activated, the treasure chest will drop items in multiple times (the multiplier is dynamically adjusted according to the number of players or can be set as a fixed rate. The configuration needs to be modified in the configuration file). \nEnable this artifact to activate the multiple-dropping feature of the Shared Treasure Chest Mod."; public override Sprite ArtifactEnabledIcon => GetIcon("ArtifactOfEquilibrium_On"); public override Sprite ArtifactDisabledIcon => GetIcon("ArtifactOfEquilibrium_Off"); private Sprite GetIcon(string iconName) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ShareChestPlugin.MainAssets != (Object)null) { Sprite val = ShareChestPlugin.MainAssets.LoadAsset<Sprite>(iconName); if ((Object)(object)val != (Object)null) { return val; } ShareChestPlugin.LogWarning("未找到图标 " + iconName + ",将使用默认占位图标"); } else { ShareChestPlugin.LogWarning("AssetBundle 未加载,使用默认占位图标"); } Texture2D val2 = new Texture2D(2, 2); val2.SetPixels32((Color32[])(object)new Color32[4] { Color32.op_Implicit(Color.clear), Color32.op_Implicit(Color.clear), Color32.op_Implicit(Color.clear), Color32.op_Implicit(Color.clear) }); val2.Apply(); return Sprite.Create(val2, new Rect(0f, 0f, 2f, 2f), new Vector2(0.5f, 0.5f)); } public override void Init(ConfigFile config) { CreateLang(); if (CreateArtifact()) { ShareChestPlugin.LogInfo("神器 " + ArtifactName + " 已成功注册到游戏。"); } else { ShareChestPlugin.LogError("神器 " + ArtifactName + " 注册失败。"); } Hooks(); } public override void Hooks() { Run.onRunStartGlobal += OnRunStart; } private void OnRunStart(Run run) { if (NetworkServer.active) { ShareChestPlugin.IsArtifactEnabled = base.ArtifactEnabled; ShareChestPlugin.LogInfo("神器均衡宝箱状态: " + (ShareChestPlugin.IsArtifactEnabled ? "启用" : "禁用")); } } } [BepInPlugin("com.Muskmelovon.ShareChest", "共享宝箱", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ShareChestPlugin : BaseUnityPlugin { public const string PluginGUID = "com.Muskmelovon.ShareChest"; public const string PluginName = "共享宝箱"; public const string PluginVersion = "1.0.0"; private static ManualLogSource Log; private static Harmony harmony; public static ConfigEntry<bool> ModEnabled; public static ConfigEntry<bool> EnableDynamicMultiplier; public static ConfigEntry<int> FixedMultiplier; public static ConfigEntry<bool> EnableDebugLogs; public static ConfigEntry<string> AffectedChestTypes; public static ConfigEntry<float> DropDistanceClamp; private static readonly string ChestListSeparator = ","; private static HashSet<string> affectedChestTypeSet = new HashSet<string>(); public static AssetBundle MainAssets; private static List<ArtifactBase> artifacts = new List<ArtifactBase>(); public static bool IsArtifactEnabled = false; public static bool IsInitialized { get; private set; } = false; public void Awake() { Log = ((BaseUnityPlugin)this).Logger; try { Log.LogInfo((object)"========== 共享宝箱 v1.0.0 初始化开始 =========="); LoadAssetBundle(); InitializePlayerCountManager(); InitializeConfiguration(); InitializeArtifacts(); InitializeHarmonyPatches(); IsInitialized = true; Log.LogInfo((object)"插件初始化成功!"); Log.LogInfo((object)$"当前配置:插件总开关={ModEnabled.Value}, 动态倍率={EnableDynamicMultiplier.Value}"); Log.LogInfo((object)$"掉落距离设置:{DropDistanceClamp.Value}(原版为6)"); Log.LogInfo((object)("应用倍率的宝箱类型:" + ((affectedChestTypeSet.Count > 0) ? string.Join(", ", affectedChestTypeSet) : "所有宝箱"))); Log.LogInfo((object)"配置位置:BepInEx/config/com.Muskmelovon.ShareChest.cfg"); Log.LogInfo((object)"调试命令:按 F5 显示调试信息,按 F6 强制重新计算玩家数量"); Log.LogInfo((object)"=================================================="); } catch (Exception ex) { Log.LogError((object)"插件初始化失败!"); Log.LogError((object)("错误信息:" + ex.Message)); Log.LogError((object)("堆栈跟踪:" + ex.StackTrace)); if (ex.InnerException != null) { Log.LogError((object)("内部异常:" + ex.InnerException.Message)); } try { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } catch { } throw; } } private void LoadAssetBundle() { string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); string text = manifestResourceNames.FirstOrDefault((string r) => r.EndsWith(".assets", StringComparison.OrdinalIgnoreCase)); if (text == null) { Log.LogWarning((object)"未找到任何 .assets 嵌入资源,神器图标将使用默认占位图。"); return; } Log.LogInfo((object)("找到嵌入资源: " + text)); using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text); if (stream == null) { Log.LogError((object)("无法获取资源流: " + text)); return; } MainAssets = AssetBundle.LoadFromStream(stream); if ((Object)(object)MainAssets == (Object)null) { Log.LogError((object)"AssetBundle.LoadFromStream 返回 null,请检查资源文件是否有效。"); } else { Log.LogInfo((object)("AssetBundle 加载成功,包含的资源: " + string.Join(", ", MainAssets.GetAllAssetNames()))); } } public void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } public void Update() { if (Input.GetKeyDown((KeyCode)286)) { ShowDebugInfo(); } if (Input.GetKeyDown((KeyCode)287)) { ForceRecalculate(); } } private void InitializePlayerCountManager() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Log.LogInfo((object)"正在初始化 PlayerCountManager..."); if ((Object)(object)PlayerCountManager.Instance != (Object)null) { Log.LogWarning((object)"PlayerCountManager 已存在,跳过创建"); return; } GameObject val = new GameObject("ShareChest_PlayerCountManager"); val.AddComponent<PlayerCountManager>(); Object.DontDestroyOnLoad((Object)(object)val); Log.LogInfo((object)"PlayerCountManager 初始化完成"); } private void InitializeConfiguration() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown Log.LogInfo((object)"正在初始化配置系统..."); ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("通用设置", "启用插件", true, new ConfigDescription("插件总开关。注意:同时需要神器“共享宝箱”启用才能生效。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 10, IsAdvanced = false } })); EnableDynamicMultiplier = ((BaseUnityPlugin)this).Config.Bind<bool>("掉落设置", "启用动态倍率", false, new ConfigDescription("是否根据玩家人数动态调整掉落倍率\n• true = 启用动态倍率(倍率 = 玩家人数)\n• false = 使用固定倍率", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 15, IsAdvanced = false } })); FixedMultiplier = ((BaseUnityPlugin)this).Config.Bind<int>("掉落设置", "固定掉落倍率", 5, new ConfigDescription("当'启用动态倍率'为false时使用的固定掉落倍率\n• 1 = 正常掉落(原版行为)\n• 5 = 掉落5个相同物品(推荐)\n• 单人固定倍率推荐1,多人推荐动态倍率\n• 注意:过高的值可能影响游戏性能", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), new object[1] { new ConfigurationManagerAttributes { Order = 20, IsAdvanced = false } })); DropDistanceClamp = ((BaseUnityPlugin)this).Config.Bind<float>("掉落设置", "掉落距离限制", 6f, new ConfigDescription("控制物品掉落时的最小距离限制\n• 默认值为6,不推荐更改\n• 较低的值使物品掉落更集中\n• 较高的值使物品掉落更分散\n• 注意:过高的值可能导致物品飞出太远", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f), new object[1] { new ConfigurationManagerAttributes { Order = 25, IsAdvanced = false } })); AffectedChestTypes = ((BaseUnityPlugin)this).Config.Bind<string>("宝箱类型设置", "应用倍率的宝箱类型", "Chest1(Clone),Chest2(Clone),GoldChest,LunarChest(Clone),VoidChest(Clone),CategoryChestUtility(Clone),CategoryChest2Utility Variant(Clone),CategoryChestHealing(Clone),CategoryChest2Healing Variant(Clone),CategoryChestDamage(Clone),CategoryChest2Damage Variant(Clone)", new ConfigDescription("指定哪些宝箱类型应用掉落倍率\n• 用逗号分隔多个宝箱类型\n• 常见宝箱类型:\n - Chest1(Clone): 普通宝箱\n - Chest2(Clone): 大宝箱\n - GoldChest: 传奇宝箱\n - LunarChest(Clone): 月球舱\n - VoidChest(Clone): 虚空摇篮\n - EquipmentBarrel(Clone): 装备箱(默认关闭)\n - Lockbox(Clone): 生锈带锁箱(默认关闭)\n - CategoryChestUtility(Clone): 辅助箱\n - CategoryChest2Utility Variant(Clone): 大辅助箱\n - CategoryChestHealing(Clone): 治疗箱\n - CategoryChest2Healing Variant(Clone): 大治疗箱\n - CategoryChestDamage(Clone): 伤害箱\n - CategoryChest2Damage Variant(Clone): 大伤害箱\n• 默认关闭倍率宝箱类型:\n - EquipmentBarrel(Clone): 装备箱\n - Lockbox(Clone): 生锈带锁箱\n• 如需启用请在默认值中添加\n• 留空表示所有宝箱都应用倍率\n• 注意:名字必须完全匹配,包括大小写和括号", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 80, IsAdvanced = false } })); EnableDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("调试设置", "启用调试日志", true, new ConfigDescription("启用详细的调试日志输出", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1000, IsAdvanced = true } })); UpdateAffectedChestTypes(); ModEnabled.SettingChanged += delegate { LogInfo("插件总开关已变更:" + (ModEnabled.Value ? "启用" : "禁用")); }; EnableDynamicMultiplier.SettingChanged += delegate { LogInfo("倍率模式已变更:" + (EnableDynamicMultiplier.Value ? "动态" : "固定")); }; FixedMultiplier.SettingChanged += delegate { LogInfo($"固定倍率已变更:{FixedMultiplier.Value}x"); }; DropDistanceClamp.SettingChanged += delegate { LogInfo($"掉落距离限制已变更:{DropDistanceClamp.Value}"); }; AffectedChestTypes.SettingChanged += delegate { UpdateAffectedChestTypes(); }; EnableDebugLogs.SettingChanged += delegate { LogInfo("调试日志已" + (EnableDebugLogs.Value ? "启用" : "禁用")); }; } private void InitializeArtifacts() { Log.LogInfo((object)"正在初始化神器系统..."); IEnumerable<Type> enumerable = from t in Assembly.GetExecutingAssembly().GetTypes() where !t.IsAbstract && t.IsSubclassOf(typeof(ArtifactBase)) select t; foreach (Type item in enumerable) { ArtifactBase artifactBase = (ArtifactBase)Activator.CreateInstance(item); if (((BaseUnityPlugin)this).Config.Bind<bool>("神器设置", artifactBase.ArtifactName + "_启用", true, "是否在神器选择界面显示该神器").Value) { artifactBase.Init(((BaseUnityPlugin)this).Config); artifacts.Add(artifactBase); Log.LogInfo((object)("已加载神器: " + artifactBase.ArtifactName)); } } Log.LogInfo((object)$"神器系统初始化完成,共加载 {artifacts.Count} 个神器"); } private void InitializeHarmonyPatches() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Log.LogInfo((object)"正在应用 Harmony 补丁..."); harmony = new Harmony("com.Muskmelovon.ShareChest"); harmony.PatchAll(Assembly.GetExecutingAssembly()); IEnumerable<MethodBase> patchedMethods = harmony.GetPatchedMethods(); Log.LogInfo((object)$"成功应用 {patchedMethods.Count()} 个 Harmony 补丁"); } private static void ShowDebugInfo() { int currentPlayerCount = GetCurrentPlayerCount(); int num = CalculateMultiplier(currentPlayerCount); LogInfo("=== 共享宝箱调试信息 ==="); LogInfo($"插件总开关: {ModEnabled.Value}"); LogInfo($"神器启用状态: {IsArtifactEnabled}"); LogInfo($"当前玩家数量: {currentPlayerCount}"); LogInfo($"动态倍率: {EnableDynamicMultiplier.Value}"); LogInfo($"固定倍率: {FixedMultiplier.Value}"); LogInfo($"掉落距离限制: {DropDistanceClamp.Value}"); LogInfo($"计算后的倍率: {num}x"); LogInfo("PlayerCountManager 实例: " + (((Object)(object)PlayerCountManager.Instance != (Object)null) ? "存在" : "不存在")); if ((Object)(object)PlayerCountManager.Instance != (Object)null) { LogInfo($"PlayerCountManager 计数: {PlayerCountManager.Instance.CurrentPlayerCount}"); } LogInfo($"宝箱类型白名单: {affectedChestTypeSet.Count}种"); if (affectedChestTypeSet.Count > 0) { LogInfo("白名单内容: " + string.Join(", ", affectedChestTypeSet)); } LogInfo("========================"); } private static void ForceRecalculate() { if ((Object)(object)PlayerCountManager.Instance != (Object)null) { PlayerCountManager.Instance.RecalculatePlayerCount(); LogInfo($"已强制重新计算玩家数量: {PlayerCountManager.Instance.CurrentPlayerCount}人"); } else { LogError("PlayerCountManager 实例不存在,无法重新计算"); } } public static int CalculateMultiplier(int currentPlayerCount) { if (!EnableDynamicMultiplier.Value) { return Math.Max(1, FixedMultiplier.Value); } return Math.Max(1, currentPlayerCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetCurrentPlayerCount() { if ((Object)(object)PlayerCountManager.Instance != (Object)null) { return PlayerCountManager.Instance.CurrentPlayerCount; } try { if (NetworkUser.readOnlyInstancesList != null) { return NetworkUser.readOnlyInstancesList.Count; } if (NetworkServer.active) { int num = 0; foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if ((Object)(object)instance != (Object)null && ((Behaviour)instance).isActiveAndEnabled) { num++; } } return Math.Max(1, num); } return 1; } catch { return 1; } } public static string GetMultiplierInfo(int playerCount) { if (!EnableDynamicMultiplier.Value) { return $"固定倍率: {FixedMultiplier.Value}x"; } return $"动态倍率: {CalculateMultiplier(playerCount)}x (玩家数: {playerCount}人)"; } private static void UpdateAffectedChestTypes() { affectedChestTypeSet.Clear(); string value = AffectedChestTypes.Value; if (string.IsNullOrWhiteSpace(value)) { return; } IEnumerable<string> enumerable = from s in value.Split(new string[1] { ChestListSeparator }, StringSplitOptions.RemoveEmptyEntries) select s.Trim() into s where !string.IsNullOrEmpty(s) select s; foreach (string item in enumerable) { affectedChestTypeSet.Add(item); } LogDebug($"已加载 {affectedChestTypeSet.Count} 种宝箱类型"); } public static bool ShouldApplyToChest(string chestName) { if (affectedChestTypeSet.Count == 0) { return true; } return affectedChestTypeSet.Contains(chestName); } public static bool ShouldApplyMultiplier(ChestBehavior chest) { if (!ModEnabled.Value || !IsArtifactEnabled) { LogDebug($"多倍掉落未生效:插件总开关={ModEnabled.Value}, 神器启用={IsArtifactEnabled}"); return false; } if ((Object)(object)chest == (Object)null || (Object)(object)((Component)chest).gameObject == (Object)null) { return false; } string name = ((Object)((Component)chest).gameObject).name; if (!ShouldApplyToChest(name)) { LogDebug("宝箱 " + name + " 不在允许列表中,不应用倍率"); return false; } Traverse val = Traverse.Create((object)chest); if (val.Field("isChestOpened").GetValue<bool>()) { return false; } if (chest.isCommandChest) { LogDebug("命令宝箱不应用倍率"); return false; } int currentPlayerCount = GetCurrentPlayerCount(); int num = CalculateMultiplier(currentPlayerCount); LogDebug($"将对宝箱 {name} 应用 {num}x 倍率"); return true; } public static void LogDebug(string message) { if (EnableDebugLogs.Value && Log != null) { Log.LogInfo((object)("[调试] " + message)); } } public static void LogWarning(string message) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[警告] " + message)); } } public static void LogError(string message) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("[错误] " + message)); } } public static void LogInfo(string message) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[信息] " + message)); } } } internal class ConfigurationManagerAttributes { public int? Order = null; public bool? IsAdvanced = null; public string Category = null; public Action<ConfigEntryBase> CustomDrawer = null; } public class PlayerCountManager : MonoBehaviour { private float lastRecalculateTime = 0f; private const float RECALCULATE_INTERVAL = 2f; public static PlayerCountManager Instance { get; private set; } public int CurrentPlayerCount { get; private set; } public bool IsMultiplayer => CurrentPlayerCount > 1; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); ((MonoBehaviour)this).StartCoroutine(DelayedInitialize()); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } private IEnumerator DelayedInitialize() { yield return null; try { NetworkUser.onPostNetworkUserStart += new NetworkUserGenericDelegate(OnPlayerJoined); NetworkUser.onNetworkUserLost += new NetworkUserGenericDelegate(OnPlayerLost); SceneManager.activeSceneChanged += OnSceneChanged; RecalculatePlayerCount(); ShareChestPlugin.LogInfo($"[PlayerCountManager] 初始化完成,当前玩家数: {CurrentPlayerCount}"); ((MonoBehaviour)this).InvokeRepeating("PeriodicCheck", 5f, 5f); } catch (Exception ex) { ShareChestPlugin.LogError("[PlayerCountManager] 初始化失败: " + ex.Message); } } private void OnDestroy() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown try { NetworkUser.onPostNetworkUserStart -= new NetworkUserGenericDelegate(OnPlayerJoined); NetworkUser.onNetworkUserLost -= new NetworkUserGenericDelegate(OnPlayerLost); SceneManager.activeSceneChanged -= OnSceneChanged; } catch { } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } ((MonoBehaviour)this).CancelInvoke("PeriodicCheck"); } private void OnPlayerJoined(NetworkUser joinedUser) { ((MonoBehaviour)this).StartCoroutine(UpdatePlayerCountDelayed(1f)); ShareChestPlugin.LogInfo("[PlayerCountManager] 玩家加入: " + joinedUser.userName); } private void OnPlayerLost(NetworkUser lostUser) { ((MonoBehaviour)this).StartCoroutine(UpdatePlayerCountDelayed(1f)); ShareChestPlugin.LogInfo("[PlayerCountManager] 玩家离开: " + lostUser?.userName); } private void OnSceneChanged(Scene oldScene, Scene newScene) { RecalculatePlayerCount(); ShareChestPlugin.LogInfo($"[PlayerCountManager] 场景变化: {((Scene)(ref oldScene)).name} -> {((Scene)(ref newScene)).name}, 玩家数: {CurrentPlayerCount}"); } private IEnumerator UpdatePlayerCountDelayed(float delay) { yield return (object)new WaitForSeconds(delay); RecalculatePlayerCount(); } private void PeriodicCheck() { if (Time.time - lastRecalculateTime > 2f) { RecalculatePlayerCount(); } } public void RecalculatePlayerCount() { int currentPlayerCount = CurrentPlayerCount; try { if (NetworkUser.readOnlyInstancesList != null && NetworkUser.readOnlyInstancesList.Count >= 0) { CurrentPlayerCount = NetworkUser.readOnlyInstancesList.Count; ShareChestPlugin.LogInfo($"[PlayerCountManager] 通过NetworkUser获取: {CurrentPlayerCount}人"); } else if (PlayerCharacterMasterController.instances != null && NetworkServer.active) { CurrentPlayerCount = 0; foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if ((Object)(object)instance != (Object)null && ((Behaviour)instance).isActiveAndEnabled) { CurrentPlayerCount++; } } ShareChestPlugin.LogDebug($"[PlayerCountManager] 通过PlayerController获取: {CurrentPlayerCount}人"); } else { CurrentPlayerCount = 1; ShareChestPlugin.LogDebug("[PlayerCountManager] 单人游戏模式: 1人"); } if (CurrentPlayerCount != currentPlayerCount) { ShareChestPlugin.LogInfo($"[PlayerCountManager] 玩家数量变化: {currentPlayerCount} -> {CurrentPlayerCount}"); if (ShareChestPlugin.ModEnabled != null && ShareChestPlugin.ModEnabled.Value && ShareChestPlugin.EnableDynamicMultiplier != null && ShareChestPlugin.EnableDynamicMultiplier.Value) { ShareChestPlugin.LogInfo($"动态倍率更新: 当前{CurrentPlayerCount}人, 倍率{ShareChestPlugin.CalculateMultiplier(CurrentPlayerCount)}x"); } } lastRecalculateTime = Time.time; } catch (Exception ex) { ShareChestPlugin.LogError("重新计算玩家数量失败: " + ex.Message); CurrentPlayerCount = Math.Max(1, currentPlayerCount); } } public void Reset() { CurrentPlayerCount = 0; RecalculatePlayerCount(); } } } namespace ShareChest.Patches { [HarmonyPatch] public static class ChestBehaviorPatches { private static readonly HashSet<uint> processedChests = new HashSet<uint>(); private static int totalChestsGenerated = 0; private static int chestsOpenedCount = 0; private static float runStartTime = 0f; private static uint GetChestUniqueId(ChestBehavior chest) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)chest == (Object)null) { return 0u; } int instanceID = ((Object)chest).GetInstanceID(); Vector3 position = ((Component)chest).transform.position; int hashCode = ((object)(Vector3)(ref position)).GetHashCode(); return (uint)(instanceID ^ hashCode) & 0x7FFFFFFFu; } [HarmonyPatch(typeof(ChestBehavior), "BaseItemDrop")] [HarmonyPrefix] private static bool BaseItemDropPrefix(ChestBehavior __instance) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) try { uint chestUniqueId = GetChestUniqueId(__instance); if (!NetworkServer.active) { ShareChestPlugin.LogDebug($"[{chestUniqueId}] 非服务器端,跳过处理"); return true; } if (processedChests.Contains(chestUniqueId)) { ShareChestPlugin.LogDebug($"[{chestUniqueId}] 宝箱已处理过,防止重复"); return false; } if (!ShareChestPlugin.ShouldApplyMultiplier(__instance)) { return true; } if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null) { return true; } Traverse val = Traverse.Create((object)__instance); if (val.Field("isChestOpened").GetValue<bool>()) { return true; } UniquePickup currentPickup = __instance.currentPickup; if (!((UniquePickup)(ref currentPickup)).isValid) { __instance.Roll(); currentPickup = __instance.currentPickup; if (!((UniquePickup)(ref currentPickup)).isValid) { ShareChestPlugin.LogWarning($"[{chestUniqueId}] 无法生成有效掉落物"); return true; } } processedChests.Add(chestUniqueId); chestsOpenedCount++; int currentPlayerCount = ShareChestPlugin.GetCurrentPlayerCount(); int num = ShareChestPlugin.CalculateMultiplier(currentPlayerCount); int dropCount = __instance.dropCount; int num2 = dropCount * num; if (num2 <= 0) { ShareChestPlugin.LogWarning($"[{chestUniqueId}] 最终掉落数量异常: {num2}"); return false; } UniquePickup currentPickup2 = __instance.currentPickup; Transform dropTransform = __instance.dropTransform ?? ((Component)__instance).transform; ExecuteMultiDrop(__instance, dropTransform, currentPickup2, num2); val.Property("currentPickup", (object[])null).SetValue((object)UniquePickup.none); val.Field("isChestOpened").SetValue((object)true); __instance.NetworkisChestOpened = true; Util.PlaySound("Play_ui_item_world_pickup", ((Component)__instance).gameObject); ShareChestPlugin.LogDebug($"[{chestUniqueId}] 成功生成 {num2} 个掉落物 (原始:{dropCount} × {num})"); return false; } catch (Exception ex) { ShareChestPlugin.LogError("BaseItemDropPrefix 错误: " + ex.Message + "\n" + ex.StackTrace); return true; } } [HarmonyPatch(typeof(ChestBehavior), "Open")] [HarmonyPostfix] private static void OpenPostfix(ChestBehavior __instance) { if (ShareChestPlugin.ModEnabled.Value) { uint chestUniqueId = GetChestUniqueId(__instance); bool flag = processedChests.Contains(chestUniqueId); Traverse val = Traverse.Create((object)__instance); bool value = val.Field("isChestOpened").GetValue<bool>(); ShareChestPlugin.LogInfo($"[{chestUniqueId}] Open() 被调用 - 已处理:{flag}, 状态:{value}"); } } [HarmonyPatch(typeof(ChestBehavior), "Start")] [HarmonyPostfix] private static void StartPostfix(ChestBehavior __instance) { if (ShareChestPlugin.ModEnabled.Value) { if (runStartTime == 0f) { runStartTime = Time.time; ShareChestPlugin.LogDebug($"新对局开始于: {runStartTime}"); } totalChestsGenerated++; uint chestUniqueId = GetChestUniqueId(__instance); ShareChestPlugin.LogInfo($"[{chestUniqueId}] 宝箱生成 - 总计: {totalChestsGenerated}个, 类型: {((Object)((Component)__instance).gameObject).name}"); LogChestType(__instance); } } [HarmonyPatch(typeof(ChestBehavior), "OnDisable")] [HarmonyPostfix] private static void OnDisablePostfix(ChestBehavior __instance) { uint chestUniqueId = GetChestUniqueId(__instance); processedChests.Remove(chestUniqueId); } [HarmonyPatch(typeof(Run), "Start")] [HarmonyPostfix] private static void RunStartPostfix() { processedChests.Clear(); totalChestsGenerated = 0; chestsOpenedCount = 0; runStartTime = Time.time; if ((Object)(object)PlayerCountManager.Instance != (Object)null) { PlayerCountManager.Instance.Reset(); } ShareChestPlugin.LogInfo("===== 新对局开始 ====="); } [HarmonyPatch(typeof(Run), "OnDestroy")] [HarmonyPrefix] private static void RunOnDestroyPrefix() { if (totalChestsGenerated > 0) { float num = Time.time - runStartTime; int currentPlayerCount = ShareChestPlugin.GetCurrentPlayerCount(); ShareChestPlugin.LogInfo("===== 对局结束统计 ====="); ShareChestPlugin.LogInfo($"对局时长: {num:F1}秒"); ShareChestPlugin.LogInfo($"玩家数量: {currentPlayerCount}人"); ShareChestPlugin.LogInfo($"生成宝箱总数: {totalChestsGenerated}个"); ShareChestPlugin.LogInfo($"已打开宝箱数: {chestsOpenedCount}个"); ShareChestPlugin.LogInfo($"宝箱打开率: {(float)chestsOpenedCount * 100f / (float)totalChestsGenerated:F1}%"); ShareChestPlugin.LogInfo("=========================="); } } private static void LogChestType(ChestBehavior chest) { string text = ((Object)((Component)chest).gameObject).name.ToLower(); string text2 = "未知"; if (text.Contains("chest1")) { text2 = "普通宝箱"; } else if (text.Contains("chest2")) { text2 = "大型宝箱"; } else if (text.Contains("equipment")) { text2 = "装备桶"; } else if (text.Contains("lunar")) { text2 = "月球宝箱"; } else if (text.Contains("void")) { text2 = "虚空宝箱"; } else if (text.Contains("category")) { text2 = "分类宝箱"; } ShareChestPlugin.LogDebug("宝箱类型识别: " + text + " → " + text2); } private static void ExecuteMultiDrop(ChestBehavior chest, Transform dropTransform, UniquePickup basePickup, int dropCount) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00ca: Unknown result type (might be due to invalid IL or missing references) try { float num = 360f / (float)dropCount; float value = ShareChestPlugin.DropDistanceClamp.Value; float num2 = Mathf.Clamp(chest.dropForwardVelocityStrength, value, 7f); Vector3 val = Vector3.up * chest.dropUpVelocityStrength + Vector3.forward * num2; Quaternion val2 = Quaternion.AngleAxis(num, Vector3.up); Vector3 val3 = val; for (int i = 0; i < dropCount; i++) { CreatePickupInfo val4 = default(CreatePickupInfo); ((CreatePickupInfo)(ref val4)).pickup = basePickup; val4.position = dropTransform.position + Vector3.up * 1.5f; val4.chest = chest; val4.artifactFlag = (PickupArtifactFlag)(chest.isCommandChest ? 1 : 0); CreatePickupInfo val5 = val4; CreatePickupDropletSafe(val5, val5.position, val3); val3 = val2 * val3; } } catch (Exception ex) { ShareChestPlugin.LogError("ExecuteMultiDrop 错误: " + ex.Message); throw; } } private static void CreatePickupDropletSafe(CreatePickupInfo pickupInfo, Vector3 position, Vector3 velocity) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo method = typeof(PickupDropletController).GetMethod("CreatePickupDroplet", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3] { typeof(CreatePickupInfo), typeof(Vector3), typeof(Vector3) }, null); if (method != null) { method.Invoke(null, new object[3] { pickupInfo, position, velocity }); } else { PickupDropletController.CreatePickupDroplet(((CreatePickupInfo)(ref pickupInfo)).pickup.pickupIndex, position, velocity); } } catch (Exception ex) { ShareChestPlugin.LogError("创建掉落物失败: " + ex.Message); try { PickupDropletController.CreatePickupDroplet(((CreatePickupInfo)(ref pickupInfo)).pickup.pickupIndex, position, velocity); } catch { ShareChestPlugin.LogError("备用创建方案也失败"); } } } } }