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