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;
}
}
}
}
}