Decompiled source of RewindThat v1.0.0

RewindThat.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 System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("RewindThat")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RewindThat")]
[assembly: AssemblyTitle("RewindThat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 RewindThat
{
	[BepInPlugin("com.zylow.rewindthat", "REWIND THAT", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public struct FrameSnapshot
		{
			public Vector3 position;

			public Quaternion rotation;

			public int health;

			public FrameSnapshot(Vector3 pos, Quaternion rot, int hp)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: 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)
				position = pos;
				rotation = rot;
				health = hp;
			}
		}

		private static Harmony harmony;

		internal static ManualLogSource Log;

		public static List<FrameSnapshot> history = new List<FrameSnapshot>();

		public const int maxFrames = 1200;

		public const int rewindSpeed = 3;

		public const KeyCode rewindKey = (KeyCode)99;

		public static bool isRewinding = false;

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"[REWIND THAT] Initialisiere Mod...");
			GameObject val = new GameObject("RewindThat_FX");
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			val.AddComponent<RewindFx>();
			harmony = new Harmony("com.zylow.rewindthat");
			harmony.PatchAll();
		}
	}
	public class RewindFx : MonoBehaviour
	{
		private static readonly Color overlayColor = Color.white;

		private const float soundVolume = 1f;

		private Material overlayMat;

		private AudioSource audioSource;

		private int soundStartSample;

		private bool effectsActive;

		private void Awake()
		{
			SetupOverlayMaterial();
			SetupAudio();
			((MonoBehaviour)this).StartCoroutine(DrawOverlayAtEndOfFrame());
		}

		private void LateUpdate()
		{
			bool flag = Plugin.isRewinding && Input.GetKey((KeyCode)99);
			if ((Object)(object)audioSource != (Object)null && (Object)(object)audioSource.clip != (Object)null)
			{
				if (!audioSource.isPlaying)
				{
					audioSource.Play();
				}
				if (flag && !effectsActive)
				{
					audioSource.timeSamples = soundStartSample;
					audioSource.volume = 1f;
				}
				else if (!flag && effectsActive)
				{
					audioSource.volume = 0f;
				}
			}
			effectsActive = flag;
		}

		private void SetupOverlayMaterial()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Shader val = Shader.Find("Hidden/Internal-Colored");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"[REWIND THAT] Shader 'Hidden/Internal-Colored' nicht gefunden – kein Overlay.");
				return;
			}
			overlayMat = new Material(val)
			{
				hideFlags = (HideFlags)61
			};
			overlayMat.SetInt("_SrcBlend", 4);
			overlayMat.SetInt("_DstBlend", 0);
			overlayMat.SetInt("_Cull", 0);
			overlayMat.SetInt("_ZWrite", 0);
			overlayMat.SetInt("_ZTest", 8);
		}

		private IEnumerator DrawOverlayAtEndOfFrame()
		{
			WaitForEndOfFrame endOfFrame = new WaitForEndOfFrame();
			while (true)
			{
				yield return endOfFrame;
				if (effectsActive && !((Object)(object)overlayMat == (Object)null))
				{
					RenderTexture previous = RenderTexture.active;
					RenderTexture.active = null;
					bool previousSrgbWrite = GL.sRGBWrite;
					GL.sRGBWrite = false;
					GL.PushMatrix();
					GL.LoadOrtho();
					overlayMat.SetPass(0);
					GL.Begin(7);
					GL.Color(overlayColor);
					GL.Vertex3(0f, 0f, 0f);
					GL.Vertex3(0f, 1f, 0f);
					GL.Vertex3(1f, 1f, 0f);
					GL.Vertex3(1f, 0f, 0f);
					GL.End();
					GL.PopMatrix();
					GL.sRGBWrite = previousSrgbWrite;
					RenderTexture.active = previous;
				}
			}
		}

		private void SetupAudio()
		{
			audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			audioSource.playOnAwake = false;
			audioSource.loop = true;
			audioSource.spatialBlend = 0f;
			audioSource.priority = 0;
			audioSource.bypassReverbZones = true;
			audioSource.dopplerLevel = 0f;
			audioSource.volume = 0f;
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = Path.Combine(directoryName, "mandom.wav");
			if (!File.Exists(text))
			{
				Plugin.Log.LogError((object)("[REWIND THAT] Sound nicht gefunden: " + text));
				return;
			}
			string error;
			AudioClip val = WavLoader.Load(text, out soundStartSample, out error);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("[REWIND THAT] WAV konnte nicht geladen werden: " + error));
				return;
			}
			audioSource.clip = val;
			audioSource.Play();
			Plugin.Log.LogInfo((object)$"[REWIND THAT] Sound geladen: {val.length:0.00}s, {val.frequency} Hz, {val.channels} Kanäle, Stille am Anfang übersprungen: {(float)soundStartSample / (float)val.frequency:0.000}s");
		}
	}
	internal static class WavLoader
	{
		private const float silenceThreshold = 0.01f;

		public static AudioClip Load(string path, out int firstAudibleSample, out string error)
		{
			firstAudibleSample = 0;
			error = null;
			byte[] array = File.ReadAllBytes(path);
			if (array.Length < 12 || Encoding.ASCII.GetString(array, 0, 4) != "RIFF" || Encoding.ASCII.GetString(array, 8, 4) != "WAVE")
			{
				error = "Keine gültige WAV-Datei (RIFF/WAVE-Header fehlt). Ist es evtl. eine umbenannte MP3/OGG?";
				return null;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = -1;
			int num6 = 0;
			int num7 = 12;
			while (num7 + 8 <= array.Length)
			{
				string text = Encoding.ASCII.GetString(array, num7, 4);
				int num8 = BitConverter.ToInt32(array, num7 + 4);
				int num9 = num7 + 8;
				if (num8 < 0 || num9 + num8 > array.Length)
				{
					num8 = array.Length - num9;
				}
				if (text == "fmt ")
				{
					num = BitConverter.ToUInt16(array, num9);
					num2 = BitConverter.ToUInt16(array, num9 + 2);
					num3 = BitConverter.ToInt32(array, num9 + 4);
					num4 = BitConverter.ToUInt16(array, num9 + 14);
					if (num == 65534 && num8 >= 26)
					{
						num = BitConverter.ToUInt16(array, num9 + 24);
					}
				}
				else if (text == "data")
				{
					num5 = num9;
					num6 = num8;
				}
				num7 = num9 + num8 + (num8 & 1);
			}
			if (num5 < 0 || num2 <= 0 || num3 <= 0 || num4 <= 0)
			{
				error = "fmt- oder data-Chunk fehlt.";
				return null;
			}
			bool flag = num == 3 && num4 == 32;
			if (num != 1 && !flag)
			{
				error = "Nicht unterstütztes Format (Format-Tag " + num + ", " + num4 + " Bit). Bitte als PCM 16 Bit exportieren.";
				return null;
			}
			int num10 = num4 / 8;
			int num11 = num6 / num10 / num2;
			float[] array2 = new float[num11 * num2];
			for (int i = 0; i < array2.Length; i++)
			{
				int num12 = num5 + i * num10;
				if (flag)
				{
					array2[i] = BitConverter.ToSingle(array, num12);
					continue;
				}
				switch (num4)
				{
				case 8:
					array2[i] = (float)(array[num12] - 128) / 128f;
					break;
				case 16:
					array2[i] = (float)(short)(array[num12] | (array[num12 + 1] << 8)) / 32768f;
					break;
				case 24:
					array2[i] = (float)((array[num12] << 8) | (array[num12 + 1] << 16) | (array[num12 + 2] << 24)) / 2.1474836E+09f;
					break;
				case 32:
					array2[i] = (float)BitConverter.ToInt32(array, num12) / 2.1474836E+09f;
					break;
				}
			}
			for (int j = 0; j < array2.Length; j++)
			{
				if (Math.Abs(array2[j]) > 0.01f)
				{
					firstAudibleSample = j / num2;
					break;
				}
			}
			AudioClip val = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num11, num2, num3, false);
			val.SetData(array2, 0);
			return val;
		}
	}
	[HarmonyPatch(typeof(NewMovement), "Update")]
	public class NewMovementUpdatePatch
	{
		[HarmonyPostfix]
		public static void Postfix(NewMovement __instance)
		{
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKey((KeyCode)99))
			{
				Plugin.isRewinding = true;
				Rigidbody val = (((Object)(object)__instance.rb != (Object)null) ? __instance.rb : ((Component)__instance).GetComponent<Rigidbody>());
				if ((Object)(object)val != (Object)null)
				{
					val.velocity = Vector3.zero;
					val.angularVelocity = Vector3.zero;
				}
				if (Plugin.history.Count != 0)
				{
					int num = Mathf.Min(3, Plugin.history.Count);
					int index = Plugin.history.Count - num;
					Plugin.FrameSnapshot frameSnapshot = Plugin.history[index];
					((Component)__instance).transform.position = frameSnapshot.position;
					((Component)__instance).transform.rotation = frameSnapshot.rotation;
					__instance.hp = frameSnapshot.health;
					Plugin.history.RemoveRange(index, num);
					if ((Object)(object)MonoSingleton<HudMessageReceiver>.Instance != (Object)null && Time.frameCount % 10 == 0)
					{
						MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("<<< MANDOM: REWINDING 20s", "", "", 0, false, false, true);
					}
				}
			}
			else
			{
				Plugin.isRewinding = false;
				if (Plugin.history.Count >= 1200)
				{
					Plugin.history.RemoveAt(0);
				}
				Plugin.history.Add(new Plugin.FrameSnapshot(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, __instance.hp));
			}
		}
	}
}