Decompiled source of YouDied v1.0.5

YouDied.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;
using YouDied.Config;
using YouDied.Features;
using YouDied.Infrastructure;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("YouDied")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+e6dae0eee805cf95559389a1e4c3d769a9885640")]
[assembly: AssemblyProduct("YouDied")]
[assembly: AssemblyTitle("YouDied")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.5.0")]
[module: UnverifiableCode]
[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 YouDied
{
	[BepInPlugin("JevMods.YouDied", "YouDied", "1.0.5")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "JevMods.YouDied";

		public const string PluginName = "YouDied";

		private IFeature[] _features;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			GameEvents events = (GameEvents.Instance = new GameEvents());
			DeathScreen deathScreen = ((Component)this).gameObject.AddComponent<DeathScreen>();
			deathScreen.Initialize(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "assets"));
			ModSettings settings = new ModSettings(((BaseUnityPlugin)this).Config);
			_features = new IFeature[2]
			{
				new DeathTimingFeature(events),
				new DeathScreenFeature(events, settings, deathScreen)
			};
			IFeature[] features = _features;
			for (int i = 0; i < features.Length; i++)
			{
				features[i].Enable();
			}
			_harmony = new Harmony("JevMods.YouDied");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if (_features != null)
			{
				IFeature[] features = _features;
				for (int i = 0; i < features.Length; i++)
				{
					features[i].Disable();
				}
			}
			GameEvents.Instance = null;
		}
	}
	internal static class BuildInfo
	{
		public const string Version = "1.0.5";
	}
}
namespace YouDied.Patches
{
	internal static class GamePatches
	{
		[HarmonyPatch(typeof(Game), "RequestRespawn")]
		private static class RequestRespawn
		{
			private static void Prefix(ref float delay, bool afterDeath)
			{
				GameEvents.Instance?.RaiseRespawnRequested(ref delay, afterDeath);
			}
		}
	}
	internal static class HudPatches
	{
		[HarmonyPatch(typeof(Hud), "UpdateBlackScreen")]
		private static class UpdateBlackScreen
		{
			private static bool Prefix(Player player)
			{
				bool skip = false;
				GameEvents.Instance?.RaiseBlackScreenUpdating(player, ref skip);
				return !skip;
			}
		}
	}
	internal static class PlayerPatches
	{
		[HarmonyPatch(typeof(Player), "OnDeath")]
		private static class OnDeath
		{
			private static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					GameEvents.Instance?.RaiseLocalPlayerDied();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "Message")]
		private static class Message
		{
			private static bool Prefix(string msg)
			{
				bool suppress = false;
				GameEvents.Instance?.RaiseMessageShowing(msg, ref suppress);
				return !suppress;
			}
		}
	}
}
namespace YouDied.Infrastructure
{
	public delegate void BlackScreenUpdatingHandler(Player player, ref bool skip);
	public sealed class DeathScreen : MonoBehaviour
	{
		private const string FontFile = "EBGaramond.ttf";

		private const string SoundFile = "youdied.wav";

		private const int SortingOrder = 1000;

		private const float ReferenceWidth = 1920f;

		private const float ReferenceHeight = 1080f;

		private const float BandHeight = 300f;

		private const float BandOpacity = 0.85f;

		private const float BandFeather = 0.4f;

		private const int BandTextureHeight = 128;

		private const float FontSize = 130f;

		private const float CharacterSpacing = 12f;

		private const int FontSamplingSize = 90;

		private const int FontAtlasPadding = 9;

		private const int FontAtlasSize = 1024;

		private static readonly Color TitleColor = new Color(0.6f, 0.07f, 0.07f);

		private string _assetsDirectory;

		private AudioClip _sound;

		private AudioSource _source;

		private GameObject _root;

		private RawImage _band;

		private RectTransform _titleRect;

		private TextMeshProUGUI _title;

		private float _elapsed;

		public void Initialize(string assetsDirectory)
		{
			_assetsDirectory = assetsDirectory;
			_source = ((Component)this).gameObject.AddComponent<AudioSource>();
			_source.playOnAwake = false;
			_source.spatialBlend = 0f;
			((Behaviour)this).enabled = false;
			((MonoBehaviour)this).StartCoroutine(LoadSound());
		}

		public void Play(string title, float volume)
		{
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
			((TMP_Text)_title).text = title;
			_elapsed = 0f;
			_source.outputAudioMixerGroup = (Object.op_Implicit((Object)(object)AudioMan.instance) ? AudioMan.instance.m_guiMixer : null);
			_source.clip = _sound;
			_source.volume = volume;
			_source.PlayDelayed(0.5f);
			Apply();
			_root.SetActive(true);
			((Behaviour)this).enabled = true;
		}

		private void Update()
		{
			_elapsed += Time.unscaledDeltaTime;
			if (_elapsed >= 5.2f)
			{
				_root.SetActive(false);
				((Behaviour)this).enabled = false;
			}
			else
			{
				Apply();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}

		private IEnumerator LoadSound()
		{
			string absoluteUri = new Uri(Path.Combine(_assetsDirectory, "youdied.wav")).AbsoluteUri;
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, (AudioType)20);
			try
			{
				yield return request.SendWebRequest();
				_sound = DownloadHandlerAudioClip.GetContent(request);
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		private void Apply()
		{
			//IL_0022: 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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			float num = DeathTimeline.Visibility(_elapsed);
			((Graphic)_band).color = new Color(1f, 1f, 1f, num);
			((Graphic)_title).color = new Color(TitleColor.r, TitleColor.g, TitleColor.b, num);
			((Transform)_titleRect).localScale = Vector3.one * DeathTimeline.TitleScale(_elapsed);
		}

		private void Build()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			_root = new GameObject("YouDiedScreen");
			Object.DontDestroyOnLoad((Object)(object)_root);
			Canvas obj = _root.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 1000;
			CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 1f;
			GameObject val = CreateBand("Band");
			_band = val.AddComponent<RawImage>();
			_band.texture = (Texture)(object)CreateBandTexture();
			((Graphic)_band).raycastTarget = false;
			GameObject val2 = CreateBand("Title");
			_titleRect = val2.GetComponent<RectTransform>();
			_title = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)_title).fontSize = 130f;
			((TMP_Text)_title).characterSpacing = 12f;
			((TMP_Text)_title).alignment = (TextAlignmentOptions)514;
			((Graphic)_title).raycastTarget = false;
			TMP_FontAsset val3 = CreateFont();
			if ((Object)(object)val3 != (Object)null)
			{
				((TMP_Text)_title).font = val3;
			}
		}

		private GameObject CreateBand(string name)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(_root.transform, false);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.anchorMax = new Vector2(1f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(0f, 300f);
			component.anchoredPosition = Vector2.zero;
			return val;
		}

		private TMP_FontAsset CreateFont()
		{
			TMP_FontAsset val = TMP_FontAsset.CreateFontAsset(Path.Combine(_assetsDirectory, "EBGaramond.ttf"), 0, 90, 9, (GlyphRenderMode)4165, 1024, 1024);
			TMP_FontAsset font = MessageHud.instance.m_messageCenterText.font;
			if ((Object)(object)val != (Object)null && (Object)(object)font != (Object)null)
			{
				val.fallbackFontAssetTable = new List<TMP_FontAsset> { font };
			}
			return val;
		}

		private static Texture2D CreateBandTexture()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(1, 128, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			for (int i = 0; i < 128; i++)
			{
				float num = (float)i / 127f;
				float num2 = Mathf.Min(num, 1f - num);
				float num3 = Mathf.SmoothStep(0f, 1f, num2 / 0.4f) * 0.85f;
				val.SetPixel(0, i, new Color(0f, 0f, 0f, num3));
			}
			val.Apply();
			return val;
		}
	}
	internal static class DeathTimeline
	{
		public const float RespawnDelaySeconds = 5.2f;

		public const float TitleStartSeconds = 0.5f;

		public const float BlackFadeStartSeconds = 3.95f;

		public const float BlackFadeSeconds = 1f;

		private const float FadeInSeconds = 0.7f;

		private const float HoldEndSeconds = 2.85f;

		private const float FadeOutSeconds = 0.7f;

		private const float StartScale = 0.94f;

		private const float EndScale = 1.06f;

		public static float Visibility(float time)
		{
			float num = Mathf.SmoothStep(0f, 1f, (time - 0.5f) / 0.7f);
			float num2 = Mathf.SmoothStep(0f, 1f, (time - 2.85f) / 0.7f);
			return num * (1f - num2);
		}

		public static float TitleScale(float time)
		{
			float num = 3.05f;
			float num2 = (time - 0.5f) / num;
			return Mathf.Lerp(0.94f, 1.06f, num2);
		}
	}
	public sealed class GameEvents : IGameEvents
	{
		internal static GameEvents Instance { get; set; }

		public event Action LocalPlayerDied;

		public event RespawnRequestedHandler RespawnRequested;

		public event BlackScreenUpdatingHandler BlackScreenUpdating;

		public event MessageShowingHandler MessageShowing;

		internal void RaiseLocalPlayerDied()
		{
			this.LocalPlayerDied?.Invoke();
		}

		internal void RaiseRespawnRequested(ref float delay, bool afterDeath)
		{
			this.RespawnRequested?.Invoke(ref delay, afterDeath);
		}

		internal void RaiseBlackScreenUpdating(Player player, ref bool skip)
		{
			this.BlackScreenUpdating?.Invoke(player, ref skip);
		}

		internal void RaiseMessageShowing(string message, ref bool suppress)
		{
			this.MessageShowing?.Invoke(message, ref suppress);
		}
	}
	public interface IGameEvents
	{
		event Action LocalPlayerDied;

		event RespawnRequestedHandler RespawnRequested;

		event BlackScreenUpdatingHandler BlackScreenUpdating;

		event MessageShowingHandler MessageShowing;
	}
	public delegate void MessageShowingHandler(string message, ref bool suppress);
	public delegate void RespawnRequestedHandler(ref float delay, bool afterDeath);
}
namespace YouDied.Features
{
	public sealed class DeathScreenFeature : IFeature
	{
		private const string DeathMessage = "$msg_youdied";

		private static readonly char[] Exclamations = new char[4] { '!', '!', '¡', ' ' };

		private readonly IGameEvents _events;

		private readonly IModSettings _settings;

		private readonly DeathScreen _screen;

		public DeathScreenFeature(IGameEvents events, IModSettings settings, DeathScreen screen)
		{
			_events = events;
			_settings = settings;
			_screen = screen;
		}

		public void Enable()
		{
			_events.LocalPlayerDied += OnLocalPlayerDied;
			_events.MessageShowing += OnMessageShowing;
		}

		public void Disable()
		{
			_events.LocalPlayerDied -= OnLocalPlayerDied;
			_events.MessageShowing -= OnMessageShowing;
		}

		private void OnLocalPlayerDied()
		{
			string title = Localization.instance.Localize("$msg_youdied").Trim(Exclamations).ToUpperInvariant();
			_screen.Play(title, _settings.Volume);
		}

		private void OnMessageShowing(string message, ref bool suppress)
		{
			if (message == "$msg_youdied")
			{
				suppress = true;
			}
		}
	}
	public sealed class DeathTimingFeature : IFeature
	{
		private readonly IGameEvents _events;

		private float _diedAt = float.NegativeInfinity;

		public DeathTimingFeature(IGameEvents events)
		{
			_events = events;
		}

		public void Enable()
		{
			_events.RespawnRequested += OnRespawnRequested;
			_events.LocalPlayerDied += OnLocalPlayerDied;
			_events.BlackScreenUpdating += OnBlackScreenUpdating;
		}

		public void Disable()
		{
			_events.RespawnRequested -= OnRespawnRequested;
			_events.LocalPlayerDied -= OnLocalPlayerDied;
			_events.BlackScreenUpdating -= OnBlackScreenUpdating;
		}

		private void OnRespawnRequested(ref float delay, bool afterDeath)
		{
			if (afterDeath)
			{
				delay = 5.2f;
				Game.instance.m_fadeTimeDeath = 1f;
			}
		}

		private void OnLocalPlayerDied()
		{
			_diedAt = Time.unscaledTime;
		}

		private void OnBlackScreenUpdating(Player player, ref bool skip)
		{
			skip = IsBeforeBlackFade(player);
		}

		private bool IsBeforeBlackFade(Player player)
		{
			if ((Object)(object)player != (Object)null && ((Character)player).IsDead())
			{
				return Time.unscaledTime - _diedAt < 3.95f;
			}
			return false;
		}
	}
	public interface IFeature
	{
		void Enable();

		void Disable();
	}
}
namespace YouDied.Config
{
	public interface IModSettings
	{
		float Volume { get; }
	}
	public sealed class ModSettings : IModSettings
	{
		private readonly ConfigEntry<float> _volume;

		public float Volume => _volume.Value;

		public ModSettings(ConfigFile file)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			_volume = file.Bind<float>("Sound", "Volume", 0.7f, new ConfigDescription("Volume of the death sound, from 0 (silent) to 1 (full).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}