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 Equilibrium v2.1.1
Equilibrium.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; 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 System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates.ScavBackpack; using Equilibrium.Components; using Equilibrium.Config; using Equilibrium.Core; using Equilibrium.Hooks; using Equilibrium.Networking; using Equilibrium.ObjectHandlers; using Equilibrium.Utils; using HG.Reflection; using HarmonyLib; using IL.EntityStates.ScavBackpack; using IL.RoR2; using IL.RoR2.Hologram; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using On.RoR2; using On.RoR2.Artifacts; using On.RoR2.Hologram; using R2API; using R2API.Networking; using R2API.Networking.Interfaces; using R2API.Utils; using RoR2; using RoR2.Artifacts; using RoR2.Hologram; using UnityEngine; using UnityEngine.Events; 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: OptIn] [assembly: AssemblyTitle("Equilibrium")] [assembly: AssemblyDescription("Artifact of Equilibrium - Risk of Rain 2 Mod")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Muskmelovon")] [assembly: AssemblyProduct("Equilibrium")] [assembly: AssemblyCopyright("Copyright © Muskmelovon 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8da79297-920b-437a-aad8-e8c59d499508")] [assembly: AssemblyFileVersion("2.1.1")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.1.0")] [module: UnverifiableCode] namespace Equilibrium { public static class AssetBundleLoader { private static AssetBundle _bundle; private static bool _loaded; public static bool IsLoaded => _loaded; public static void LoadFromEmbeddedResource() { if (_loaded) { return; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "Equilibrium.Resources.equilibrium"; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { Debug.LogError((object)("[均衡神器] 嵌入资源未找到: " + text)); return; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); _bundle = AssetBundle.LoadFromMemory(array); if ((Object)(object)_bundle == (Object)null) { Debug.LogError((object)"[均衡神器] 无法从内存解析 AssetBundle!"); return; } _loaded = true; Debug.Log((object)"[均衡神器] AssetBundle 已从嵌入资源加载。"); } public static void LoadFromFile(string path) { if (!_loaded) { if (!File.Exists(path)) { Debug.LogError((object)("[均衡神器] 文件未找到: " + path)); return; } _bundle = AssetBundle.LoadFromFile(path); _loaded = (Object)(object)_bundle != (Object)null; } } public static Sprite GetSprite(params string[] assetNames) { //IL_008b: 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) if (!_loaded || (Object)(object)_bundle == (Object)null) { return null; } foreach (string text in assetNames) { Sprite val = _bundle.LoadAsset<Sprite>(text); if ((Object)(object)val != (Object)null) { return val; } Texture2D val2 = _bundle.LoadAsset<Texture2D>(text); if ((Object)(object)val2 != (Object)null) { return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f)); } } return null; } public static void Unload() { AssetBundle bundle = _bundle; if (bundle != null) { bundle.Unload(true); } _bundle = null; _loaded = false; } } [BepInPlugin("com.muskmelovon.equilibrium", "Equilibrium", "2.1.1")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Equilibrium : BaseUnityPlugin { public HookManager HookManager; public ObjectHandlerManager ObjectHandlerManager; public static ArtifactDef EquilibriumArtifactDef; private const string ArtifactLangTokenName = "EQUILIBRIUM"; private static bool _patched; public static bool IsCloningForInstance; private float nextResendTime = 0f; public global::Equilibrium.Config.Config ModConfig { get; private set; } public bool InteractionLoggingEnabled { get { global::Equilibrium.Config.Config modConfig = ModConfig; if (modConfig == null) { return false; } return modConfig.LogInstanceInteractions?.Value ?? false; } } public static Equilibrium Instance { get; private set; } internal ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; private string DisplayName => "Artifact of Equilibrium - 均衡神器"; private string ArtifactDescription => "“是故风雨时节,五谷丰登,社稷安宁。”\nTherefore, during the season of wind and rain, the crops yield abundantly, and the country enjoys peace and prosperity."; public void Awake() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown Instance = this; ModConfig = new global::Equilibrium.Config.Config(this, Logger); HookManager = new HookManager(this); ObjectHandlerManager = new ObjectHandlerManager(this); NetworkingAPI.RegisterMessageType<SyncInstances>(); LoadAssetBundle(); CreateLang(); EquilibriumArtifactDef = ScriptableObject.CreateInstance<ArtifactDef>(); EquilibriumArtifactDef.nameToken = "ARTIFACT_EQUILIBRIUM_NAME"; EquilibriumArtifactDef.descriptionToken = "ARTIFACT_EQUILIBRIUM_DESCRIPTION"; EquilibriumArtifactDef.smallIconSelectedSprite = AssetBundleLoader.GetSprite("equilibrium_selected") ?? CreatePlaceholderSprite(Color.green); EquilibriumArtifactDef.smallIconDeselectedSprite = AssetBundleLoader.GetSprite("equilibrium_deselected") ?? CreatePlaceholderSprite(Color.gray); ContentAddition.AddArtifactDef(EquilibriumArtifactDef); try { EquilibriumManager.Init(); } catch (Exception arg) { Logger.LogWarning((object)$"[均衡神器] 调用 EquilibriumManager.Init() 失败:{arg}"); } if (!_patched) { Harmony val = new Harmony("com.muskmelovon.equilibrium"); val.PatchAll(); _patched = true; Logger.LogInfo((object)"[均衡神器] Harmony 补丁已应用"); } LogInfo("[均衡神器] 插件加载完成 | F5=调试信息 | F6=强制刷新"); GameObject val2 = new GameObject("PlayerManager"); val2.AddComponent<PlayerManager>(); Object.DontDestroyOnLoad((Object)(object)val2); Logger.LogInfo((object)"[均衡神器] 插件 Awake 完成"); } public void Start() { Logger.LogInfo((object)"[均衡神器] Start 完成"); } public void OnEnable() { Instance = this; PlayerCharacterMasterController.onPlayerAdded += OnPlayerAdded; HookManager.RegisterHooks(); Logger.LogInfo((object)"[均衡神器] 已启用并注册钩子"); } public void OnDisable() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } HookManager.UnregisterHooks(); PlayerCharacterMasterController.onPlayerAdded -= OnPlayerAdded; InteractionDiagnostics.Clear(); SyncInstances.ClearPending(); Logger.LogInfo((object)"[均衡神器] 已禁用并注销钩子"); } public void Update() { if (Input.GetKeyDown((KeyCode)286)) { ShowPlayerListInfo(); } if (Input.GetKeyDown((KeyCode)287)) { ForceRefresh(); } if (NetworkServer.active && Time.time >= nextResendTime) { nextResendTime = Time.time + 10f; ResendAllInstances(); } if (!NetworkServer.active) { SyncInstances.CheckTimeouts(); } } private void ResendAllInstances() { foreach (InstanceHandler instance in InstanceHandler.Instances) { if (Object.op_Implicit((Object)(object)instance) && instance.SharedInfo != null) { instance.SharedInfo.SyncToAll(); } } } private static bool IsHostUser(NetworkUser user) { if ((Object)(object)user == (Object)null) { return false; } if (NetworkServer.active && NetworkClient.active) { return ((NetworkBehaviour)user).isLocalPlayer; } if (!NetworkServer.active && NetworkClient.active) { return ((NetworkBehaviour)user).playerControllerId == -1; } return ((NetworkBehaviour)user).isLocalPlayer; } private static void ShowPlayerListInfo() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) LogInfo("========== [均衡神器] 玩家列表信息 =========="); Scene activeScene = SceneManager.GetActiveScene(); LogInfo("当前场景: " + ((Scene)(ref activeScene)).name); int num = NetworkUser.readOnlyInstancesList?.Count ?? 0; LogInfo($"NetworkUser 玩家数量: {num}人"); if (NetworkUser.readOnlyInstancesList == null || num == 0) { LogInfo("玩家列表为空"); LogInfo("============================================="); return; } foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { if (Object.op_Implicit((Object)(object)readOnlyInstances)) { string text = (IsHostUser(readOnlyInstances) ? "[Host]" : "[Client]"); string text2 = (((NetworkBehaviour)readOnlyInstances).isLocalPlayer ? " (You)" : ""); LogInfo(text + " " + readOnlyInstances.userName + text2); } } LogInfo("============================================="); } private static void ForceRefresh() { LogInfo(">>> 正在强制刷新玩家数据..."); if ((Object)(object)PlayerManager.Instance != (Object)null) { PlayerManager.Instance.RecalculatePlayerCount(); LogInfo($">>> 刷新完成,当前玩家数: {PlayerManager.Instance.CurrentPlayerCount}人"); } else { LogError(">>> 刷新失败:PlayerManager 未初始化"); } } private void OnPlayerAdded(PlayerCharacterMasterController player) { if (!NetworkServer.active) { return; } object obj; if (player == null) { obj = null; } else { NetworkUser networkUser = player.networkUser; obj = ((networkUser != null) ? ((NetworkBehaviour)networkUser).connectionToClient : null); } if (obj == null) { return; } HashSet<InstanceHandler> hashSet = new HashSet<InstanceHandler>(); foreach (InstanceHandler instance in InstanceHandler.Instances) { InstanceHandler instanceHandler = instance.LinkedHandlers?[0] ?? instance; if ((Object)(object)instanceHandler != (Object)null && !hashSet.Contains(instanceHandler)) { hashSet.Add(instanceHandler); instanceHandler.SyncToPlayer(player); } } Logger.LogInfo((object)("[均衡神器] 向新加入玩家 " + player.networkUser?.userName + " 下发实例快照")); } public void HandleInstancing(GameObject obj, InstanceInfoTracker.InstanceOverrideInfo? overrideInfo = null, bool isObject = true) { //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj.GetComponent<TeleporterInteraction>() != (Object)null || (Object)(object)obj.GetComponent<PickupDropletController>() != (Object)null) { return; } InstanceInfoTracker component = obj.GetComponent<InstanceInfoTracker>(); InstanceInfoTracker.InstanceOverrideInfo? instanceOverrideInfo = component?.Info; string text = overrideInfo?.ObjectType ?? instanceOverrideInfo?.ObjectType; PlayerCharacterMasterController val = overrideInfo?.Owner ?? instanceOverrideInfo?.Owner; if ((Object)(object)component == (Object)null && text == null) { return; } InstanceMode mode = ModConfig.GetMode(text ?? instanceOverrideInfo?.ObjectType); if (mode == InstanceMode.None) { return; } bool flag = false; bool flag2 = false; if (instanceOverrideInfo?.ObjectType == null) { InstanceMode instanceMode = mode; InstanceMode instanceMode2 = instanceMode; if ((uint)(instanceMode2 - 1) <= 1u) { flag = true; flag2 = false; } } bool flag3 = false; GenericPickupController component2 = obj.GetComponent<GenericPickupController>(); if ((Object)(object)component2 != (Object)null) { PickupDef pickupDef = PickupCatalog.GetPickupDef(component2.pickupIndex); if (((pickupDef == null) ? (-1) : ((int)pickupDef.itemIndex)) != -1) { goto IL_0190; } } if ((Object)(object)obj.GetComponent<PickupPickerController>() != (Object)null) { goto IL_0190; } goto IL_01c5; IL_0190: if (!isObject) { flag3 = true; switch (mode) { case InstanceMode.InstanceObject: flag = false; break; case InstanceMode.InstanceBoth: flag = true; flag2 = true; break; } } goto IL_01c5; IL_01c5: if (!flag3 && flag) { flag = ObjectHandlerManager.CanInstanceObject(text, obj); } overrideInfo?.AttachTo(obj); if (flag && (!flag2 || !((Object)(object)val == (Object)null) || !((Object)(object)instanceOverrideInfo?.Owner == (Object)null))) { HashSet<PlayerCharacterMasterController> source = ((!flag2) ? ModConfig.GetValidPlayers() : new HashSet<PlayerCharacterMasterController> { val }); List<PlayerCharacterMasterController> list = source.ToList(); PlayerCharacterMasterController val2 = ((IEnumerable<PlayerCharacterMasterController>)list).FirstOrDefault((Func<PlayerCharacterMasterController, bool>)((PlayerCharacterMasterController p) => Object.op_Implicit((Object)(object)p.networkUser) && ((NetworkBehaviour)p.networkUser).isServer)); if ((Object)(object)val2 != (Object)null && list.IndexOf(val2) != 0) { list.Remove(val2); list.Insert(0, val2); } if (flag3) { InstanceHandler instanceHandler = obj.AddComponent<InstanceHandler>(); instanceHandler.SharedInfo = new InstanceHandler.SharedInstanceInfo { ObjectInstanceMode = ObjectInstanceMode.InstancedObject }; instanceHandler.SetPlayers(list); } else { ObjectHandlerManager.InstanceObject(text, obj, list.ToArray()); } Logger.LogInfo((object)$"[均衡神器] 对象 {((Object)obj).name} 应用实例化策略: {mode} (objectType={text}, isObject={isObject})"); } } public static bool CanUninstance(InstanceHandler handler, PlayerCharacterMasterController player) { if (!handler.Players.Contains(player)) { return false; } return handler.AllPlayers.Count == 1 || Object.op_Implicit((Object)(object)((Component)handler).GetComponent<CreatePickupInfoTracker>()); } public static void LogDebug(string message) { Equilibrium instance = Instance; if (instance != null) { instance.Logger.LogInfo((object)("[调试] " + message)); } } public static void LogWarning(string message) { Equilibrium instance = Instance; if (instance != null) { instance.Logger.LogWarning((object)("[警告] " + message)); } } public static void LogError(string message) { Equilibrium instance = Instance; if (instance != null) { instance.Logger.LogError((object)("[错误] " + message)); } } public static void LogInfo(string message) { Equilibrium instance = Instance; if (instance != null) { instance.Logger.LogInfo((object)("[信息] " + message)); } } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCReloadConfig(ConCommandArgs args) { if ((Object)(object)Instance == (Object)null) { return; } try { ((BaseUnityPlugin)Instance).Config.Reload(); Instance.ModConfig.OnConfigReloaded(); Instance.Logger.LogInfo((object)"[均衡神器] 配置已重新加载并应用。"); } catch (Exception arg) { Instance.Logger.LogError((object)$"[均衡神器] 重新加载配置时出错:{arg}"); } } private IEnumerable<NetworkUser> GetPlayersFromPartial(string name) { if (string.IsNullOrEmpty(name)) { return NetworkUser.readOnlyInstancesList; } if (int.TryParse(name, out var result)) { if (result >= 0 && result < NetworkUser.readOnlyInstancesList.Count) { return new List<NetworkUser> { NetworkUser.readOnlyInstancesList[result] }; } return new List<NetworkUser>(); } name = name.ToUpperInvariant(); List<NetworkUser> list = new List<NetworkUser>(); foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { if ((Object)(object)readOnlyInstances != (Object)null && readOnlyInstances.userName.ToUpperInvariant().Contains(name)) { list.Add(readOnlyInstances); } } return list; } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCPlayerList(ConCommandArgs args) { try { string text = ((((ConCommandArgs)(ref args)).Count > 0) ? ((ConCommandArgs)(ref args))[0] : ""); IEnumerable<NetworkUser> playersFromPartial = Instance.GetPlayersFromPartial(text); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"========== 当前玩家列表 (共 {playersFromPartial.Count()} 人) =========="); int num = 0; foreach (NetworkUser item in playersFromPartial) { if (!((Object)(object)item == (Object)null)) { string text2 = (IsHostUser(item) ? "[Host]" : "[Client]"); string text3 = (((NetworkBehaviour)item).isLocalPlayer ? " (You)" : ""); stringBuilder.AppendLine($"[{num}] {text2} {item.userName}{text3}"); num++; } } if (stringBuilder.Length > 0) { LogInfo(stringBuilder.ToString()); } else { LogInfo("找不到匹配 \"" + text + "\" 的玩家。"); } } catch (Exception ex) { LogError("获取玩家列表时出错: " + ex.Message); } } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCDebugUser(ConCommandArgs args) { //IL_0084: 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_008d: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("========== NetworkUser 调试 =========="); stringBuilder.AppendLine($"本机: NetworkServer.active={NetworkServer.active}, NetworkClient.active={NetworkClient.active}"); foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { if (!((Object)(object)readOnlyInstances == (Object)null)) { stringBuilder.AppendLine("--- " + readOnlyInstances.userName + " ---"); NetworkUserId id = readOnlyInstances.id; stringBuilder.AppendLine($" id.steamId: {((NetworkUserId)(ref id)).steamId}"); stringBuilder.AppendLine($" isLocalPlayer: {((NetworkBehaviour)readOnlyInstances).isLocalPlayer}"); stringBuilder.AppendLine($" hasAuthority: {((NetworkBehaviour)readOnlyInstances).hasAuthority}"); stringBuilder.AppendLine($" isServer: {((NetworkBehaviour)readOnlyInstances).isServer}"); stringBuilder.AppendLine($" isClient: {((NetworkBehaviour)readOnlyInstances).isClient}"); stringBuilder.AppendLine($" authed: {readOnlyInstances.authed}"); } } LogInfo(stringBuilder.ToString()); } protected void CreateLang() { LanguageAPI.Add("ARTIFACT_EQUILIBRIUM_NAME", DisplayName); LanguageAPI.Add("ARTIFACT_EQUILIBRIUM_DESCRIPTION", ArtifactDescription); Logger.LogInfo((object)("[均衡神器] 语言条目已注册:" + DisplayName)); } private void LoadAssetBundle() { AssetBundleLoader.LoadFromEmbeddedResource(); if (!AssetBundleLoader.IsLoaded) { string path = Path.Combine(Paths.PluginPath, "Equilibrium", "equilibrium"); AssetBundleLoader.LoadFromFile(path); } } private Sprite CreatePlaceholderSprite(Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0063: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64); Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < array.Length; i++) { array[i] = color; } val.SetPixels(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f)); } private void OnDestroy() { AssetBundleLoader.Unload(); } } public static class EquilibriumManager { private static bool _initialized; private static bool artifactEnabled = false; private static bool configEnabled = true; public static bool IsEnabled { get; private set; } public static void Init() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown if (!_initialized) { _initialized = true; artifactEnabled = false; configEnabled = true; UpdateIsEnabled(); RunArtifactManager.onArtifactEnabledGlobal += new ArtifactStateChangeDelegate(OnArtifactEnabled); RunArtifactManager.onArtifactDisabledGlobal += new ArtifactStateChangeDelegate(OnArtifactDisabled); } } private static void OnArtifactEnabled(RunArtifactManager manager, ArtifactDef def) { if ((Object)(object)def == (Object)(object)Equilibrium.EquilibriumArtifactDef) { artifactEnabled = true; UpdateIsEnabled(); } } private static void OnArtifactDisabled(RunArtifactManager manager, ArtifactDef def) { if ((Object)(object)def == (Object)(object)Equilibrium.EquilibriumArtifactDef) { artifactEnabled = false; UpdateIsEnabled(); } } public static void SetConfigEnabled(bool enabled) { configEnabled = enabled; UpdateIsEnabled(); } private static void UpdateIsEnabled() { IsEnabled = artifactEnabled && configEnabled; } public static void Cleanup() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if (_initialized) { RunArtifactManager.onArtifactEnabledGlobal -= new ArtifactStateChangeDelegate(OnArtifactEnabled); RunArtifactManager.onArtifactDisabledGlobal -= new ArtifactStateChangeDelegate(OnArtifactDisabled); _initialized = false; artifactEnabled = false; configEnabled = true; UpdateIsEnabled(); } } } public class PlayerManager : MonoBehaviour { private float lastRecalculateTime = 0f; private const float RECALCULATE_INTERVAL = 2f; public static PlayerManager 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(); Equilibrium.LogInfo($"[PlayerManager] 初始化完成,当前玩家数: {CurrentPlayerCount}"); ((MonoBehaviour)this).InvokeRepeating("PeriodicCheck", 5f, 5f); } catch (Exception ex) { Exception ex2 = ex; Equilibrium.LogError("[PlayerManager] 初始化失败: " + ex2.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)); Equilibrium.LogInfo("[PlayerManager] 玩家加入: " + joinedUser.userName); } private void OnPlayerLost(NetworkUser lostUser) { ((MonoBehaviour)this).StartCoroutine(UpdatePlayerCountDelayed(1f)); Equilibrium.LogInfo("[PlayerManager] 玩家离开: " + lostUser?.userName); } private void OnSceneChanged(Scene oldScene, Scene newScene) { RecalculatePlayerCount(); Equilibrium.LogInfo($"[PlayerManager] 场景变化: {((Scene)(ref oldScene)).name} -> {((Scene)(ref newScene)).name}, 玩家数: {CurrentPlayerCount}"); SyncInstances.ClearPending(); } 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; } 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++; } } } else { CurrentPlayerCount = 1; Equilibrium.LogDebug("[PlayerManager] 单人游戏模式: 1人"); } if (CurrentPlayerCount != currentPlayerCount) { Equilibrium.LogInfo($"[PlayerManager] 玩家数量变化: {currentPlayerCount} -> {CurrentPlayerCount}"); } lastRecalculateTime = Time.time; } catch (Exception ex) { Equilibrium.LogError("重新计算玩家数量失败: " + ex.Message); CurrentPlayerCount = Math.Max(1, currentPlayerCount); } } public void Reset() { CurrentPlayerCount = 0; RecalculatePlayerCount(); } } } namespace Equilibrium.Utils { public enum InstanceMode { None, InstanceObject, InstanceBoth } public enum ObjectInstanceMode { None, CopyObject, InstancedObject } public static class ObjectType { public const string Chest1 = "Chest1"; public const string Chest2 = "Chest2"; public const string GoldChest = "GoldChest"; public const string Chest1StealthedVariant = "Chest1StealthedVariant"; public const string CategoryChestDamage = "CategoryChestDamage"; public const string CategoryChestHealing = "CategoryChestHealing"; public const string CategoryChestUtility = "CategoryChestUtility"; public const string CategoryChest2Damage = "CategoryChest2Damage"; public const string CategoryChest2Healing = "CategoryChest2Healing"; public const string CategoryChest2Utility = "CategoryChest2Utility"; public const string EquipmentBarrel = "EquipmentBarrel"; public const string LunarChest = "LunarChest"; public const string VoidChest = "VoidChest"; public const string Lockbox = "Lockbox"; public const string ScavBackpack = "ScavBackpack"; public const string ShrineChance = "ShrineChance"; public const string ShrineBlood = "ShrineBlood"; public const string ShrineRestack = "ShrineRestack"; public const string TripleShop = "TripleShop"; public const string TripleShopLarge = "TripleShopLarge"; public const string TripleShopEquipment = "TripleShopEquipment"; public const string FreeChestMultiShop = "FreeChestMultiShop"; public const string VoidTriple = "VoidTriple"; public const string LockboxVoid = "LockboxVoid"; public const string Sacrifice = "Sacrifice"; public const string HuntersTricorn = "HuntersTricorn"; public const string SonorousWhispers = "SonorousWhispers"; public const string TeleporterBoss = "TeleporterBoss"; public const string SuperRoboBallEncounter = "SuperRoboBallEncounter"; public const string BossGroup = "BossGroup"; } public static class Utils { public static bool IsObjectInteractibleForPlayer(GameObject gameObject, PlayerCharacterMasterController player) { if ((Object)(object)gameObject == (Object)null) { return true; } InstanceHandler component = gameObject.GetComponent<InstanceHandler>(); if ((Object)(object)component != (Object)null) { if (component.AllPlayers.Contains(player)) { return component.LinkedHandlers.Where((InstanceHandler h) => h.Players.Contains(player)).Any(delegate(InstanceHandler h) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 IInteractable component2 = ((Component)h).GetComponent<IInteractable>(); if (component2 != null) { CharacterBody body = player.body; if (Object.op_Implicit((Object)(object)body)) { Interactor component3 = ((Component)body).GetComponent<Interactor>(); if (Object.op_Implicit((Object)(object)component3)) { return (int)component2.GetInteractability(component3) > 0; } } } return true; }); } return false; } return true; } public static bool IsObjectInstanceInteractibleForPlayer(GameObject gameObject, PlayerCharacterMasterController player) { if ((Object)(object)gameObject == (Object)null) { return true; } InstanceHandler component = gameObject.GetComponent<InstanceHandler>(); if ((Object)(object)component != (Object)null) { return component.Players.Contains(player); } return true; } public static bool IsObjectInteractibleForCameraRigController(GameObject gameObject, CameraRigController cameraRigController) { if ((Object)(object)cameraRigController == (Object)null) { return true; } CharacterBody targetBody = cameraRigController.targetBody; if ((Object)(object)targetBody == (Object)null) { return true; } CharacterMaster master = targetBody.master; if ((Object)(object)master == (Object)null) { return true; } PlayerCharacterMasterController playerCharacterMasterController = master.playerCharacterMasterController; if ((Object)(object)playerCharacterMasterController == (Object)null) { return true; } return IsObjectInteractibleForPlayer(gameObject, playerCharacterMasterController); } public static bool IncreasesItemCount(InstanceMode instanceMode) { if ((uint)(instanceMode - 1) <= 1u) { return true; } return false; } } } namespace Equilibrium.ObjectHandlers { public class ChestHandler : AbstractObjectHandler { public override string[] HandledObjectTypes { get; } = new string[15] { "Chest1", "Chest2", "GoldChest", "Chest1StealthedVariant", "CategoryChestDamage", "CategoryChestHealing", "CategoryChestUtility", "CategoryChest2Damage", "CategoryChest2Healing", "CategoryChest2Utility", "EquipmentBarrel", "LunarChest", "VoidChest", "Lockbox", "ScavBackpack" }; public override ObjectInstanceMode ObjectInstanceMode => ObjectInstanceMode.CopyObject; public override bool CanObjectBeOwned(string objectType) { return objectType == "Lockbox"; } public override bool IsValidForObject(string objectType, GameObject gameObject) { return (Object)(object)gameObject.GetComponent<ChestBehavior>() != (Object)null; } public override void Init(ObjectHandlerManager manager) { base.Init(manager); base.Plugin.HookManager.RegisterHandler<ChestBehaviorHandler>(); base.Plugin.HookManager.RegisterHandler<ScavBackpackOpeningHandler>(); } public override InstanceHandler InstanceSingleObjectFrom(GameObject source, GameObject target, PlayerCharacterMasterController[] players) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown ChestBehavior component = source.GetComponent<ChestBehavior>(); ChestBehavior component2 = target.GetComponent<ChestBehavior>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { if (base.Plugin.ModConfig.ARollDrop.Value) { component2.rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong); component2.Roll(); component2.dropCount = component.dropCount; component2.dropTable = component.dropTable; } else { component2.rng = new Xoroshiro128Plus(component.rng); component2.dropCount = component.dropCount; component2.currentPickup = component.currentPickup; } } return base.InstanceSingleObjectFrom(source, target, players); } } public class MultiShopHandler : AbstractObjectHandler { public override string[] HandledObjectTypes { get; } = new string[4] { "TripleShop", "TripleShopLarge", "TripleShopEquipment", "FreeChestMultiShop" }; public override ObjectInstanceMode ObjectInstanceMode => ObjectInstanceMode.CopyObject; public override bool CanObjectBeOwned(string objectType) { return objectType == "FreeChestMultiShop"; } public override bool IsValidForObject(string objectType, GameObject gameObject) { return (Object)(object)gameObject.GetComponent<MultiShopController>() != (Object)null || (Object)(object)gameObject.GetComponent<ShopTerminalBehavior>() != (Object)null; } public override void Init(ObjectHandlerManager manager) { base.Init(manager); base.Plugin.HookManager.RegisterHandler<MultiShopControllerHandler>(); } public override InstanceHandler InstanceSingleObjectFrom(GameObject source, GameObject target, PlayerCharacterMasterController[] players) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) InstanceHandler instanceHandler = base.InstanceSingleObjectFrom(source, target, players); if ((Object)(object)source == (Object)(object)target) { InstanceInfoTracker component = source.GetComponent<InstanceInfoTracker>(); MultiShopController component2 = source.GetComponent<MultiShopController>(); ShopTerminalBehavior component3 = source.GetComponent<ShopTerminalBehavior>(); if ((Object)(object)component2 != (Object)null) { GameObject[] terminalGameObjects = component2.terminalGameObjects; foreach (GameObject val in terminalGameObjects) { InstanceSingleObjectFrom(val, val, players); component?.Info.AttachTo(val); } } if ((Object)(object)component3 != (Object)null) { instanceHandler.SharedInfo = new InstanceHandler.SharedInstanceInfo { SourceObject = target, ObjectInstanceMode = ObjectInstanceMode }; } } else { MultiShopController component4 = target.GetComponent<MultiShopController>(); if ((Object)(object)component4 != (Object)null) { MultiShopController component5 = source.GetComponent<MultiShopController>(); component4.rng = new Xoroshiro128Plus(0uL); component4.CreateTerminals(); component4.Networkcost = component5.Networkcost; component4.rng = new Xoroshiro128Plus(component5.rng); for (int j = 0; j < component4.terminalGameObjects.Length; j++) { AwaitObjectFor(component4.terminalGameObjects[j], new AwaitedObjectInfo { SourceObject = component5.terminalGameObjects[j], Players = players }); } } ShopTerminalBehavior component6 = target.GetComponent<ShopTerminalBehavior>(); if ((Object)(object)component6 != (Object)null) { ShopTerminalBehavior component7 = source.GetComponent<ShopTerminalBehavior>(); component6.hasStarted = true; component6.rng = new Xoroshiro128Plus(component7.rng); component6.Networkpickup = component7.Networkpickup; component6.Networkhidden = component7.Networkhidden; component6.UpdatePickupDisplayAndAnimations(); } PurchaseInteraction component8 = target.GetComponent<PurchaseInteraction>(); if ((Object)(object)component8 != (Object)null) { PurchaseInteraction component9 = source.GetComponent<PurchaseInteraction>(); component8.rng = component9.rng; component8.Networkcost = component9.Networkcost; } } return instanceHandler; } } public class OptionChestHandler : AbstractObjectHandler { public override string[] HandledObjectTypes { get; } = new string[2] { "VoidTriple", "LockboxVoid" }; public override ObjectInstanceMode ObjectInstanceMode => ObjectInstanceMode.CopyObject; public override bool CanObjectBeOwned(string objectType) { return objectType == "LockboxVoid"; } public override bool IsValidForObject(string objectType, GameObject gameObject) { return (Object)(object)gameObject.GetComponent<OptionChestBehavior>() != (Object)null; } public override void Init(ObjectHandlerManager manager) { base.Init(manager); base.Plugin.HookManager.RegisterHandler<OptionChestBehaviorHandler>(); } public override InstanceHandler InstanceSingleObjectFrom(GameObject source, GameObject target, PlayerCharacterMasterController[] players) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown OptionChestBehavior component = source.GetComponent<OptionChestBehavior>(); OptionChestBehavior component2 = target.GetComponent<OptionChestBehavior>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { component2.rng = new Xoroshiro128Plus(component.rng); component2.generatedPickups = component.generatedPickups; } return base.InstanceSingleObjectFrom(source, target, players); } } public class ShrineChanceHandler : AbstractObjectHandler { public override ObjectInstanceMode ObjectInstanceMode => ObjectInstanceMode.CopyObject; public override string[] HandledObjectTypes { get; } = new string[1] { "ShrineChance" }; public override bool IsValidForObject(string objectType, GameObject gameObject) { return (Object)(object)gameObject.GetComponent<ShrineChanceBehavior>() != (Object)null; } public override void Init(ObjectHandlerManager manager) { base.Init(manager); base.Plugin.HookManager.RegisterHandler<ShrineBehaviorHandler>(); } public override InstanceHandler InstanceSingleObjectFrom(GameObject source, GameObject target, PlayerCharacterMasterController[] players) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown ShrineChanceBehavior component = source.GetComponent<ShrineChanceBehavior>(); ShrineChanceBehavior component2 = target.GetComponent<ShrineChanceBehavior>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { component2.rng = new Xoroshiro128Plus(component.rng); component2.purchaseInteraction.Networkcost = component.purchaseInteraction.Networkcost; } return base.InstanceSingleObjectFrom(source, target, players); } } public class SpecialItemHandler : AbstractObjectHandler { public override string[] HandledObjectTypes { get; } = new string[5] { "Sacrifice", "HuntersTricorn", "TeleporterBoss", "SuperRoboBallEncounter", "BossGroup" }; public override ObjectInstanceMode ObjectInstanceMode => ObjectInstanceMode.CopyObject; public override void Init(ObjectHandlerManager manager) { base.Init(manager); base.Plugin.HookManager.RegisterHandler<SacrificeArtifactManagerHandler>(); base.Plugin.HookManager.RegisterHandler<BossGroupHandler>(); base.Plugin.HookManager.RegisterHandler<BossHunterHandler>(); } } public class SpecialObjectHandler : AbstractObjectHandler { public override string[] HandledObjectTypes { get; } = new string[2] { "ShrineBlood", "ShrineRestack" }; public override ObjectInstanceMode ObjectInstanceMode => ObjectInstanceMode.CopyObject; public override void Init(ObjectHandlerManager manager) { base.Init(manager); base.Plugin.HookManager.RegisterHandler<ShrineBehaviorHandler>(); } public override InstanceHandler InstanceSingleObjectFrom(GameObject source, GameObject target, PlayerCharacterMasterController[] players) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown ShrineRestackBehavior component = target.GetComponent<ShrineRestackBehavior>(); if ((Object)(object)component != (Object)null) { ShrineRestackBehavior component2 = source.GetComponent<ShrineRestackBehavior>(); component.purchaseInteraction = ((Component)component).GetComponent<PurchaseInteraction>(); component.rng = new Xoroshiro128Plus(component2.rng); } ShrineBloodBehavior component3 = target.GetComponent<ShrineBloodBehavior>(); if ((Object)(object)component3 != (Object)null) { component3.purchaseInteraction = ((Component)component3).GetComponent<PurchaseInteraction>(); } return base.InstanceSingleObjectFrom(source, target, players); } } } namespace Equilibrium.Networking { public class SyncInstances : INetMessage, ISerializableObject { public struct InstanceHandlerEntry { public GameObject target; public GameObject[] players; public GameObject origPlayer; public NetworkInstanceId _target; public NetworkInstanceId[] _players; public NetworkInstanceId _origPlayer; public int Cost; public CostTypeIndex CostType; private bool validated; public InstanceHandlerEntry(InstanceHandler instanceHandler) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) target = ((Component)instanceHandler).gameObject; players = instanceHandler.Players.Select((PlayerCharacterMasterController p) => ((Component)p).gameObject).ToArray(); PlayerCharacterMasterController obj = instanceHandler.OrigPlayer; origPlayer = ((obj != null) ? ((Component)obj).gameObject : null); _target = NetworkInstanceId.Invalid; _players = Array.Empty<NetworkInstanceId>(); _origPlayer = NetworkInstanceId.Invalid; PurchaseInteraction component = ((Component)instanceHandler).GetComponent<PurchaseInteraction>(); Cost = (((Object)(object)component != (Object)null) ? component.cost : 0); CostType = (CostTypeIndex)(((Object)(object)component != (Object)null) ? ((int)component.costType) : 0); validated = true; } public bool TryProcess() { //IL_0014: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) if (validated) { return true; } target = Util.FindNetworkObject(_target); if ((Object)(object)target == (Object)null) { return false; } if (_origPlayer != NetworkInstanceId.Invalid) { origPlayer = Util.FindNetworkObject(_origPlayer); } players = (GameObject[])(object)new GameObject[_players.Length]; for (int i = 0; i < _players.Length; i++) { players[i] = Util.FindNetworkObject(_players[i]); } validated = true; return true; } public void Serialize(NetworkWriter writer) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0098: Expected I4, but got Unknown writer.Write(target.GetComponent<NetworkIdentity>().netId); writer.Write(((Object)(object)origPlayer == (Object)null) ? NetworkInstanceId.Invalid : origPlayer.GetComponent<NetworkIdentity>().netId); writer.Write(players.Length); GameObject[] array = players; foreach (GameObject val in array) { writer.Write(val.GetComponent<NetworkIdentity>().netId); } writer.Write(Cost); writer.Write((int)CostType); } public static InstanceHandlerEntry Deserialize(NetworkReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) InstanceHandlerEntry result = new InstanceHandlerEntry { validated = false, _target = reader.ReadNetworkId(), _origPlayer = reader.ReadNetworkId() }; int num = reader.ReadInt32(); result._players = (NetworkInstanceId[])(object)new NetworkInstanceId[num]; for (int i = 0; i < num; i++) { result._players[i] = reader.ReadNetworkId(); } result.Cost = reader.ReadInt32(); result.CostType = (CostTypeIndex)reader.ReadInt32(); return result; } } private class PendingInfo { public SyncInstances Message; public float Timestamp; } private NetworkInstanceId _sourceObject; private ObjectInstanceMode objectInstanceMode; private InstanceHandlerEntry[] entries; private static readonly List<PendingInfo> PendingMessages = new List<PendingInfo>(); public static bool IsPending(GameObject target) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)target)) { return false; } NetworkIdentity component = target.GetComponent<NetworkIdentity>(); if (!Object.op_Implicit((Object)(object)component)) { return false; } NetworkInstanceId targetId = component.netId; return PendingMessages.Any((PendingInfo msg) => msg.Message.entries.Any((InstanceHandlerEntry e) => e._target == targetId)); } public static void ClearPending() { PendingMessages.Clear(); } public SyncInstances() { entries = Array.Empty<InstanceHandlerEntry>(); } public SyncInstances(InstanceHandler.SharedInstanceInfo instanceInfo) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) entries = instanceInfo.LinkedHandlers.Select((InstanceHandler h) => new InstanceHandlerEntry(h)).ToArray(); objectInstanceMode = instanceInfo.ObjectInstanceMode; _sourceObject = (((Object)(object)instanceInfo.SourceObject == (Object)null) ? NetworkInstanceId.Invalid : instanceInfo.SourceObject.GetComponent<NetworkIdentity>().netId); } public void Serialize(NetworkWriter writer) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) writer.Write((int)objectInstanceMode); writer.Write(_sourceObject); writer.Write(entries.Length); InstanceHandlerEntry[] array = entries; foreach (InstanceHandlerEntry instanceHandlerEntry in array) { instanceHandlerEntry.Serialize(writer); } } public void Deserialize(NetworkReader reader) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) objectInstanceMode = (ObjectInstanceMode)reader.ReadInt32(); _sourceObject = reader.ReadNetworkId(); int num = reader.ReadInt32(); entries = new InstanceHandlerEntry[num]; for (int i = 0; i < num; i++) { entries[i] = InstanceHandlerEntry.Deserialize(reader); } } public void OnReceived() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { PendingMessages.Add(new PendingInfo { Message = this, Timestamp = Time.realtimeSinceStartup }); ((MonoBehaviour)Equilibrium.Instance).StartCoroutine(HandleMessage(objectInstanceMode, entries, _sourceObject)); } } private IEnumerator HandleMessage(ObjectInstanceMode mode, InstanceHandlerEntry[] entries, NetworkInstanceId sourceId) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) bool validated = false; int retryCount = 0; GameObject sourceObject = null; while (!validated && retryCount < 20) { retryCount++; validated = true; for (int i = 0; i < entries.Length; i++) { if (!entries[i].TryProcess()) { validated = false; } } if ((Object)(object)sourceObject == (Object)null && sourceId != NetworkInstanceId.Invalid) { sourceObject = Util.FindNetworkObject(sourceId); } if (!validated) { yield return null; } } try { InstanceHandler.SharedInstanceInfo sharedInfo = new InstanceHandler.SharedInstanceInfo { ObjectInstanceMode = mode, SourceObject = sourceObject }; PlayerCharacterMasterController pc = default(PlayerCharacterMasterController); for (int j = 0; j < entries.Length; j++) { InstanceHandlerEntry entry = entries[j]; GameObject target = Util.FindNetworkObject(entry._target); if ((Object)(object)target == (Object)null) { continue; } PurchaseInteraction pi = target.GetComponent<PurchaseInteraction>(); if ((Object)(object)pi != (Object)null && entry.Cost > 0) { pi.cost = entry.Cost; pi.Networkcost = entry.Cost; pi.costType = entry.CostType; } InstanceHandler handler = target.GetComponent<InstanceHandler>(); if ((Object)(object)handler == (Object)null) { handler = target.AddComponent<InstanceHandler>(); } List<PlayerCharacterMasterController> validPlayers = new List<PlayerCharacterMasterController>(); if (entry.players != null) { GameObject[] players = entry.players; foreach (GameObject pObj in players) { int num; if (Object.op_Implicit((Object)(object)pObj)) { pc = pObj.GetComponent<PlayerCharacterMasterController>(); num = 1; } else { num = 0; } if (num != 0) { validPlayers.Add(pc); } pc = null; } } handler.SetPlayers(validPlayers, sync: false); if ((Object)(object)entry.origPlayer != (Object)null) { handler.OrigPlayer = entry.origPlayer.GetComponent<PlayerCharacterMasterController>(); } if ((Object)(object)sourceObject != (Object)null) { target.transform.position = sourceObject.transform.position; target.transform.rotation = sourceObject.transform.rotation; target.transform.localScale = sourceObject.transform.localScale; } handler.SharedInfo = sharedInfo; } sharedInfo.RecalculateAllPlayers(); foreach (InstanceHandler handler2 in InstanceHandler.Instances) { if (Object.op_Implicit((Object)(object)handler2) && handler2.SharedInfo == sharedInfo) { handler2.UpdateVisuals(); } } } catch (Exception ex) { Exception e = ex; Equilibrium.Instance.Logger.LogError((object)$"[均衡神器] 应用网络同步数据时出错: {e}"); } finally { PendingInfo info = PendingMessages.FirstOrDefault((PendingInfo p) => p.Message == this); if (info != null) { PendingMessages.Remove(info); } } } public static void CheckTimeouts() { if (NetworkServer.active) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; for (int num = PendingMessages.Count - 1; num >= 0; num--) { if (realtimeSinceStartup - PendingMessages[num].Timestamp > 2f) { PendingMessages.RemoveAt(num); } } } } } namespace Equilibrium.Patches { [HarmonyPatch(typeof(SwarmsArtifactManager), "OnSpawnCardOnSpawnedServerGlobal")] internal static class Swarms_OnSpawnCard_Patch { private static bool Prefix() { return !Equilibrium.IsCloningForInstance; } } } namespace Equilibrium.Core { public abstract class AbstractHookHandler { internal HookManager HookManager; protected Equilibrium Plugin => HookManager.Plugin; protected global::Equilibrium.Config.Config ModConfig => Plugin.ModConfig; public void Init(HookManager hookManager) { HookManager = hookManager; } public abstract void RegisterHooks(); public abstract void UnregisterHooks(); } public abstract class AbstractObjectHandler { public struct AwaitedObjectInfo { public GameObject SourceObject; public PlayerCharacterMasterController[] Players; public object ExtraInfo; } private static Dictionary<string, SpawnCard> _spawnCardsForPrefabName; protected ObjectHandlerManager Manager; public readonly Dictionary<GameObject, AwaitedObjectInfo> InfoForAwaitedObjects = new Dictionary<GameObject, AwaitedObjectInfo>(); public static Dictionary<string, SpawnCard> SpawnCardsForPrefabName { get { if (_spawnCardsForPrefabName == null) { GenerateSpawnCards(); } return _spawnCardsForPrefabName; } } protected Equilibrium Plugin => Manager.Plugin; public abstract string[] HandledObjectTypes { get; } public abstract ObjectInstanceMode ObjectInstanceMode { get; } private static void GenerateSpawnCards() { _spawnCardsForPrefabName = new Dictionary<string, SpawnCard>(); InteractableSpawnCard[] array = Resources.FindObjectsOfTypeAll<InteractableSpawnCard>(); foreach (InteractableSpawnCard val in array) { string name = ((Object)((SpawnCard)val).prefab).name; if (!_spawnCardsForPrefabName.ContainsKey(name)) { _spawnCardsForPrefabName.Add(name, (SpawnCard)(object)val); } } } public virtual void Init(ObjectHandlerManager manager) { Manager = manager; } public virtual bool CanObjectBeOwned(string objectType) { return false; } public virtual bool IsValidForObject(string objectType, GameObject gameObject) { return true; } public virtual void InstanceObject(string objectType, GameObject gameObject, PlayerCharacterMasterController[] players) { InstanceHandler.SharedInstanceInfo sharedInfo = new InstanceHandler.SharedInstanceInfo { SourceObject = gameObject, ObjectInstanceMode = ObjectInstanceMode }; InstanceHandler[] array; PlayerCharacterMasterController[] players2; switch (ObjectInstanceMode) { case ObjectInstanceMode.InstancedObject: array = new InstanceHandler[1]; players2 = players; break; case ObjectInstanceMode.CopyObject: array = new InstanceHandler[players.Length]; players2 = (PlayerCharacterMasterController[])(object)new PlayerCharacterMasterController[1] { players[0] }; break; default: throw new InvalidOperationException("Object handler 不支持此对象实例化模式"); } (array[0] = InstanceSingleObjectFrom(gameObject, gameObject, players2)).SharedInfo = sharedInfo; if (ObjectInstanceMode == ObjectInstanceMode.CopyObject) { for (int i = 1; i < players.Length; i++) { GameObject val = CloneObject(objectType, gameObject); if ((Object)(object)val != (Object)null) { AwaitObjectFor(val, new AwaitedObjectInfo { SourceObject = gameObject, Players = (PlayerCharacterMasterController[])(object)new PlayerCharacterMasterController[1] { players[i] } }); } } } FinalizeSourceObjectIfNotAwaited(gameObject); } public virtual GameObject CloneObject(string objectType, GameObject gameObject) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00c6: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) SpawnCard value = null; SpawnCardTracker component = gameObject.GetComponent<SpawnCardTracker>(); if ((Object)(object)component != (Object)null) { value = component.SpawnCard; } if ((Object)(object)value == (Object)null) { string key = ((Object)gameObject).name.Replace("(Clone)", "").Replace("(Cloned)", "").Trim(); SpawnCardsForPrefabName.TryGetValue(key, out value); } if ((Object)(object)value != (Object)null) { DirectorPlacementRule val = new DirectorPlacementRule { placementMode = (PlacementMode)0, position = gameObject.transform.position, rotation = gameObject.transform.rotation }; DirectorSpawnRequest val2 = new DirectorSpawnRequest(value, val, new Xoroshiro128Plus(0uL)); GameObject val3 = null; try { Equilibrium.IsCloningForInstance = true; SpawnResult val4 = value.DoSpawn(gameObject.transform.position, gameObject.transform.rotation, val2); val3 = val4.spawnedInstance; if ((Object)(object)val3 != (Object)null) { val3.transform.position = gameObject.transform.position; val3.transform.rotation = gameObject.transform.rotation; val3.transform.localScale = gameObject.transform.localScale; val3.layer = gameObject.layer; } } finally { Equilibrium.IsCloningForInstance = false; } return val3; } Plugin.Logger.LogError((object)$"未找到 SpawnCard,用于复制对象 {gameObject}(objectType={objectType})"); return null; } public virtual InstanceHandler InstanceSingleObjectFrom(GameObject source, GameObject target, PlayerCharacterMasterController[] players) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown InstanceHandler instanceHandler = target.AddComponent<InstanceHandler>(); instanceHandler.SetPlayers(players, sync: false); if (ObjectInstanceMode == ObjectInstanceMode.CopyObject) { instanceHandler.OrigPlayer = players[0]; InstanceInfoTracker component = source.GetComponent<InstanceInfoTracker>(); if ((Object)(object)component != (Object)null) { component.Info.AttachTo(target); } InstanceHandler component2 = source.GetComponent<InstanceHandler>(); if ((Object)(object)component2 != (Object)null) { instanceHandler.SharedInfo = component2.SharedInfo; } } PurchaseInteraction component3 = source.GetComponent<PurchaseInteraction>(); PurchaseInteraction component4 = target.GetComponent<PurchaseInteraction>(); if ((Object)(object)component3 != (Object)null && (Object)(object)component4 != (Object)null) { component4.costType = component3.costType; component4.cost = component3.cost; component4.Networkcost = component3.Networkcost; if (component3.rng != null) { component4.rng = new Xoroshiro128Plus(component3.rng); } } return instanceHandler; } public virtual void FinalizeSourceObjectIfNotAwaited(GameObject sourceObject) { if (InfoForAwaitedObjects.All((KeyValuePair<GameObject, AwaitedObjectInfo> pair) => (Object)(object)pair.Value.SourceObject != (Object)(object)sourceObject)) { FinalizeObject(sourceObject); } } public virtual void FinalizeObject(GameObject sourceObject) { InstanceHandler component = sourceObject.GetComponent<InstanceHandler>(); if ((Object)(object)component == (Object)null) { return; } component.SharedInfo.SyncToAll(); foreach (InstanceHandler linkedHandler in component.SharedInfo.LinkedHandlers) { linkedHandler.UpdateVisuals(); } } public virtual void AwaitObjectFor(GameObject target, AwaitedObjectInfo info) { InfoForAwaitedObjects.Add(target, info); Manager.RegisterAwaitedObject(target, this); } public virtual void HandleAwaitedObject(GameObject target) { if (InfoForAwaitedObjects.TryGetValue(target, out var value)) { InfoForAwaitedObjects.Remove(target); InstanceSingleObjectFrom(value.SourceObject, target, value.Players); FinalizeSourceObjectIfNotAwaited(value.SourceObject); } } } public class HookManager { public readonly Dictionary<Type, AbstractHookHandler> HookHandlers = new Dictionary<Type, AbstractHookHandler>(); public readonly Equilibrium Plugin; public HookManager(Equilibrium plugin) { Plugin = plugin; RegisterHandler<ChestBehaviorHandler>(); RegisterHandler<ShrineBehaviorHandler>(); RegisterHandler<MultiShopControllerHandler>(); RegisterHandler<OptionChestBehaviorHandler>(); RegisterHandler<SacrificeArtifactManagerHandler>(); RegisterHandler<BossGroupHandler>(); RegisterHandler<BossHunterHandler>(); RegisterHandler<PurchaseInteractionHandler>(); RegisterHandler<GenericPickupControllerHandler>(); RegisterHandler<PickupDropletControllerHandler>(); RegisterHandler<SpawnCardHandler>(); RegisterHandler<ScavBackpackOpeningHandler>(); RegisterHandler<PickupPickerControllerHandler>(); RegisterHandler<DitherModelHandler>(); RegisterHandler<InteractorHandler>(); RegisterHandler<SonorousWhispersHandler>(); } public void RegisterHandler<T>() where T : AbstractHookHandler, new() { if (!HookHandlers.ContainsKey(typeof(T))) { T val = new T(); val.Init(this); HookHandlers[typeof(T)] = val; } } public T GetHandler<T>() where T : AbstractHookHandler { return (T)HookHandlers[typeof(T)]; } public void RegisterHooks() { foreach (AbstractHookHandler value in HookHandlers.Values) { value.RegisterHooks(); } } public void UnregisterHooks() { foreach (AbstractHookHandler value in HookHandlers.Values) { try { value.UnregisterHooks(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error unloading {value.GetType()}: {arg}"); } } } } public class ObjectHandlerManager { public readonly Dictionary<Type, AbstractObjectHandler> ObjectHandlers = new Dictionary<Type, AbstractObjectHandler>(); public readonly Dictionary<string, AbstractObjectHandler> HandlersForObjectType = new Dictionary<string, AbstractObjectHandler>(); public readonly Dictionary<GameObject, AbstractObjectHandler> AwaitedObjects = new Dictionary<GameObject, AbstractObjectHandler>(); public readonly Equilibrium Plugin; public ObjectHandlerManager(Equilibrium plugin) { Plugin = plugin; RegisterHandler<ChestHandler>(); RegisterHandler<ShrineChanceHandler>(); RegisterHandler<SpecialObjectHandler>(); RegisterHandler<MultiShopHandler>(); RegisterHandler<OptionChestHandler>(); RegisterHandler<SpecialItemHandler>(); Plugin.Logger.LogInfo((object)"[均衡神器] 对象处理器注册完成"); } public void RegisterHandler<T>() where T : AbstractObjectHandler, new() { T val = new T(); val.Init(this); ObjectHandlers[typeof(T)] = val; string[] handledObjectTypes = val.HandledObjectTypes; foreach (string key in handledObjectTypes) { HandlersForObjectType[key] = val; } Plugin.Logger.LogInfo((object)("[均衡神器] 注册对象处理器:" + typeof(T).Name)); } public T GetHandler<T>() where T : AbstractObjectHandler { return (T)ObjectHandlers[typeof(T)]; } public void InstanceObject(string objectType, GameObject gameObject, PlayerCharacterMasterController[] players) { if (HandlersForObjectType.TryGetValue(objectType, out var value)) { value.InstanceObject(objectType, gameObject, players); } else { Plugin.Logger.LogWarning((object)("[均衡神器] 尝试实例化未知对象类型: " + objectType)); } } public InstanceHandler InstanceSingleObject(string objectType, GameObject source, GameObject target, PlayerCharacterMasterController[] players) { AbstractObjectHandler value; return HandlersForObjectType.TryGetValue(objectType, out value) ? value.InstanceSingleObjectFrom(source, target, players) : null; } public bool CanInstanceObject(string objectType, GameObject gameObject) { AbstractObjectHandler value; return HandlersForObjectType.TryGetValue(objectType, out value) && value.IsValidForObject(objectType, gameObject); } public void RegisterAwaitedObject(GameObject gameObject, AbstractObjectHandler owningHandler) { AwaitedObjects.Add(gameObject, owningHandler); Plugin.Logger.LogDebug((object)("[均衡神器] 注册待等待对象: " + ((Object)gameObject).name)); } public bool HandleAwaitedObject(GameObject gameObject) { if (!AwaitedObjects.TryGetValue(gameObject, out var value)) { return false; } AwaitedObjects.Remove(gameObject); value.HandleAwaitedObject(gameObject); Plugin.Logger.LogDebug((object)("[均衡神器] 处理待等待对象: " + ((Object)gameObject).name)); return true; } } } namespace Equilibrium.Config { public class AcceptableValuesInstanceMode : AcceptableValueBase { public AcceptableValuesInstanceMode() : base(typeof(InstanceMode)) { } public override object Clamp(object value) { return ((AcceptableValueBase)this).IsValid(value) ? value : ((object)InstanceMode.None); } public override bool IsValid(object value) { InstanceMode instanceMode = default(InstanceMode); int num; if (value is InstanceMode) { instanceMode = (InstanceMode)value; num = 1; } else { num = 0; } bool flag = (byte)num != 0; bool flag2 = flag; if (flag2) { bool flag3 = (uint)instanceMode <= 2u; flag2 = flag3; } return flag2; } public override string ToDescriptionString() { return "# Acceptable values: None, InstanceObject, InstanceBoth"; } } public class Config { public readonly Equilibrium Plugin; private readonly ManualLogSource _logger; public ConfigEntry<InstanceMode> DefaultChestMode; public ConfigEntry<InstanceMode> DefaultShrineMode; public ConfigEntry<InstanceMode> DefaultShopMode; public ConfigEntry<InstanceMode> DefaultVoidMode; public ConfigEntry<InstanceMode> DefaultSpecialMode; public ConfigEntry<bool> GlobalInstancingEnabled; public ConfigEntry<float> InteractibleCreditMultiplier; public Dictionary<string, ConfigEntry<InstanceMode>> PerObjectMode = new Dictionary<string, ConfigEntry<InstanceMode>>(); private readonly Dictionary<string, InstanceMode> _cache = new Dictionary<string, InstanceMode>(); public ConfigEntry<bool> ARollDrop; public ConfigEntry<bool> LogInstanceInteractions; public Config(Equilibrium plugin, ManualLogSource logger) { Plugin = plugin; _logger = logger; ARollDrop = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("ARollDrop", "ARollDrop", true, "When true, each chest copy will get a separate random seed and re-roll its items (random loot per player). When false, all copies will have the exact same items as the original chest.\n启用独立随机掉落:每个复制宝箱将使用独立的随机种子并重新生成物品(每个玩家看到不同的掉落)。关闭时,所有复制宝箱将与原宝箱拥有完全相同的物品。"); LogInstanceInteractions = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("Debug", "LogInstanceInteractions", false, "Enable detailed interaction diagnostics logging.\nLogs purchase calls, changed selections/pickup states and instance snapshots.\nCapped at 512 purchase, 512 selection/pickup lines per plugin session. Restart to collect a new trace.\n启用详细交互诊断日志。记录购买调用、选择/拾取状态变化和实例快照。\n每次插件会话最多记录 512 条购买、512 条选择/拾取日志,重启以重新收集。默认关闭。"); GlobalInstancingEnabled = ((BaseUnityPlugin)Plugin).Config.Bind<bool>("AGeneral", "Enabled", true, "Global master switch for Equilibrium. When false, all object instancing modes behave as None.\n均衡神器的全局控制开关。当该开关为“false”时,所有对象实例化模式都将等同于“None”模式。(该开关由大厅内神器开关控制,保持默认即可)"); InteractibleCreditMultiplier = ((BaseUnityPlugin)Plugin).Config.Bind<float>("AGeneral", "InteractibleCreditMultiplier", 0.76f, "Multiplayer interactable (chest/shrine) budget multiplier. Original game scales this significantly, causing chest floods. 1.0 = Vanilla; 0.7 = Recommended; 0.5 = Half.\n多人游戏下,交互物(宝箱/神龛/商店)生成预算的乘数。原版多人时宝箱会增加数量,且每人一个宝箱时导致最终战利品过多。这个系数用于减少多人时宝箱会增加数量从而平衡最终战利品\n原版:1.0;默认值:0.76;推荐值:0.7、0.75、0.76、0.8;减半:0.5。数值越大宝箱越多,单人游戏不受此配置影响始终为1。"); DefaultChestMode = Bind("Chests", "Default", InstanceMode.InstanceBoth, "Default mode for all chests. InstanceObject = each player gets a copy, items free-for-all. InstanceBoth = each player gets a copy, items owner-only.\n所有宝箱的默认设置。InstanceObject模式:其他玩家也可以拾取;InstanceBoth模式:仅自己可拾取\n以下是宝箱对应名称:\n- Chest1: 普通宝箱\n- Chest2: 大宝箱\n- GoldChest: 传奇宝箱\n- Chest1StealthedVariant: 隐藏宝箱\n- CategoryChestDamage: 伤害箱\n- CategoryChestHealing: 治疗箱\n- CategoryChestUtility: 辅助箱\n- CategoryChest2Damage: 大伤害箱\n- CategoryChest2Healing: 大治疗箱\n- CategoryChest2Utility: 大辅助箱\n- EquipmentBarrel: 装备箱\n- LunarChest: 月球舱\n- VoidChest: 虚空摇篮\n- Lockbox: 生锈锁箱\n- ScavBackpack: 拾荒者背包"); DefaultShrineMode = Bind("Shrines", "Default", InstanceMode.InstanceBoth, "Default mode for shrines.\n神龛的默认模式\n以下是神龛对应名称:\n- ShrineChance: 机遇神龛\n- ShrineBlood: 鲜血神龛\n- ShrineRestack: 塑形神龛maybe"); DefaultShopMode = Bind("Shops", "Default", InstanceMode.InstanceBoth, "Default mode for multi shops.\n三选一商店的默认模式\n以下是三选一商店对应名称:\n- TripleShop: 三选一商店\n- TripleShopLarge: 大三选一商店?\n- TripleShopEquipment: 装备三选一商店\n- FreeChestMultiShop: 坠毁的多功能商店maybe┑(\uffe3Д \uffe3)┍"); DefaultVoidMode = Bind("Void", "Default", InstanceMode.InstanceBoth, "Default mode for void objects.\n虚空物品的默认模式\n以下是虚空物品对应名称:\n- VoidTriple: 虚空潜能\n- LockboxVoid: 结壳宝箱"); DefaultSpecialMode = Bind("Special", "Default", InstanceMode.InstanceBoth, "Default mode for sacrifice, boss drops, etc.\n牺牲、首领掉落物品等的处理方式的默认模式\n以下是牺牲、首领掉落物品对应名称:\n- Sacrifice: 牺牲掉落\n- HuntersTricorn: 米爹maybe\n- TeleporterBoss: 传送器BOSS\n- SuperRoboBallEncounter: 合金崇拜单体maybe\n- BossGroup: idk┑(\uffe3Д \uffe3)┍"); FieldInfo[] fields = typeof(ObjectType).GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.FieldType != typeof(string))) { string text = (string)fieldInfo.GetValue(null); string category = GetCategory(text); if (1 == 0) { } InstanceMode instanceMode = category switch { "Chests" => DefaultChestMode.Value, "Shrines" => DefaultShrineMode.Value, "Shops" => DefaultShopMode.Value, "Void" => DefaultVoidMode.Value, _ => DefaultSpecialMode.Value, }; if (1 == 0) { } InstanceMode instanceMode2 = instanceMode; PerObjectMode[text] = ((BaseUnityPlugin)plugin).Config.Bind<InstanceMode>(category, text, instanceMode2, "Instancing mode for " + text); } } ((BaseUnityPlugin)plugin).Config.SettingChanged += delegate(object _, SettingChangedEventArgs e) { _cache.Clear(); if (GlobalInstancingEnabled != null && e.ChangedSetting.Definition.Equals(((ConfigEntryBase)GlobalInstancingEnabled).Definition)) { EquilibriumManager.SetConfigEnabled(GlobalInstancingEnabled.Value); Plugin.Logger.LogInfo((object)$"[Equilibrium] Global instancing enabled.\n[均衡神器] 全局实例化已启用 = {GlobalInstancingEnabled.Value}"); } }; EquilibriumManager.SetConfigEnabled(GlobalInstancingEnabled.Value); } private ConfigEntry<InstanceMode> Bind(string section, string key, InstanceMode defaultValue, string description) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown return ((BaseUnityPlugin)Plugin).Config.Bind<InstanceMode>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValuesInstanceMode(), Array.Empty<object>())); } public InstanceMode GetMode(string objectType) { if (GlobalInstancingEnabled != null && !GlobalInstancingEnabled.Value) { return InstanceMode.None; } if (objectType == null) { return InstanceMode.None; } if (_cache.TryGetValue(objectType, out var value)) { return value; } ConfigEntry<InstanceMode> value2; InstanceMode instanceMode = (PerObjectMode.TryGetValue(objectType, out value2) ? value2.Value : InstanceMode.None); _cache[objectType] = instanceMode; return instanceMode; } public HashSet<PlayerCharacterMasterController> GetValidPlayers() { return new HashSet<PlayerCharacterMasterController>(PlayerCharacterMasterController.instances); } public void OnConfigReloaded() { _cache.Clear(); EquilibriumManager.SetConfigEnabled(GlobalInstancingEnabled.Value); Plugin.Logger.LogInfo((object)"[Equilibrium] Config reloaded and applied.[均衡神器] 配置文件已重新加载并生效。"); } private static string GetCategory(string objectType) { if (1 == 0) { } string result; switch (objectType) { case "Chest1": case "Chest2": case "GoldChest": case "Chest1StealthedVariant": case "CategoryChestDamage": case "CategoryChestHealing": case "CategoryChestUtility": case "CategoryChest2Damage": case "CategoryChest2Healing": case "CategoryChest2Utility": case "EquipmentBarrel": case "LunarChest": case "VoidChest": case "Lockbox": case "ScavBackpack": result = "Chests"; break; case "ShrineChance": case "ShrineBlood": case "ShrineRestack": result = "Shrines"; break; case "TripleShop": case "TripleShopLarge": case "TripleShopEquipment": case "FreeChestMultiShop": result = "Shops"; break; case "VoidTriple": case "LockboxVoid": result = "Void"; break; default: result = "Special"; break; } if (1 == 0) { } return result; } } } namespace Equilibrium.Hooks { public class AnimationEventsHandler : AbstractHookHandler { public static AnimationEvents CurrentAnimationEvents; public override void RegisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown AnimationEvents.CreateEffect += new hook_CreateEffect(On_AnimationEvents_CreateEffect); AnimationEvents.CreatePrefab += new Manipulator(IL_AnimationEvents_CreatePrefab); } public override void UnregisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown AnimationEvents.CreateEffect -= new hook_CreateEffect(On_AnimationEvents_CreateEffect); AnimationEvents.CreatePrefab -= new Manipulator(IL_AnimationEvents_CreatePrefab); } private void On_AnimationEvents_CreateEffect(orig_CreateEffect orig, AnimationEvents self, AnimationEvent animationEvent) { CurrentAnimationEvents = self; orig.Invoke(self, animationEvent); CurrentAnimationEvents = null; FadeBehavior component = ((Component)self).GetComponent<FadeBehavior>(); if (Object.op_Implicit((Object)(object)component)) { component.RefreshNextFrame(); } EntityLocator component2 = ((Component)self).GetComponent<EntityLocator>(); if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.entity)) { FadeBehavior component3 = component2.entity.GetComponent<FadeBehavior>(); if (Object.op_Implicit((Object)(object)component3)) { component3.Refresh(); } } } private void IL_AnimationEvents_CreatePrefab(ILContext il) { AnimationPrefabIL.Apply<Action<Transform, AnimationEvents, bool>>(il, HandlePrefabCreation); } public static void HandlePrefabCreation(Transform created, AnimationEvents parent, bool pooled) { if (!pooled && Object.op_Implicit((Object)(object)created)) { HandleObjectCreation(((Component)created).gameObject, parent); } } public static void HandleEffectCreation(GameObject objectToAdd) { if ((Object)(object)CurrentAnimationEvents != (Object)null) { HandleObjectCreation(objectToAdd, CurrentAnimationEvents); } } public static void HandleObjectCreation(GameObject objectToAdd, AnimationEvents parent) { Transform val = objectToAdd.transform; Transform transform = ((Component)parent).transform; while ((Object)(object)val != (Object)(object)transform && (Object)(object)val != (Object)null) { val = val.parent; } FadeBehavior componentInParent = ((Component)parent).GetComponentInParent<FadeBehavior>(); if ((Object)(object)componentInParent == (Object)null) { EntityLocator component = ((Component)parent).GetComponent<EntityLocator>(); if ((Object)(object)component != (Object)null && (Object)(object)component.entity != (Object)null) { componentInParent = component.entity.GetComponentInParent<FadeBehavior>(); } } if (!((Object)(object)componentInParent == (Object)null)) { if ((Object)(object)val != (Object)(object)transform) { componentInParent.ExtraGameObjects.Add(objectToAdd); } componentInParent.Refresh(); } } } internal static class AnimationPrefabIL { internal static void Apply<TDelegate>(ILContext il, TDelegate handleCreation) where TDelegate : Delegate { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Invalid comparison between Unknown and I4 //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); int pooledLocal = -1; if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2] { IsShouldUsePooledEffectCall, (Instruction i) => ILPatternMatchingExt.MatchStloc(i, ref pooledLocal) }) || (int)((VariableReference)il.Body.Variables[pooledLocal]).VariableType.MetadataType != 2) { throw new InvalidOperationException(((MemberReference)il.Method).FullName + ": CreatePrefab pooled-effect flag pattern not found."); } val.Index = 0; int num = 0; while (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { IsDoSpawnEffectCall })) { val.Emit(OpCodes.Dup); val.Emit(OpCodes.Ldarg_0); val.Emit(OpCodes.Ldloc, il.Body.Variables[pooledLocal]); val.EmitDelegate<TDelegate>(handleCreation); num++; } if (num == 0) { throw new InvalidOperationException(((MemberReference)il.Method).FullName + ": CreatePrefab DoSpawnEffect pattern not found."); } } private static bool IsShouldUsePooledEffectCall(Instruction i) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 if (i.OpCode != OpCodes.Call) { return false; } object operand = i.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val == null) { return false; } return ((MemberReference)((MemberReference)val).DeclaringType).FullName == "RoR2.EffectManager" && ((MemberReference)val).Name == "ShouldUsePooledEffect" && (int)val.ReturnType.MetadataType == 2 && val.Parameters.Count == 1 && ((MemberReference)((ParameterReference)val.Parameters[0]).ParameterType).FullName == "UnityEngine.GameObject"; } private static bool IsDoSpawnEffectCall(Instruction i) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Invalid comparison between Unknown and I4 if (i.OpCode != OpCodes.Call) { return false; } object operand = i.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val == null) { return false; } return ((MemberReference)((MemberReference)val).DeclaringType).FullName == "RoR2.AnimationEvents" && !val.HasThis && ((MemberReference)val).Name.StartsWith("<CreatePrefab>g__DoSpawnEffect|", StringComparison.Ordinal) && ((MemberReference)val.ReturnType).FullName == "UnityEngine.Transform" && val.Parameters.Count == 5 && (int)((ParameterReference)val.Parameters[0]).ParameterType.MetadataType == 2 && ((MemberReference)((ParameterReference)val.Parameters[1]).ParameterType).FullName == "UnityEngine.GameObject" && ((MemberReference)((ParameterReference)val.Parameters[2]).ParameterType).FullName == "UnityEngine.Vector3" && ((MemberReference)((ParameterReference)val.Parameters[3]).ParameterType).FullName == "UnityEngine.Quaternion" && ((MemberReference)((ParameterReference)val.Parameters[4]).ParameterType).FullName == "UnityEngine.Transform"; } } public class ChestBehaviorHandler : AbstractHookHandler { public override void RegisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown ChestBehavior.ItemDrop += new hook_ItemDrop(OnItemDrop); ChestBehavior.Start += new hook_Start(OnStart); } public override void UnregisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown ChestBehavior.ItemDrop -= new hook_ItemDrop(OnItemDrop); ChestBehavior.Start -= new hook_Start(OnStart); } private void OnItemDrop(orig_ItemDrop orig, ChestBehavior self) { InstanceInfoTracker component = ((Component)self).GetComponent<InstanceInfoTracker>(); if ((Object)(object)component != (Object)null) { HookManager.GetHandler<PickupDropletControllerHandler>().InstanceOverrideInfo = component.Info; orig.Invoke(self); HookManager.GetHandler<PickupDropletControllerHandler>().InstanceOverrideInfo = null; } else { orig.Invoke(self); } } private void OnStart(orig_Start orig, ChestBehavior self) { if (!NetworkServer.active) { orig.Invoke(self); } else { if (base.Plugin.ObjectHandlerManager.HandleAwaitedObject(((Component)self).gameObject)) { return; } if ((Object)(object)((Component)self).GetComponent<InstanceHandler>() != (Object)null) { orig.Invoke(self); return; } orig.Invoke(self); string name = ((Object)self).name; string text = name; if (1 == 0) { } string text2 = ((!name.StartsWith("Chest1")) ? ((!name.StartsWith("Chest2")) ? ((!name.StartsWith("GoldChest")) ? ((!name.StartsWith("Chest1StealthedVariant")) ? ((!name.StartsWith("CategoryChestDamage")) ? ((!name.StartsWith("CategoryChestHealing")) ? ((!name.StartsWith("CategoryChestUtility")) ? ((!name.StartsWith("CategoryChest2Damage")) ? ((!name.StartsWith("CategoryChest2Healing")) ? ((!name.StartsWith("CategoryChest2Utility")) ? ((!name.StartsWith("EquipmentBarrel")) ? ((!name.StartsWith("LunarChest")) ? ((!name.StartsWith("VoidChest")) ? ((!name.StartsWith("Lockbox")) ? ((!name.StartsWith("ScavBackpack")) ? null : "ScavBackpack") : "Lockbox") : "VoidChest") : "LunarChest") : "EquipmentBarrel") : "CategoryChest2Utility") : "CategoryChest2Healing") : "CategoryChest2Damage") : "CategoryChestUtility") : "CategoryChestHealing") : "CategoryChestDamage") : "Chest1StealthedVariant") : "GoldChest") : "Chest2") : "Chest1"); if (1 == 0) { } string text3 = text2; if (text3 != null) { base.Plugin.HandleInstancing(((Component)self).gameObject, new InstanceInfoTracker.InstanceOverrideInfo(text3)); } } } } public class BossGroupHandler : AbstractHookHandler { public override void RegisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown BossGroup.Start += new hook_Start(OnStart); BossGroup.DropRewards += new hook_DropRewards(OnDropRewards); BossGroup.DropRewards += new Manipulator(IL_DropRewards); } public override void UnregisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown BossGroup.Start -= new hook_Start(OnStart); BossGroup.DropRewards -= new hook_DropRewards(OnDropRewards); BossGroup.DropRewards -= new Manipulator(IL_DropRewards); } private void OnStart(orig_Start orig, BossGroup self) { string name = ((Object)self).name; string text = name; if (1 == 0) { } string text2 = ((!name.StartsWith("LunarTeleporter")) ? ((!name.StartsWith("Teleporter")) ? ((!name.StartsWith("SuperRoboBallEncounter")) ? "BossGroup" : "SuperRoboBallEncounter") : "TeleporterBoss") : "TeleporterBoss"); if (1 == 0) { } string objectType = text2; base.Plugin.HandleInstancing(((Component)self).gameObject, new InstanceInfoTracker.InstanceOverrideInfo(objectType), isObject: false); } private void OnDropRewards(orig_DropRewards orig, BossGroup self) { InstanceInfoTracker component = ((Component)self).GetComponent<InstanceInfoTracker>(); if ((Object)(object)component == (Object)null) { orig.Invoke(self); return; } PickupDropletControllerHandler handler = HookManager.GetHandler<PickupDropletControllerHandler>(); handler.InstanceOverrideInfo = component.Info; orig.Invoke(self); handler.InstanceOverrideInfo = null; } private void IL_DropRewards(ILContext il) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); int varLoopCount = -1; val.GotoNext((MoveType)0, new Func<Instruction, bool>[2] { (Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<PickupDropletController>(i, "CreatePickupDroplet"), (Instruction i) => ILPatternMatchingExt.MatchLdloc(i, ref varLoopCount) }); val.Emit(OpCodes.Ldarg_0); val.Emit(OpCodes.Ldloc, varLoopCount); val.EmitDelegate<Action<BossGroup, int>>((Action<BossGroup, int>)delegate(BossGroup self, int loopCount) { if (self.scaleRewardsByPlayerCount && HookManager.GetHandler<PickupDropletControllerHandler>().InstanceOverrideInfo.HasValue) { int index = loopCount % Run.instance.participatingPlayerCount; PlayerCharacterMasterController owner = PlayerCharacterMasterController.instances[index]; InstanceInfoTracker.InstanceOverrideInfo value = HookManager.GetHandler<PickupDropletControllerHandler>().InstanceOverrideInfo.Value; value.Owner = owner; HookManager.GetHandler<PickupDropletControllerHandler>().InstanceOverrideInfo = value; } }); } } public class BossHunterHandler : AbstractHookHandler { public override void RegisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown EquipmentSlot.FireBossHunter += new hook_FireBossHunter(OnFireBossHunter); } public override void UnregisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown EquipmentSlot.FireBossHunter -= new hook_FireBossHunter(OnFireBossHunter); } private bool OnFireBossHunter(orig_FireBossHunter orig, EquipmentSlot self) { object obj; if (self == null) { obj = null; } else { CharacterBody characterBody = self.characterBody; if (characterBody == null) { obj = null; } else { CharacterMaster master = characterBody.master; obj = ((master != null) ? master.playerCharacterMasterController : null); } } PlayerCharacterMasterController owner = (PlayerCharacterMasterController)obj; PickupDropletControllerHandler handler = HookManager.GetHandler<PickupDropletControllerHandler>(); handler.InstanceOverrideInfo = new InstanceInfoTracker.InstanceOverrideInfo("HuntersTricorn", owner); bool result = orig.Invoke(self); handler.InstanceOverrideInfo = null; return result; } } internal static class CommandCubeIL { internal static void Apply<TDelegate>(ILContext il, TDelegate onSpawned) where TDelegate : Delegate { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) Instruction[] array = ((IEnumerable<Instruction>)il.Body.Instructions).Where(IsNetworkServerSpawn).ToArray(); if (array.Length == 1 && IsSpawnGameObjectMethod((MethodReference)/*isinst with value type is only supported in some contexts*/)) { ILCursor val = new ILCursor(il); val.Goto(array[0], (MoveType)0, false); val.MoveAfterLabels(); val.Emit(OpCodes.Dup); int index = val.Index; val.Index = index + 1; val.EmitDelegate<TDelegate>(onSpawned); return; } throw new InvalidOperationException(((MemberReference)il.Method).FullName + ": Command cube Spawn(GameObject) pattern not found."); } private static bool IsNetworkServerSpawn(Instruction i) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode != OpCodes.Call) { return false; } object operand = i.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val == null) { return false; } return ((MemberReference)((MemberReference)val).DeclaringType).FullName == "UnityEngine.Networking.NetworkServer" && ((MemberReference)val).Name == "Spawn"; } private static bool IsSpawnGameObjectMethod(MethodReference method) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 return method != null && !method.HasThis && (int)method.ReturnType.MetadataType == 1 && method.Parameters.Count == 1 && ((MemberReference)((ParameterReference)method.Parameters[0]).ParameterType).FullName == "UnityEngine.GameObject"; } } public class DitherModelHandler : AbstractHookHandler { public override void RegisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown DitherModel.RefreshObstructorsForCamera += new Manipulator(IL_DitherModel_RefreshObstructorsForCamera); } public override void UnregisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown DitherModel.RefreshObstructorsForCamera -= new Manipulator(IL_DitherModel_RefreshObstructorsForCamera); } private void IL_DitherModel_RefreshObstructorsForCamera(ILContext il) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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_019e: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); ILLabel val2 = il.DefineLabel(); ILLabel val3 = il.DefineLabel(); MethodInfo methodInfo = typeof(Component).GetMethods(BindingFlags.Instance | BindingFlags.Public).First((MethodInfo method) => method.Name == "GetComponent" && method.IsGenericMethod); MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(typeof(FadeBehavior)); int ditherModelLoc = -1; val.GotoNext((MoveType)0, new Func<Instruction, bool>[2] { (Instruction i) => ILPatternMatchingExt.MatchLdloc(i, ref ditherModelLoc), (Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<DitherModel>(i, "UpdateDither") }); int index = val.Index; val.Index = index + 1; val.Emit(OpCodes.Dup); val.Emit(OpCodes.Dup); val.Emit(OpCodes.Call, (MethodBase)methodInfo2); val.Emit(OpCodes.Dup); val.Emit(OpCodes.Ldnull); val.Emit(OpCodes.Ceq); val.Emit(OpCodes.Brtrue, (object)val2); val.Emit(OpCodes.Ldarg_0); val.Emit<FadeBehavior>(OpCodes.Call, "GetFadeLevelForCameraRigController"); val.Emit(OpCodes.Ldloc, ditherModelLoc); val.Emit<DitherModel>(OpCodes.Ldfld, "fade"); val.Emit(OpCodes.Mul); val.Emit<DitherModel>(OpCodes.Stfld, "fade"); val.Emit(OpCodes.Br, (object)val3); val.MarkLabel(val2); val.Emit(OpCodes.Pop); val.Emit(OpCodes.Pop); val.MarkLabel(val3); } } public class EffectManagerHandler : AbstractHookHandler { public override void RegisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown EffectManager.SpawnEffect_EffectIndex_EffectData_bool += new Manipulator(IL_EffectManager_SpawnEffect); } public override void UnregisterHooks() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown EffectManager.SpawnEffect_EffectIndex_EffectData_bool -= new Manipulator(IL_EffectManager_SpawnEffect); } private void IL_Ef