Decompiled source of AllyOutline v1.0.0

AllyOutline.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AllyOutline")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Outlines teammates through walls")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AllyOutline")]
[assembly: AssemblyTitle("AllyOutline")]
[assembly: AssemblyVersion("1.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 AllyOutline
{
	internal static class AllyOutliner
	{
		private static Object _requester;

		private static bool _hooked;

		private static bool _requesting;

		private static readonly List<CharacterBody> Targets = new List<CharacterBody>();

		private static readonly ReadOnlyCollection<TeamComponent> EmptyTeam = new ReadOnlyCollection<TeamComponent>(Array.Empty<TeamComponent>());

		internal static void Init(Object requester)
		{
			_requester = requester;
			try
			{
				OutlineHighlight.onPreRenderOutlineHighlight = (Action<OutlineHighlight>)Delegate.Combine(OutlineHighlight.onPreRenderOutlineHighlight, new Action<OutlineHighlight>(OnPreRenderOutlineHighlight));
				_hooked = true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("OutlineHighlight のフックに失敗しました。縁取りは無効になります: " + ex));
			}
		}

		internal static void Shutdown()
		{
			if (_hooked)
			{
				OutlineHighlight.onPreRenderOutlineHighlight = (Action<OutlineHighlight>)Delegate.Remove(OutlineHighlight.onPreRenderOutlineHighlight, new Action<OutlineHighlight>(OnPreRenderOutlineHighlight));
				_hooked = false;
			}
			ReleaseRequest();
			_requester = null;
		}

		internal static void Tick()
		{
			if (!_hooked)
			{
				return;
			}
			bool flag = ModConfig.Enabled.Value && HasAnyTarget();
			if (flag != _requesting)
			{
				if (flag)
				{
					_requesting = true;
					OutlineHighlight.AddPreRenderHighlightRequest(_requester);
				}
				else
				{
					ReleaseRequest();
				}
			}
		}

		private static void ReleaseRequest()
		{
			if (_requesting)
			{
				_requesting = false;
				OutlineHighlight.ReleasePreRenderHighlightRequest(_requester);
			}
		}

		private static void OnPreRenderOutlineHighlight(OutlineHighlight outlineHighlight)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Enabled.Value || !Object.op_Implicit((Object)(object)outlineHighlight))
			{
				return;
			}
			try
			{
				SceneCamera sceneCamera = outlineHighlight.sceneCamera;
				if (!Object.op_Implicit((Object)(object)sceneCamera))
				{
					return;
				}
				CameraRigController cameraRigController = sceneCamera.cameraRigController;
				if (Object.op_Implicit((Object)(object)cameraRigController))
				{
					Color outlineColor = GetOutlineColor();
					SilhouetteFill.BeginFrame(outlineHighlight, outlineColor);
					CollectTargets(cameraRigController);
					for (int i = 0; i < Targets.Count; i++)
					{
						AddOutline(outlineHighlight, Targets[i], outlineColor);
					}
					Targets.Clear();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("縁取りの追加に失敗しました: " + ex));
			}
		}

		private static bool HasAnyTarget()
		{
			ReadOnlyCollection<CameraRigController> readOnlyInstancesList = CameraRigController.readOnlyInstancesList;
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CameraRigController val = readOnlyInstancesList[i];
				if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).enabled)
				{
					CollectTargets(val);
					int count = Targets.Count;
					Targets.Clear();
					if (count > 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		internal static void CollectTargets(CameraRigController rig)
		{
			Targets.Clear();
			CharacterBody targetBody = rig.targetBody;
			ReadOnlyCollection<TeamComponent> allies = GetAllies(rig);
			for (int i = 0; i < allies.Count; i++)
			{
				CharacterBody outlineTarget = GetOutlineTarget(allies[i], targetBody);
				if (Object.op_Implicit((Object)(object)outlineTarget))
				{
					Targets.Add(outlineTarget);
				}
			}
		}

		private static ReadOnlyCollection<TeamComponent> GetAllies(CameraRigController rig)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			TeamIndex targetTeamIndex = rig.targetTeamIndex;
			if ((int)targetTeamIndex != -1)
			{
				return TeamComponent.GetTeamMembers(targetTeamIndex);
			}
			return EmptyTeam;
		}

		private static CharacterBody GetOutlineTarget(TeamComponent teamComponent, CharacterBody viewer)
		{
			if (!Object.op_Implicit((Object)(object)teamComponent))
			{
				return null;
			}
			CharacterBody body = teamComponent.body;
			if (!Object.op_Implicit((Object)(object)body))
			{
				return null;
			}
			if (!ModConfig.ShowSelf.Value && (Object)(object)body == (Object)(object)viewer)
			{
				return null;
			}
			if (ModConfig.ShowMinions.Value)
			{
				return body;
			}
			if (!IsPlayer(body))
			{
				return null;
			}
			return body;
		}

		private static bool IsPlayer(CharacterBody body)
		{
			CharacterMaster master = body.master;
			if (Object.op_Implicit((Object)(object)master))
			{
				return Object.op_Implicit((Object)(object)master.playerCharacterMasterController);
			}
			return false;
		}

		private static void AddOutline(OutlineHighlight outlineHighlight, CharacterBody body, Color color)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			CharacterModel model = GetModel(body);
			if (!Object.op_Implicit((Object)(object)model) || (int)model.visibility == 0)
			{
				return;
			}
			RendererInfo[] baseRendererInfos = model.baseRendererInfos;
			if (baseRendererInfos == null)
			{
				return;
			}
			for (int i = 0; i < baseRendererInfos.Length; i++)
			{
				Renderer renderer = baseRendererInfos[i].renderer;
				if (Object.op_Implicit((Object)(object)renderer) && renderer.enabled && ((Component)renderer).gameObject.activeInHierarchy && !SilhouetteFill.TryDraw(renderer))
				{
					outlineHighlight.AddHighlight(renderer, color);
				}
			}
		}

		internal static CharacterModel GetModel(CharacterBody body)
		{
			ModelLocator modelLocator = body.modelLocator;
			if (!Object.op_Implicit((Object)(object)modelLocator))
			{
				return null;
			}
			Transform modelTransform = modelLocator.modelTransform;
			if (!Object.op_Implicit((Object)(object)modelTransform))
			{
				return null;
			}
			return ((Component)modelTransform).GetComponent<CharacterModel>();
		}

		private static Color GetOutlineColor()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return Color32.op_Implicit(Color32.op_Implicit(ModConfig.OutlineColor.Value));
		}
	}
	internal static class ModConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> ShowSelf;

		public static ConfigEntry<bool> ShowMinions;

		public static ConfigEntry<Color> OutlineColor;

		public static void Init(ConfigFile config)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			EnsureColorConverter();
			Enabled = config.Bind<bool>("General", "Enabled", true, "味方プレイヤーを縁取る。off にするとバニラの見た目に戻る。");
			ShowSelf = config.Bind<bool>("General", "Show Self", false, "自分自身も縁取る。自分は常に画面の中心に居るので既定では縁取らない。");
			ShowMinions = config.Bind<bool>("General", "Show Minions", true, "味方が連れているドローン・タレット・召喚も縁取る。off にすると操作プレイヤーだけになる。");
			OutlineColor = config.Bind<Color>("General", "Outline Color", new Color(0.2f, 0.8f, 1f, 1f), "縁取りの色。アルファは縁取りの濃さになる。RoR2 は色ごとにマテリアルを作って保持し続けるので、毎フレーム変わるような使い方はしない。");
			if (!Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				Plugin.Log.LogInfo((object)"Risk of Options が見つからないので設定画面は登録しません。");
				return;
			}
			try
			{
				RegisterRiskOfOptions();
				Plugin.Log.LogInfo((object)"Risk of Options へ設定を登録しました。");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Risk of Options への設定登録に失敗しました: " + ex));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void RegisterRiskOfOptions()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("味方の輪郭を壁越しに表示します。誰がどこにいるか常に分かります。連れているタレットやドローンも含みます。自分自身は既定では縁取りません。");
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(ShowMinions));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(ShowSelf));
			ModSettingsManager.AddOption((BaseOption)new ColorOption(OutlineColor));
		}

		private static void EnsureColorConverter()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			if (TomlTypeConverter.CanConvert(typeof(Color)))
			{
				return;
			}
			TomlTypeConverter.AddConverter(typeof(Color), new TypeConverter
			{
				ConvertToString = (object obj, Type type) => "#" + ColorUtility.ToHtmlStringRGBA((Color)obj),
				ConvertToObject = delegate(string str, Type type)
				{
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					//IL_000a: Unknown result type (might be due to invalid IL or missing references)
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					Color white = default(Color);
					if (!ColorUtility.TryParseHtmlString(str, ref white))
					{
						white = Color.white;
					}
					return white;
				}
			});
		}
	}
	[BepInPlugin("OchaDashiMan.AllyOutline", "AllyOutline", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "OchaDashiMan.AllyOutline";

		public const string ModName = "AllyOutline";

		public const string Version = "1.0.0";

		internal const string RiskOfOptionsGuid = "com.rune580.riskofoptions";

		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			AllyOutliner.Init((Object)(object)this);
			Log.LogInfo((object)"AllyOutline 1.0.0 loaded.");
		}

		private void Update()
		{
			AllyOutliner.Tick();
		}

		private void OnDestroy()
		{
			AllyOutliner.Shutdown();
		}
	}
	internal static class SilhouetteFill
	{
		internal const string DefaultShaderName = "Hopoo Games/FX/Cloud Remap";

		private const string ZTestName = "_ZTest";

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private static readonly int TintColorId = Shader.PropertyToID("_TintColor");

		private static readonly int ZTestId = Shader.PropertyToID("_ZTest");

		private static readonly int ZWriteId = Shader.PropertyToID("_ZWrite");

		private static readonly int CullId = Shader.PropertyToID("_Cull");

		private static readonly int SrcBlendId = Shader.PropertyToID("_SrcBlend");

		private static readonly int DstBlendId = Shader.PropertyToID("_DstBlend");

		private static readonly int MainTexId = Shader.PropertyToID("_MainTex");

		private static FieldInfo _commandBufferField;

		private static bool _commandBufferFieldMissing;

		private static Material _material;

		private static string _materialShaderName;

		private static bool _shaderMissingLogged;

		private static CommandBuffer _buffer;

		private static bool _active;

		internal static void BeginFrame(OutlineHighlight outlineHighlight, Color color)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			_active = false;
			Material material = GetMaterial(ResolveShaderName());
			if (!Object.op_Implicit((Object)(object)material))
			{
				return;
			}
			CommandBuffer commandBuffer = GetCommandBuffer(outlineHighlight);
			if (commandBuffer != null)
			{
				if (material.HasProperty(ColorId))
				{
					material.SetColor(ColorId, color);
				}
				if (material.HasProperty(TintColorId))
				{
					material.SetColor(TintColorId, color);
				}
				_buffer = commandBuffer;
				_material = material;
				_active = true;
			}
		}

		internal static bool TryDraw(Renderer renderer)
		{
			if (!_active)
			{
				return false;
			}
			_buffer.DrawRenderer(renderer, _material, 0, 0);
			return true;
		}

		private static string ResolveShaderName()
		{
			return "Hopoo Games/FX/Cloud Remap";
		}

		private static Material GetMaterial(string shaderName)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)_material) && _materialShaderName == shaderName)
			{
				return _material;
			}
			Shader val = FindLoadedShader(shaderName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				if (!_shaderMissingLogged)
				{
					_shaderMissingLogged = true;
					Plugin.Log.LogWarning((object)("塗りつぶし用のシェーダー \"" + shaderName + "\" が見つかりません。バニラの塗りつぶしへ落とします(縁取りは出ますが壁越しにはなりません)。"));
				}
				return null;
			}
			Material val2 = new Material(val)
			{
				hideFlags = (HideFlags)61
			};
			if (val2.HasProperty(ZTestId))
			{
				val2.SetInt(ZTestId, 8);
			}
			if (val2.HasProperty(ZWriteId))
			{
				val2.SetInt(ZWriteId, 0);
			}
			if (val2.HasProperty(CullId))
			{
				val2.SetInt(CullId, 0);
			}
			if (val2.HasProperty(SrcBlendId))
			{
				val2.SetInt(SrcBlendId, 1);
			}
			if (val2.HasProperty(DstBlendId))
			{
				val2.SetInt(DstBlendId, 0);
			}
			if (val2.HasProperty(MainTexId))
			{
				val2.SetTexture(MainTexId, (Texture)(object)Texture2D.whiteTexture);
			}
			SuppressFading(val2);
			_material = val2;
			_materialShaderName = shaderName;
			return val2;
		}

		private static void SuppressFading(Material material)
		{
			material.DisableKeyword("SOFTPARTICLES_ON");
			SetIfPresent(material, "_FadeCloseOn", 0f);
			SetIfPresent(material, "_FadeCloseDistance", 0f);
			SetIfPresent(material, "_VertexColorOn", 0f);
			SetIfPresent(material, "_VertexAlphaOn", 0f);
			SetIfPresent(material, "_VertColor", 0f);
			SetIfPresent(material, "_Fade", 1f);
			SetIfPresent(material, "_ExternalAlpha", 1f);
			SetIfPresent(material, "_AlphaBias", 0f);
			SetIfPresent(material, "_Cutoff", 0f);
			SetIfPresent(material, "_WireframeOnly", 0f);
		}

		private static void SetIfPresent(Material material, string name, float value)
		{
			if (material.HasProperty(name))
			{
				material.SetFloat(name, value);
			}
		}

		internal static Shader FindLoadedShader(string name)
		{
			Shader[] array = Resources.FindObjectsOfTypeAll<Shader>();
			for (int i = 0; i < array.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)array[i]) && ((Object)array[i]).name == name)
				{
					return array[i];
				}
			}
			return null;
		}

		private static CommandBuffer GetCommandBuffer(OutlineHighlight outlineHighlight)
		{
			if (_commandBufferFieldMissing)
			{
				return null;
			}
			if (_commandBufferField == null)
			{
				_commandBufferField = typeof(OutlineHighlight).GetField("commandBuffer", BindingFlags.Instance | BindingFlags.NonPublic);
				if (_commandBufferField == null)
				{
					_commandBufferFieldMissing = true;
					Plugin.Log.LogWarning((object)"OutlineHighlight.commandBuffer が見つかりません。バニラの塗りつぶしへ落とします(縁取りは出ますが壁越しにはなりません)。");
					return null;
				}
			}
			object? value = _commandBufferField.GetValue(outlineHighlight);
			return (CommandBuffer)((value is CommandBuffer) ? value : null);
		}
	}
}