using 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.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(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 ModEnabled; public static ConfigEntry EnableDynamicMultiplier; public static ConfigEntry FixedMultiplier; public static ConfigEntry EnableDebugLogs; public static ConfigEntry AffectedChestTypes; public static ConfigEntry DropDistanceClamp; private static readonly string ChestListSeparator = ","; private static HashSet affectedChestTypeSet = new HashSet(); public static AssetBundle MainAssets; private static List artifacts = new List(); 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(); 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("通用设置", "启用插件", true, new ConfigDescription("插件总开关。注意:同时需要神器“共享宝箱”启用才能生效。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 10, IsAdvanced = false } })); EnableDynamicMultiplier = ((BaseUnityPlugin)this).Config.Bind("掉落设置", "启用动态倍率", false, new ConfigDescription("是否根据玩家人数动态调整掉落倍率\n• true = 启用动态倍率(倍率 = 玩家人数)\n• false = 使用固定倍率", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 15, IsAdvanced = false } })); FixedMultiplier = ((BaseUnityPlugin)this).Config.Bind("掉落设置", "固定掉落倍率", 5, new ConfigDescription("当'启用动态倍率'为false时使用的固定掉落倍率\n• 1 = 正常掉落(原版行为)\n• 5 = 掉落5个相同物品(推荐)\n• 单人固定倍率推荐1,多人推荐动态倍率\n• 注意:过高的值可能影响游戏性能", (AcceptableValueBase)(object)new AcceptableValueRange(1, 50), new object[1] { new ConfigurationManagerAttributes { Order = 20, IsAdvanced = false } })); DropDistanceClamp = ((BaseUnityPlugin)this).Config.Bind("掉落设置", "掉落距离限制", 6f, new ConfigDescription("控制物品掉落时的最小距离限制\n• 默认值为6,不推荐更改\n• 较低的值使物品掉落更集中\n• 较高的值使物品掉落更分散\n• 注意:过高的值可能导致物品飞出太远", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 15f), new object[1] { new ConfigurationManagerAttributes { Order = 25, IsAdvanced = false } })); AffectedChestTypes = ((BaseUnityPlugin)this).Config.Bind("宝箱类型设置", "应用倍率的宝箱类型", "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("调试设置", "启用调试日志", 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 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("神器设置", 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 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 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()) { 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 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 processedChests = new HashSet(); 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()) { 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(); 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("备用创建方案也失败"); } } } } }