using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PhantomParty { internal sealed class MaterialBackup { public int RenderQueue; public string RenderType; public bool HasSrc; public float Src; public bool HasDst; public float Dst; public bool HasZWrite; public float ZWrite; public bool HasSurface; public float Surface; public bool HasBlend; public float Blend; public bool HasMode; public float Mode; public bool SurfaceKeywordWasOn; public bool AlphaBlendKeywordWasOn; public bool BlendmodeAlphaKeywordWasOn; public bool HasOpacity; public float Opacity; public bool HasTint; public Color Tint; public bool HasColor; public Color Color; public bool HasBaseColor; public Color BaseColor; public Shader OriginalShader; public bool ShaderWasSwapped; } internal static class MaterialTransparency { public static readonly int OpacityProp = Shader.PropertyToID("_Opacity"); public static readonly int TintProp = Shader.PropertyToID("_Tint"); public static readonly int ColorProp = Shader.PropertyToID("_Color"); public static readonly int BaseColorProp = Shader.PropertyToID("_BaseColor"); public static readonly int SrcBlendProp = Shader.PropertyToID("_SrcBlend"); public static readonly int DstBlendProp = Shader.PropertyToID("_DstBlend"); public static readonly int ZWriteProp = Shader.PropertyToID("_ZWrite"); public static readonly int SurfaceProp = Shader.PropertyToID("_Surface"); public static readonly int BlendProp = Shader.PropertyToID("_Blend"); public static readonly int ModeProp = Shader.PropertyToID("_Mode"); private const string SurfaceKeyword = "_SURFACE_TYPE_TRANSPARENT"; private const string AlphaBlendKeyword = "_ALPHABLEND_ON"; private const string BlendmodeAlphaKeyword = "_BLENDMODE_ALPHA"; private const float SrcAlphaBlend = 5f; private const float OneMinusSrcAlphaBlend = 10f; private const float SurfaceTransparent = 1f; private const float BlendAlpha = 0f; private const float ModeTransparent = 3f; private const int TransparentQueue = 3000; private static Shader _bodyShader; public static void CacheBodyShader(Character character) { if ((Object)(object)_bodyShader != (Object)null || (Object)(object)character == (Object)null || character.refs == null) { return; } CharacterCustomization customization = character.refs.customization; if ((Object)(object)customization == (Object)null || (Object)(object)customization.refs == (Object)null) { return; } Renderer[] allRenderers = customization.refs.AllRenderers; if (allRenderers == null) { return; } foreach (Renderer val in allRenderers) { if (!((Object)(object)val == (Object)null)) { Material sharedMaterial = val.sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty(OpacityProp)) { _bodyShader = sharedMaterial.shader; break; } } } } public static bool NeedsRenderModeSwitch(Material material, bool forceSwitch) { if ((Object)(object)material == (Object)null) { return false; } if (material.HasProperty(OpacityProp)) { return false; } return true; } public static MaterialBackup Capture(Material material) { //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) MaterialBackup materialBackup = new MaterialBackup { RenderQueue = material.renderQueue, RenderType = material.GetTag("RenderType", false), OriginalShader = material.shader }; materialBackup.HasSrc = material.HasProperty(SrcBlendProp); if (materialBackup.HasSrc) { materialBackup.Src = material.GetFloat(SrcBlendProp); } materialBackup.HasDst = material.HasProperty(DstBlendProp); if (materialBackup.HasDst) { materialBackup.Dst = material.GetFloat(DstBlendProp); } materialBackup.HasZWrite = material.HasProperty(ZWriteProp); if (materialBackup.HasZWrite) { materialBackup.ZWrite = material.GetFloat(ZWriteProp); } materialBackup.HasSurface = material.HasProperty(SurfaceProp); if (materialBackup.HasSurface) { materialBackup.Surface = material.GetFloat(SurfaceProp); } materialBackup.HasBlend = material.HasProperty(BlendProp); if (materialBackup.HasBlend) { materialBackup.Blend = material.GetFloat(BlendProp); } materialBackup.HasMode = material.HasProperty(ModeProp); if (materialBackup.HasMode) { materialBackup.Mode = material.GetFloat(ModeProp); } materialBackup.SurfaceKeywordWasOn = material.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT"); materialBackup.AlphaBlendKeywordWasOn = material.IsKeywordEnabled("_ALPHABLEND_ON"); materialBackup.BlendmodeAlphaKeywordWasOn = material.IsKeywordEnabled("_BLENDMODE_ALPHA"); materialBackup.HasOpacity = material.HasProperty(OpacityProp); if (materialBackup.HasOpacity) { materialBackup.Opacity = material.GetFloat(OpacityProp); } materialBackup.HasTint = material.HasProperty(TintProp); if (materialBackup.HasTint) { materialBackup.Tint = material.GetColor(TintProp); } materialBackup.HasColor = material.HasProperty(ColorProp); if (materialBackup.HasColor) { materialBackup.Color = material.GetColor(ColorProp); } materialBackup.HasBaseColor = material.HasProperty(BaseColorProp); if (materialBackup.HasBaseColor) { materialBackup.BaseColor = material.GetColor(BaseColorProp); } return materialBackup; } public static void SetTransparent(Material material, float value, bool forceSwitch, MaterialBackup backup) { if ((Object)(object)material == (Object)null) { return; } if (material.HasProperty(OpacityProp)) { if ((Object)(object)_bodyShader == (Object)null) { _bodyShader = material.shader; } material.SetFloat(OpacityProp, value); SetAlpha(material, TintProp, value); SetAlpha(material, ColorProp, value); SetAlpha(material, BaseColorProp, value); return; } SetAlpha(material, TintProp, value); SetAlpha(material, ColorProp, value); SetAlpha(material, BaseColorProp, value); if (NeedsRenderModeSwitch(material, forceSwitch) && backup != null) { if ((Object)(object)_bodyShader != (Object)null && (Object)(object)_bodyShader != (Object)(object)material.shader) { backup.ShaderWasSwapped = true; material.shader = _bodyShader; material.SetFloat(OpacityProp, value); SetAlpha(material, TintProp, value); SetAlpha(material, ColorProp, value); SetAlpha(material, BaseColorProp, value); material.renderQueue = 3000; } else { ApplyTransparentRenderMode(material); } } } public static void Restore(Material material, MaterialBackup backup) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null) { return; } if (backup != null) { if (backup.ShaderWasSwapped && (Object)(object)backup.OriginalShader != (Object)null && (Object)(object)backup.OriginalShader != (Object)(object)material.shader) { material.shader = backup.OriginalShader; } if (backup.HasOpacity && material.HasProperty(OpacityProp)) { material.SetFloat(OpacityProp, backup.Opacity); } RestoreColor(material, TintProp, backup.HasTint, backup.Tint); RestoreColor(material, ColorProp, backup.HasColor, backup.Color); RestoreColor(material, BaseColorProp, backup.HasBaseColor, backup.BaseColor); } else { if (material.HasProperty(OpacityProp)) { material.SetFloat(OpacityProp, 1f); } SetAlpha(material, TintProp, 1f); SetAlpha(material, ColorProp, 1f); SetAlpha(material, BaseColorProp, 1f); } if (backup != null && !backup.ShaderWasSwapped) { material.renderQueue = backup.RenderQueue; material.SetOverrideTag("RenderType", backup.RenderType ?? string.Empty); if (backup.HasSrc && material.HasProperty(SrcBlendProp)) { material.SetFloat(SrcBlendProp, backup.Src); } if (backup.HasDst && material.HasProperty(DstBlendProp)) { material.SetFloat(DstBlendProp, backup.Dst); } if (backup.HasZWrite && material.HasProperty(ZWriteProp)) { material.SetFloat(ZWriteProp, backup.ZWrite); } if (backup.HasSurface && material.HasProperty(SurfaceProp)) { material.SetFloat(SurfaceProp, backup.Surface); } if (backup.HasBlend && material.HasProperty(BlendProp)) { material.SetFloat(BlendProp, backup.Blend); } if (backup.HasMode && material.HasProperty(ModeProp)) { material.SetFloat(ModeProp, backup.Mode); } SetKeyword(material, "_SURFACE_TYPE_TRANSPARENT", backup.SurfaceKeywordWasOn); SetKeyword(material, "_ALPHABLEND_ON", backup.AlphaBlendKeywordWasOn); SetKeyword(material, "_BLENDMODE_ALPHA", backup.BlendmodeAlphaKeywordWasOn); } } private static void ApplyTransparentRenderMode(Material material) { material.SetOverrideTag("RenderType", "Transparent"); if (material.HasProperty(SrcBlendProp)) { material.SetFloat(SrcBlendProp, 5f); } if (material.HasProperty(DstBlendProp)) { material.SetFloat(DstBlendProp, 10f); } if (material.HasProperty(ZWriteProp)) { material.SetFloat(ZWriteProp, 0f); } if (material.HasProperty(SurfaceProp)) { material.SetFloat(SurfaceProp, 1f); } if (material.HasProperty(BlendProp)) { material.SetFloat(BlendProp, 0f); } if (material.HasProperty(ModeProp)) { material.SetFloat(ModeProp, 3f); } material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_ALPHABLEND_ON"); material.EnableKeyword("_BLENDMODE_ALPHA"); material.renderQueue = 3000; } private static void SetKeyword(Material material, string keyword, bool enabled) { if (enabled) { material.EnableKeyword(keyword); } else { material.DisableKeyword(keyword); } } private static void SetAlpha(Material material, int property, float alpha) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(property)) { Color color = material.GetColor(property); material.SetColor(property, new Color(color.r, color.g, color.b, alpha)); } } private static void RestoreColor(Material material, int property, bool hasValue, Color value) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (hasValue && material.HasProperty(property)) { material.SetColor(property, value); } } } internal static class ModConfig { public static ConfigEntry Enable; public static ConfigEntry DisableCollision; public static ConfigEntry SemiTransparent; public static ConfigEntry SemiTransparentBackpack; public static ConfigEntry SemiTransparentHeldItem; public static ConfigEntry Opacity; public static ConfigEntry TriggerDistance; public static ConfigEntry InFovOnly; public static ConfigEntry IncludeBots; public static void BindAll(ConfigFile config) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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 //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown Enable = config.Bind("通用", "总开关", true, new ConfigDescription("关闭后所有功能(禁用碰撞、半透明)都不生效。改完保存配置文件即生效,无需重启游戏。", (AcceptableValueBase)null, Array.Empty())); DisableCollision = config.Bind("碰撞", "禁用玩家碰撞", true, new ConfigDescription("开启后本玩家与所有远程玩家之间的碰撞被忽略:两人挤在一起时不会互相碰撞或推挤,可以穿过对方。世界物体(地面、墙壁、道具)的碰撞不受影响。仅客户端生效,服务器侧照常,不会影响其他玩家的体验。", (AcceptableValueBase)null, Array.Empty())); SemiTransparent = config.Bind("视野", "近距离半透明", true, new ConfigDescription("开启后当其他玩家靠近到触发距离以内、且进入视野范围时,其身体与帽子会以「不透明度」指定的值渲染(默认 0.25,即 75% 透明)。距离触发范围外或不在视野内时自动恢复正常外观。仅客户端渲染,其他玩家看不到你本地做的透明度变化。", (AcceptableValueBase)null, Array.Empty())); SemiTransparentBackpack = config.Bind("视野", "透明化背包", false, new ConfigDescription("开启后,处于半透明触发范围内的玩家,其背上的背包也一起变透明。默认关闭:背包不参与半透明,仍会挡住视线。", (AcceptableValueBase)null, Array.Empty())); SemiTransparentHeldItem = config.Bind("视野", "透明化手持物品", false, new ConfigDescription("开启后,处于半透明触发范围内的玩家,其手中正在拿的物品也一起变透明。默认关闭:手持物品不参与半透明。", (AcceptableValueBase)null, Array.Empty())); Opacity = config.Bind("视野", "不透明度", 0.25f, new ConfigDescription("半透明渲染时目标的不透明度取值(0.0 ~ 1.0)。0.25 = 很透明,能看到背后的地形和其他物体(默认);0.50 = 半透明;0.75 = 稍透明;1.0 = 完全不透明(等同禁用该功能)。改完保存配置文件即生效。", (AcceptableValueBase)null, Array.Empty())); TriggerDistance = config.Bind("视野", "触发距离", 2f, new ConfigDescription("半透明效果的距离上限(单位:米,取玩家中心点距离)。其他玩家距离本玩家小于此值时触发半透明。默认 2.0 米,覆盖两人挤在一起的主要场景。0 表示立即触发,10 以上会明显遮挡远处玩家。", (AcceptableValueBase)null, Array.Empty())); InFovOnly = config.Bind("视野", "仅视野内生效", true, new ConfigDescription("开启后仅当其他玩家处于本玩家当前视野内(相机可见范围)时才半透明。关闭则任意方向的近距离玩家都会触发半透明。开启会略微增加开销(相机 FOV 判断),但视觉更聚焦,推荐开启。", (AcceptableValueBase)null, Array.Empty())); IncludeBots = config.Bind("范围", "处理 Bot 玩家", true, new ConfigDescription("开启后 NPC/Bot 玩家也按同样规则处理(禁用碰撞 + 近距离半透明)。关闭则 Bot 保持原版行为(会碰撞、不透明)。", (AcceptableValueBase)null, Array.Empty())); } } public class PhantomPartyController : MonoBehaviour { private sealed class CharacterState { public Character Character; public bool Transparent; public Item LastItem; public BackpackOnBackVisuals LastBackpack; public readonly HashSet Materials = new HashSet(); public readonly List RestoreBuffer = new List(); } private const float RefreshInterval = 0.5f; private readonly List _states = new List(); private readonly Dictionary _backups = new Dictionary(); private readonly PlayerCollisionManager _collision = new PlayerCollisionManager(); private readonly List _targets = new List(); private readonly Dictionary _wanted = new Dictionary(); private readonly List _materialBuffer = new List(); private readonly List _backupKeys = new List(); private Character _lastMe; private float _lastAppliedOpacity = -1f; private float _lastRefreshTime; private float _nextDiagTime; private void Update() { float num = Mathf.Clamp01(ModConfig.Opacity.Value); Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || localCharacter.refs == null) { if (_states.Count > 0) { ReleaseAllMaterials(); } _collision.RestoreAll(); _lastMe = null; _lastAppliedOpacity = num; return; } if ((Object)(object)localCharacter != (Object)(object)_lastMe) { ReleaseAllMaterials(); _collision.RestoreAll(); _lastMe = localCharacter; } if (!ModConfig.Enable.Value) { if (_states.Count > 0) { ReleaseAllMaterials(); } _collision.RestoreAll(); _lastAppliedOpacity = num; return; } bool num2 = Mathf.Abs(num - _lastAppliedOpacity) > 0.0001f; bool flag = Time.unscaledTime - _lastRefreshTime >= 0.5f; if (flag) { _lastRefreshTime = Time.unscaledTime; } bool forceReapply = num2 || flag; MaterialTransparency.CacheBodyShader(localCharacter); CollectTargets(localCharacter, ModConfig.IncludeBots.Value); ProcessCollision(localCharacter, ModConfig.DisableCollision.Value); ProcessVisibility(localCharacter, num, ModConfig.SemiTransparent.Value, ModConfig.InFovOnly.Value, forceReapply); CleanupStates(); LogDiagnostics(); _lastAppliedOpacity = num; } private void LogDiagnostics() { if (Time.unscaledTime < _nextDiagTime) { return; } _nextDiagTime = Time.unscaledTime + 3f; if (_targets.Count == 0) { return; } string text = "无透明目标"; for (int i = 0; i < _states.Count; i++) { if (_states[i].Transparent) { text = TargetMaterialCollector.DescribeBackpack(_states[i].Character); break; } } PluginInfo.Log("[诊断] 本机碰撞体 " + _collision.LocalColliderCount + ",目标 " + _collision.TargetCount + ",首个目标碰撞体 " + _collision.ColliderCountOf(0) + ",忽略已设置 " + (_collision.AreIgnored(0) ? "是" : "否") + ";" + text); } private void CollectTargets(Character me, bool includeBots) { _targets.Clear(); List allCharacters = Character.AllCharacters; if (allCharacters != null) { for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)me)) { _targets.Add(val); } } } if (!includeBots) { return; } List allBotCharacters = Character.AllBotCharacters; if (allBotCharacters == null) { return; } for (int j = 0; j < allBotCharacters.Count; j++) { Character val2 = allBotCharacters[j]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)me) && !_targets.Contains(val2)) { _targets.Add(val2); } } } private void ProcessCollision(Character me, bool enabled) { if (!enabled) { _collision.RestoreAll(); } else { _collision.Apply(me, _targets, Time.unscaledTime); } } private void ProcessVisibility(Character me, float opacity, bool semiTransparent, bool inFovOnly, bool forceReapply) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if (!semiTransparent) { for (int i = 0; i < _states.Count; i++) { CharacterState characterState = _states[i]; if (characterState.Transparent && !((Object)(object)characterState.Character == (Object)null)) { RefreshCharacter(characterState.Character, transparent: false, opacity, includeBackpack: false, includeHeldItem: false, reapply: false); } } return; } float value = ModConfig.TriggerDistance.Value; bool value2 = ModConfig.SemiTransparentBackpack.Value; bool value3 = ModConfig.SemiTransparentHeldItem.Value; Vector3 center = me.Center; for (int j = 0; j < _targets.Count; j++) { Character val = _targets[j]; if ((Object)(object)val == (Object)null || val.refs == null) { continue; } bool flag = false; if (Vector3.Distance(center, val.Center) <= value && (!inFovOnly || MainCamera.PointInFieldOfView(val.Center))) { flag = true; } CharacterState characterState2 = FindState(val); if (characterState2 == null) { if (flag) { RefreshCharacter(val, transparent: true, opacity, value2, value3, reapply: true); } continue; } if (!flag) { if (characterState2.Transparent) { RefreshCharacter(val, transparent: false, opacity, value2, value3, reapply: false); } continue; } Item obj = (((Object)(object)val.data != (Object)null) ? val.data.currentItem : null); BackpackOnBackVisuals val2 = null; if ((Object)(object)val.refs.backpackHandler != (Object)null) { val2 = val.refs.backpackHandler.activeBackpackVisuals; } bool flag2 = obj != characterState2.LastItem || val2 != characterState2.LastBackpack; if (!characterState2.Transparent || flag2 || forceReapply) { RefreshCharacter(val, transparent: true, opacity, value2, value3, reapply: true); } } } private CharacterState FindState(Character character) { for (int i = 0; i < _states.Count; i++) { if (_states[i].Character == character) { return _states[i]; } } return null; } private void RefreshCharacter(Character character, bool transparent, float opacity, bool includeBackpack, bool includeHeldItem, bool reapply) { if ((Object)(object)character == (Object)null || character.refs == null) { return; } CharacterState characterState = FindState(character); if (characterState == null) { characterState = new CharacterState { Character = character }; _states.Add(characterState); } _wanted.Clear(); Item lastItem = null; BackpackOnBackVisuals lastBackpack = null; if (transparent) { TargetMaterialCollector.Collect(character, includeBackpack, includeHeldItem, _wanted, _materialBuffer); if ((Object)(object)character.data != (Object)null) { lastItem = character.data.currentItem; } if ((Object)(object)character.refs.backpackHandler != (Object)null) { lastBackpack = character.refs.backpackHandler.activeBackpackVisuals; } } characterState.RestoreBuffer.Clear(); foreach (Material material in characterState.Materials) { if ((Object)(object)material == (Object)null || !_wanted.ContainsKey(material)) { characterState.RestoreBuffer.Add(material); } } for (int i = 0; i < characterState.RestoreBuffer.Count; i++) { Material val = characterState.RestoreBuffer[i]; characterState.Materials.Remove(val); RestoreMaterial(val); } if (transparent) { foreach (KeyValuePair item in _wanted) { Material key = item.Key; if (!((Object)(object)key == (Object)null) && (characterState.Materials.Add(key) || reapply)) { ActivateMaterial(key, item.Value, opacity); } } } characterState.Transparent = transparent; characterState.LastItem = lastItem; characterState.LastBackpack = lastBackpack; } private void ActivateMaterial(Material material, bool forceSwitch, float opacity) { if (!((Object)(object)material == (Object)null)) { if (!_backups.TryGetValue(material, out var value)) { value = MaterialTransparency.Capture(material); _backups[material] = value; } MaterialTransparency.SetTransparent(material, opacity, forceSwitch, value); } } private void RestoreMaterial(Material material) { if (!((Object)(object)material == (Object)null)) { if (_backups.TryGetValue(material, out var value)) { MaterialTransparency.Restore(material, value); _backups.Remove(material); } else { MaterialTransparency.Restore(material, null); } } } private void CleanupStates() { for (int num = _states.Count - 1; num >= 0; num--) { CharacterState characterState = _states[num]; Character character = characterState.Character; if (!((Object)(object)character != (Object)null) || !_targets.Contains(character)) { foreach (Material material in characterState.Materials) { RestoreMaterial(material); } characterState.Materials.Clear(); _states.RemoveAt(num); } } } private void ReleaseAllMaterials() { for (int i = 0; i < _states.Count; i++) { HashSet materials = _states[i].Materials; foreach (Material item in materials) { RestoreMaterial(item); } materials.Clear(); } _states.Clear(); if (_backups.Count > 0) { _backupKeys.Clear(); foreach (KeyValuePair backup in _backups) { _backupKeys.Add(backup.Key); } for (int j = 0; j < _backupKeys.Count; j++) { RestoreMaterial(_backupKeys[j]); } _backups.Clear(); } _lastAppliedOpacity = -1f; } } internal sealed class PlayerCollisionManager { private sealed class Target { public Character Character; public readonly List Colliders = new List(); public float NextRefresh; public bool Seen; } private const float ApplyInterval = 0.5f; private const float ColliderRefreshInterval = 2f; private readonly List _targets = new List(); private readonly List _local = new List(); private float _nextApply; private float _nextLocalRefresh; private Character _localCharacter; public int TargetCount => _targets.Count; public int LocalColliderCount => _local.Count; public int ColliderCountOf(int index) { if (index < 0 || index >= _targets.Count) { return 0; } return _targets[index].Colliders.Count; } public bool AreIgnored(int index) { if (_local.Count == 0 || index < 0 || index >= _targets.Count) { return false; } List colliders = _targets[index].Colliders; if (colliders.Count == 0) { return false; } return Physics.GetIgnoreCollision(_local[0], colliders[0]); } public void Apply(Character me, List characters, float now) { if ((Object)(object)me == (Object)null || me.refs == null) { RestoreAll(); return; } if (me != _localCharacter) { RestoreAll(); _localCharacter = me; _nextLocalRefresh = 0f; } if (now >= _nextLocalRefresh) { _nextLocalRefresh = now + 2f; CollectColliders(me, _local); } SyncTargets(characters, now); if (!(now < _nextApply)) { _nextApply = now + 0.5f; ApplyPairs(); } } public void RestoreAll() { for (int i = 0; i < _targets.Count; i++) { RestoreTarget(_targets[i]); } _targets.Clear(); _local.Clear(); _localCharacter = null; _nextApply = 0f; _nextLocalRefresh = 0f; } private void SyncTargets(List characters, float now) { for (int i = 0; i < _targets.Count; i++) { _targets[i].Seen = false; } if (characters != null) { for (int j = 0; j < characters.Count; j++) { Character val = characters[j]; if (!((Object)(object)val == (Object)null) && val != _localCharacter) { Target target = Find(val); if (target == null) { target = new Target { Character = val }; _targets.Add(target); } target.Seen = true; if (now >= target.NextRefresh) { target.NextRefresh = now + 2f; CollectColliders(val, target.Colliders); } } } } for (int num = _targets.Count - 1; num >= 0; num--) { if (!_targets[num].Seen) { RestoreTarget(_targets[num]); _targets.RemoveAt(num); } } } private void ApplyPairs() { if (_local.Count == 0) { return; } for (int i = 0; i < _targets.Count; i++) { List colliders = _targets[i].Colliders; if (colliders.Count == 0) { continue; } for (int j = 0; j < _local.Count; j++) { Collider val = _local[j]; if (!IsActive(val)) { continue; } for (int k = 0; k < colliders.Count; k++) { Collider val2 = colliders[k]; if (IsActive(val2) && !Physics.GetIgnoreCollision(val, val2)) { Physics.IgnoreCollision(val, val2, true); } } } } } private void RestoreTarget(Target target) { List colliders = target.Colliders; for (int i = 0; i < _local.Count; i++) { Collider val = _local[i]; if ((Object)(object)val == (Object)null) { continue; } for (int j = 0; j < colliders.Count; j++) { Collider val2 = colliders[j]; if (!((Object)(object)val2 == (Object)null) && Physics.GetIgnoreCollision(val, val2)) { Physics.IgnoreCollision(val, val2, false); } } } colliders.Clear(); } private Target Find(Character character) { for (int i = 0; i < _targets.Count; i++) { if (_targets[i].Character == character) { return _targets[i]; } } return null; } private static void CollectColliders(Character character, List result) { result.Clear(); if (!((Object)(object)character == (Object)null) && character.refs != null) { CharacterRagdoll ragdoll = character.refs.ragdoll; if ((Object)(object)ragdoll != (Object)null) { AddColliders((Component)(object)ragdoll, result); } AddColliders((Component)(object)character, result); } } private static void AddColliders(Component root, List result) { if ((Object)(object)root == (Object)null) { return; } Collider[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (IsActive(val) && !result.Contains(val)) { result.Add(val); } } } private static bool IsActive(Collider collider) { if ((Object)(object)collider == (Object)null) { return false; } if (!collider.enabled) { return false; } if (collider.isTrigger) { return false; } if (!((Component)collider).gameObject.activeInHierarchy) { return false; } Rigidbody attachedRigidbody = collider.attachedRigidbody; if ((Object)(object)attachedRigidbody != (Object)null && !attachedRigidbody.detectCollisions) { return false; } return true; } } [BepInPlugin("PhantomParty", "Phantom Party", "0.2.3")] [BepInProcess("PEAK.exe")] public class Plugin : BaseUnityPlugin { private void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown PluginInfo.Init(((BaseUnityPlugin)this).Logger); ModConfig.BindAll(((BaseUnityPlugin)this).Config); GameObject val = new GameObject("PhantomPartyController"); Object.DontDestroyOnLoad((Object)val); val.AddComponent(); PluginInfo.Log("已加载 v0.2.3 —— 总开关 " + (ModConfig.Enable.Value ? "开" : "关") + ",禁用碰撞 " + (ModConfig.DisableCollision.Value ? "开" : "关") + ",半透明 " + (ModConfig.SemiTransparent.Value ? "开" : "关") + ",不透明度 " + ModConfig.Opacity.Value + ",触发距离 " + ModConfig.TriggerDistance.Value + " 米,仅视野内 " + (ModConfig.InFovOnly.Value ? "开" : "关") + ",包含 Bot " + (ModConfig.IncludeBots.Value ? "开" : "关") + ",透明背包 " + (ModConfig.SemiTransparentBackpack.Value ? "开" : "关") + ",透明手持物品 " + (ModConfig.SemiTransparentHeldItem.Value ? "开" : "关")); } } internal static class PluginInfo { public const string GUID = "PhantomParty"; public const string Name = "Phantom Party"; public const string Version = "0.2.3"; private static ManualLogSource _logger; public static void Init(ManualLogSource logger) { _logger = logger; } public static void Log(object message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo(message); } } } internal static class TargetMaterialCollector { public static void Collect(Character character, bool includeBackpack, bool includeHeldItem, Dictionary result, List materialBuffer) { result.Clear(); if (!((Object)(object)character == (Object)null)) { CollectCustomization(character, result, materialBuffer); CollectBadge(character, result, materialBuffer); if (includeBackpack) { CollectBackpack(character, result, materialBuffer); } if (includeHeldItem) { CollectHeldItem(character, result, materialBuffer); } } } private static void CollectBadge(Character character, Dictionary result, List buffer) { if (character.refs != null) { BadgeUnlocker badgeUnlocker = character.refs.badgeUnlocker; if (!((Object)(object)badgeUnlocker == (Object)null)) { AddRenderer(badgeUnlocker.badgeSashRenderer, forceSwitch: true, result, buffer); } } } private static void CollectCustomization(Character character, Dictionary result, List buffer) { if (character.refs == null) { return; } CharacterCustomization customization = character.refs.customization; if ((Object)(object)customization == (Object)null) { return; } CustomizationRefs refs = customization.refs; if (!((Object)(object)refs == (Object)null)) { AddRenderers(refs.AllRenderers, forceSwitch: false, result, buffer); AddRenderers(refs.playerHats, forceSwitch: true, result, buffer); if ((Object)(object)refs.hatTransform != (Object)null) { AddRenderers(((Component)refs.hatTransform).GetComponentsInChildren(true), forceSwitch: true, result, buffer); } if ((Object)(object)refs.hatShadowMeshFilter != (Object)null) { AddRenderer(((Component)refs.hatShadowMeshFilter).GetComponent(), forceSwitch: true, result, buffer); } } } private static void CollectBackpack(Character character, Dictionary result, List buffer) { if (character.refs == null) { return; } CharacterBackpackHandler backpackHandler = character.refs.backpackHandler; if ((Object)(object)backpackHandler == (Object)null) { return; } BackpackOnBackVisuals val = ActiveBackpackVisuals(backpackHandler); if (!((Object)(object)val == (Object)null)) { AddRenderers(((Component)val).GetComponentsInChildren(true), forceSwitch: true, result, buffer); GameObject view = val.view; if ((Object)(object)view != (Object)null && (Object)(object)view != (Object)(object)((Component)val).gameObject) { AddRenderers(view.GetComponentsInChildren(true), forceSwitch: true, result, buffer); } } } private static BackpackOnBackVisuals ActiveBackpackVisuals(CharacterBackpackHandler handler) { try { return handler.activeBackpackVisuals; } catch { return null; } } public static string DescribeBackpack(Character character) { if ((Object)(object)character == (Object)null || character.refs == null) { return "无角色引用"; } CharacterBackpackHandler backpackHandler = character.refs.backpackHandler; if ((Object)(object)backpackHandler == (Object)null) { return "无背包处理器"; } BackpackOnBackVisuals val = ActiveBackpackVisuals(backpackHandler); if ((Object)(object)val == (Object)null) { return "无背包视觉"; } int num = 0; int num2 = 0; string text = null; string text2 = null; Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null) { continue; } num++; if (!val2.enabled || !((Component)val2).gameObject.activeInHierarchy) { continue; } num2++; if (text == null) { Material sharedMaterial = val2.sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null) { text = (((Object)(object)sharedMaterial.shader != (Object)null) ? ((Object)sharedMaterial.shader).name : "?"); bool flag = sharedMaterial.HasProperty(MaterialTransparency.OpacityProp); bool flag2 = sharedMaterial.HasProperty(MaterialTransparency.TintProp); bool flag3 = sharedMaterial.HasProperty(MaterialTransparency.SurfaceProp); text2 = "Opacity=" + (flag ? "有" : "无") + " Tint=" + (flag2 ? "有" : "无") + " Surface=" + (flag3 ? "有" : "无"); } } } bool flag4 = (Object)(object)val.view != (Object)null && val.view.activeInHierarchy; return "背包渲染器 " + num + "(可用 " + num2 + "),view " + (flag4 ? "激活" : "未激活") + ((text != null) ? (",shader=" + text + "," + text2) : ""); } private static void CollectHeldItem(Character character, Dictionary result, List buffer) { if (!((Object)(object)character.data == (Object)null)) { Item currentItem = character.data.currentItem; if (!((Object)(object)currentItem == (Object)null)) { AddRenderers(((Component)currentItem).GetComponentsInChildren(true), forceSwitch: true, result, buffer); } } } private static void AddRenderers(Renderer[] renderers, bool forceSwitch, Dictionary result, List buffer) { if (renderers != null) { for (int i = 0; i < renderers.Length; i++) { AddRenderer(renderers[i], forceSwitch, result, buffer); } } } private static void AddRenderer(Renderer renderer, bool forceSwitch, Dictionary result, List buffer) { if ((Object)(object)renderer == (Object)null || !renderer.enabled || !((Component)renderer).gameObject.activeInHierarchy) { return; } buffer.Clear(); renderer.GetMaterials(buffer); for (int i = 0; i < buffer.Count; i++) { Material val = buffer[i]; if ((Object)(object)val == (Object)null) { continue; } if (result.TryGetValue(val, out var value)) { if (forceSwitch && !value) { result[val] = true; } } else { result[val] = forceSwitch; } } } } }