Decompiled source of PhantomParty v0.2.3

plugins/PhantomParty.dll

Decompiled a day ago
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<bool> Enable;

		public static ConfigEntry<bool> DisableCollision;

		public static ConfigEntry<bool> SemiTransparent;

		public static ConfigEntry<bool> SemiTransparentBackpack;

		public static ConfigEntry<bool> SemiTransparentHeldItem;

		public static ConfigEntry<float> Opacity;

		public static ConfigEntry<float> TriggerDistance;

		public static ConfigEntry<bool> InFovOnly;

		public static ConfigEntry<bool> 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<bool>("通用", "总开关", true, new ConfigDescription("关闭后所有功能(禁用碰撞、半透明)都不生效。改完保存配置文件即生效,无需重启游戏。", (AcceptableValueBase)null, Array.Empty<object>()));
			DisableCollision = config.Bind<bool>("碰撞", "禁用玩家碰撞", true, new ConfigDescription("开启后本玩家与所有远程玩家之间的碰撞被忽略:两人挤在一起时不会互相碰撞或推挤,可以穿过对方。世界物体(地面、墙壁、道具)的碰撞不受影响。仅客户端生效,服务器侧照常,不会影响其他玩家的体验。", (AcceptableValueBase)null, Array.Empty<object>()));
			SemiTransparent = config.Bind<bool>("视野", "近距离半透明", true, new ConfigDescription("开启后当其他玩家靠近到触发距离以内、且进入视野范围时,其身体与帽子会以「不透明度」指定的值渲染(默认 0.25,即 75% 透明)。距离触发范围外或不在视野内时自动恢复正常外观。仅客户端渲染,其他玩家看不到你本地做的透明度变化。", (AcceptableValueBase)null, Array.Empty<object>()));
			SemiTransparentBackpack = config.Bind<bool>("视野", "透明化背包", false, new ConfigDescription("开启后,处于半透明触发范围内的玩家,其背上的背包也一起变透明。默认关闭:背包不参与半透明,仍会挡住视线。", (AcceptableValueBase)null, Array.Empty<object>()));
			SemiTransparentHeldItem = config.Bind<bool>("视野", "透明化手持物品", false, new ConfigDescription("开启后,处于半透明触发范围内的玩家,其手中正在拿的物品也一起变透明。默认关闭:手持物品不参与半透明。", (AcceptableValueBase)null, Array.Empty<object>()));
			Opacity = config.Bind<float>("视野", "不透明度", 0.25f, new ConfigDescription("半透明渲染时目标的不透明度取值(0.0 ~ 1.0)。0.25 = 很透明,能看到背后的地形和其他物体(默认);0.50 = 半透明;0.75 = 稍透明;1.0 = 完全不透明(等同禁用该功能)。改完保存配置文件即生效。", (AcceptableValueBase)null, Array.Empty<object>()));
			TriggerDistance = config.Bind<float>("视野", "触发距离", 2f, new ConfigDescription("半透明效果的距离上限(单位:米,取玩家中心点距离)。其他玩家距离本玩家小于此值时触发半透明。默认 2.0 米,覆盖两人挤在一起的主要场景。0 表示立即触发,10 以上会明显遮挡远处玩家。", (AcceptableValueBase)null, Array.Empty<object>()));
			InFovOnly = config.Bind<bool>("视野", "仅视野内生效", true, new ConfigDescription("开启后仅当其他玩家处于本玩家当前视野内(相机可见范围)时才半透明。关闭则任意方向的近距离玩家都会触发半透明。开启会略微增加开销(相机 FOV 判断),但视觉更聚焦,推荐开启。", (AcceptableValueBase)null, Array.Empty<object>()));
			IncludeBots = config.Bind<bool>("范围", "处理 Bot 玩家", true, new ConfigDescription("开启后 NPC/Bot 玩家也按同样规则处理(禁用碰撞 + 近距离半透明)。关闭则 Bot 保持原版行为(会碰撞、不透明)。", (AcceptableValueBase)null, Array.Empty<object>()));
		}
	}
	public class PhantomPartyController : MonoBehaviour
	{
		private sealed class CharacterState
		{
			public Character Character;

			public bool Transparent;

			public Item LastItem;

			public BackpackOnBackVisuals LastBackpack;

			public readonly HashSet<Material> Materials = new HashSet<Material>();

			public readonly List<Material> RestoreBuffer = new List<Material>();
		}

		private const float RefreshInterval = 0.5f;

		private readonly List<CharacterState> _states = new List<CharacterState>();

		private readonly Dictionary<Material, MaterialBackup> _backups = new Dictionary<Material, MaterialBackup>();

		private readonly PlayerCollisionManager _collision = new PlayerCollisionManager();

		private readonly List<Character> _targets = new List<Character>();

		private readonly Dictionary<Material, bool> _wanted = new Dictionary<Material, bool>();

		private readonly List<Material> _materialBuffer = new List<Material>();

		private readonly List<Material> _backupKeys = new List<Material>();

		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<Character> 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<Character> 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<Material, bool> 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<Material> materials = _states[i].Materials;
				foreach (Material item in materials)
				{
					RestoreMaterial(item);
				}
				materials.Clear();
			}
			_states.Clear();
			if (_backups.Count > 0)
			{
				_backupKeys.Clear();
				foreach (KeyValuePair<Material, MaterialBackup> 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<Collider> Colliders = new List<Collider>();

			public float NextRefresh;

			public bool Seen;
		}

		private const float ApplyInterval = 0.5f;

		private const float ColliderRefreshInterval = 2f;

		private readonly List<Target> _targets = new List<Target>();

		private readonly List<Collider> _local = new List<Collider>();

		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<Collider> colliders = _targets[index].Colliders;
			if (colliders.Count == 0)
			{
				return false;
			}
			return Physics.GetIgnoreCollision(_local[0], colliders[0]);
		}

		public void Apply(Character me, List<Character> 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<Character> 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<Collider> 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<Collider> 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<Collider> 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<Collider> result)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(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<PhantomPartyController>();
			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<Material, bool> result, List<Material> 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<Material, bool> result, List<Material> 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<Material, bool> result, List<Material> 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<Renderer>(true), forceSwitch: true, result, buffer);
				}
				if ((Object)(object)refs.hatShadowMeshFilter != (Object)null)
				{
					AddRenderer(((Component)refs.hatShadowMeshFilter).GetComponent<Renderer>(), forceSwitch: true, result, buffer);
				}
			}
		}

		private static void CollectBackpack(Character character, Dictionary<Material, bool> result, List<Material> 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<Renderer>(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<Renderer>(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<Renderer>(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<Material, bool> result, List<Material> buffer)
		{
			if (!((Object)(object)character.data == (Object)null))
			{
				Item currentItem = character.data.currentItem;
				if (!((Object)(object)currentItem == (Object)null))
				{
					AddRenderers(((Component)currentItem).GetComponentsInChildren<Renderer>(true), forceSwitch: true, result, buffer);
				}
			}
		}

		private static void AddRenderers(Renderer[] renderers, bool forceSwitch, Dictionary<Material, bool> result, List<Material> 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<Material, bool> result, List<Material> 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;
				}
			}
		}
	}
}