Decompiled source of Replay Pot v1.0.0

ClassLibrary4.dll

Decompiled 4 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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ClassLibrary4")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ClassLibrary4")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("43afb890-208d-4528-aedf-46e3838ce5a8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.user.goi.ghostchaser", "Ghost Chaser Pro", "1.8.0")]
public class GhostChaser : BaseUnityPlugin
{
	[Serializable]
	public class FrameData
	{
		public List<PartData> parts = new List<PartData>();
	}

	[Serializable]
	public class PartData
	{
		public string name;

		public Vector3 wPos;

		public Quaternion wRot;

		public List<PartData> children = new List<PartData>();
	}

	[Serializable]
	private class RunWrapper
	{
		public List<FrameData> frames;
	}

	[CompilerGenerated]
	private sealed class <InitiateSequence>d__26 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public bool recording;

		public GhostChaser <>4__this;

		private Joint2D[] <>s__1;

		private int <>s__2;

		private Joint2D <joint>5__3;

		private MonoBehaviour[] <>s__4;

		private int <>s__5;

		private MonoBehaviour <comp>5__6;

		private string <compName>5__7;

		private Animator[] <>s__8;

		private int <>s__9;

		private Animator <anim>5__10;

		private Rigidbody2D[] <>s__11;

		private int <>s__12;

		private Rigidbody2D <rb>5__13;

		private Transform[] <>s__14;

		private int <>s__15;

		private Transform <t>5__16;

		private string <parentName>5__17;

		private string <uniqueId>5__18;

		private Renderer[] <>s__19;

		private int <>s__20;

		private Renderer <rend>5__21;

		private Material[] <>s__22;

		private int <>s__23;

		private Material <mat>5__24;

		private Color <c>5__25;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <InitiateSequence>d__26(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>s__1 = null;
			<joint>5__3 = null;
			<>s__4 = null;
			<comp>5__6 = null;
			<compName>5__7 = null;
			<>s__8 = null;
			<anim>5__10 = null;
			<>s__11 = null;
			<rb>5__13 = null;
			<>s__14 = null;
			<t>5__16 = null;
			<parentName>5__17 = null;
			<uniqueId>5__18 = null;
			<>s__19 = null;
			<rend>5__21 = null;
			<>s__22 = null;
			<mat>5__24 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.startTimer = 6.5f;
				<>2__current = (object)new WaitForSeconds(6.5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if (recording)
				{
					<>4__this.currentRun.Clear();
					<>4__this.isRecording = true;
					<>4__this.isPlaying = false;
				}
				else
				{
					<>4__this.isPlaying = true;
					<>4__this.isRecording = false;
					<>4__this.playbackIndex = 0;
				}
				if ((Object)(object)<>4__this.player != (Object)null)
				{
					<>4__this.ghost = Object.Instantiate<GameObject>(<>4__this.player);
					((Object)<>4__this.ghost).name = "GhostVisualClone";
					<>4__this.ghostPartCache.Clear();
					<>s__1 = <>4__this.ghost.GetComponentsInChildren<Joint2D>(true);
					for (<>s__2 = 0; <>s__2 < <>s__1.Length; <>s__2++)
					{
						<joint>5__3 = <>s__1[<>s__2];
						Object.Destroy((Object)(object)<joint>5__3);
						<joint>5__3 = null;
					}
					<>s__1 = null;
					<>s__4 = <>4__this.ghost.GetComponentsInChildren<MonoBehaviour>(true);
					for (<>s__5 = 0; <>s__5 < <>s__4.Length; <>s__5++)
					{
						<comp>5__6 = <>s__4[<>s__5];
						if (!((Object)(object)<comp>5__6 == (Object)(object)<>4__this))
						{
							<compName>5__7 = ((object)<comp>5__6).GetType().Name;
							if (<compName>5__7.Contains("IK") || <compName>5__7.Contains("Control") || <compName>5__7.Contains("Animator") || <compName>5__7.Contains("PlayerControl") || <compName>5__7.Contains("Saviour") || <compName>5__7.Contains("PlayerSounds") || <compName>5__7.Contains("Sounds"))
							{
								Object.DestroyImmediate((Object)(object)<comp>5__6);
							}
							<compName>5__7 = null;
							<comp>5__6 = null;
						}
					}
					<>s__4 = null;
					<>s__8 = <>4__this.ghost.GetComponentsInChildren<Animator>(true);
					for (<>s__9 = 0; <>s__9 < <>s__8.Length; <>s__9++)
					{
						<anim>5__10 = <>s__8[<>s__9];
						Object.DestroyImmediate((Object)(object)<anim>5__10);
						<anim>5__10 = null;
					}
					<>s__8 = null;
					<>s__11 = <>4__this.ghost.GetComponentsInChildren<Rigidbody2D>();
					for (<>s__12 = 0; <>s__12 < <>s__11.Length; <>s__12++)
					{
						<rb>5__13 = <>s__11[<>s__12];
						<rb>5__13.isKinematic = true;
						<rb>5__13.simulated = false;
						<rb>5__13 = null;
					}
					<>s__11 = null;
					<>s__14 = <>4__this.ghost.GetComponentsInChildren<Transform>(true);
					for (<>s__15 = 0; <>s__15 < <>s__14.Length; <>s__15++)
					{
						<t>5__16 = <>s__14[<>s__15];
						<parentName>5__17 = (((Object)(object)<t>5__16.parent != (Object)null) ? ((Object)<t>5__16.parent).name : "");
						if (<parentName>5__17 == "GhostVisualClone" || <parentName>5__17 == "Player(Clone)")
						{
							<parentName>5__17 = "Player";
						}
						<uniqueId>5__18 = (((Object)(object)<t>5__16.parent != (Object)null) ? (<parentName>5__17 + "_" + ((Object)<t>5__16).name + "_" + <t>5__16.GetSiblingIndex()) : ((Object)<t>5__16).name);
						if ((Object)(object)<t>5__16 == (Object)(object)<>4__this.ghost.transform)
						{
							<uniqueId>5__18 = "Player";
						}
						if (!<>4__this.ghostPartCache.ContainsKey(<uniqueId>5__18))
						{
							<>4__this.ghostPartCache.Add(<uniqueId>5__18, <t>5__16);
						}
						<parentName>5__17 = null;
						<uniqueId>5__18 = null;
						<t>5__16 = null;
					}
					<>s__14 = null;
					<>s__19 = <>4__this.ghost.GetComponentsInChildren<Renderer>();
					for (<>s__20 = 0; <>s__20 < <>s__19.Length; <>s__20++)
					{
						<rend>5__21 = <>s__19[<>s__20];
						if (recording)
						{
							<rend>5__21.enabled = false;
						}
						else
						{
							<>s__22 = <rend>5__21.materials;
							for (<>s__23 = 0; <>s__23 < <>s__22.Length; <>s__23++)
							{
								<mat>5__24 = <>s__22[<>s__23];
								if (<mat>5__24.HasProperty("_Color"))
								{
									<c>5__25 = <mat>5__24.color;
									<c>5__25.a = 0.4f;
									<mat>5__24.color = <c>5__25;
								}
								<mat>5__24 = null;
							}
							<>s__22 = null;
						}
						<rend>5__21 = null;
					}
					<>s__19 = null;
				}
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <WaitAndShowMenu>d__23 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public GhostChaser <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <WaitAndShowMenu>d__23(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if ((Object)(object)<>4__this.player == (Object)null)
			{
				<>4__this.player = GameObject.Find("Player");
				<>2__current = null;
				<>1__state = 1;
				return true;
			}
			<>4__this.showMenu = true;
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private GameObject player;

	private GameObject ghost;

	private bool isRecording = false;

	private bool isPlaying = false;

	private bool showMenu = false;

	private float startTimer = -1f;

	private Dictionary<string, Transform> ghostPartCache = new Dictionary<string, Transform>();

	private bool showSaveSelection = false;

	private Vector2 scrollPosition = Vector2.zero;

	private string selectedFilePath = "";

	private string renameString = "";

	private List<FrameData> currentRun = new List<FrameData>();

	private int playbackIndex = 0;

	private string SavesFolder => Path.Combine(Application.persistentDataPath, "ghost_saves");

	private string DefaultSavePath => Path.Combine(SavesFolder, "ghost_run.json");

	private void Awake()
	{
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		Cleanup();
		((MonoBehaviour)this).StartCoroutine(WaitAndShowMenu());
	}

	private void Cleanup()
	{
		if ((Object)(object)ghost != (Object)null)
		{
			Object.Destroy((Object)(object)ghost);
		}
		ghostPartCache.Clear();
		isRecording = false;
		isPlaying = false;
		showSaveSelection = false;
		selectedFilePath = "";
		startTimer = -1f;
		Time.timeScale = 1f;
		if (!Directory.Exists(SavesFolder))
		{
			Directory.CreateDirectory(SavesFolder);
		}
	}

	[IteratorStateMachine(typeof(<WaitAndShowMenu>d__23))]
	private IEnumerator WaitAndShowMenu()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitAndShowMenu>d__23(0)
		{
			<>4__this = this
		};
	}

	private void Update()
	{
		if (showMenu)
		{
			Cursor.visible = true;
			Cursor.lockState = (CursorLockMode)0;
		}
		else
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			if (startTimer > 0f)
			{
				startTimer -= Time.deltaTime;
				return;
			}
			if (isRecording)
			{
				RecordFrame();
			}
			if (isPlaying && (Object)(object)ghost != (Object)null && currentRun.Count > 0)
			{
				ApplyFrame(playbackIndex);
				playbackIndex = (playbackIndex + 1) % currentRun.Count;
			}
		}
	}

	private void OnGUI()
	{
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_054a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_045a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		if (showMenu)
		{
			Time.timeScale = 0f;
			if (!showSaveSelection)
			{
				Rect val = default(Rect);
				((Rect)(ref val))..ctor((float)(Screen.width / 2 - 120), (float)(Screen.height / 2 - 80), 240f, 160f);
				GUI.Box(val, "GHOST MENU");
				if (GUI.Button(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 30f, 200f, 35f), "RECORD NEW RUN"))
				{
					Cursor.visible = false;
					Cursor.lockState = (CursorLockMode)1;
					showMenu = false;
					Time.timeScale = 1f;
					((MonoBehaviour)this).StartCoroutine(InitiateSequence(recording: true));
				}
				string[] files = Directory.GetFiles(SavesFolder, "*.json");
				if ((files.Length != 0 || File.Exists(DefaultSavePath)) && GUI.Button(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 75f, 200f, 35f), "PLAY LAST RUN"))
				{
					showSaveSelection = true;
				}
			}
			else
			{
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor((float)(Screen.width / 2 - 250), (float)(Screen.height / 2 - 180), 500f, 360f);
				GUI.Box(val2, "SELECT OR RENAME RUN TRACKS");
				string[] files2 = Directory.GetFiles(SavesFolder, "*.json");
				Rect val3 = default(Rect);
				((Rect)(ref val3))..ctor(((Rect)(ref val2)).x + 15f, ((Rect)(ref val2)).y + 30f, 470f, 200f);
				Rect val4 = default(Rect);
				((Rect)(ref val4))..ctor(0f, 0f, 450f, (float)Mathf.Max(200, files2.Length * 32));
				scrollPosition = GUI.BeginScrollView(val3, scrollPosition, val4);
				for (int i = 0; i < files2.Length; i++)
				{
					string text = files2[i];
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
					string text2 = ((selectedFilePath == text) ? ("> " + fileNameWithoutExtension + " <") : fileNameWithoutExtension);
					if (GUI.Button(new Rect(5f, (float)(i * 32), 440f, 28f), text2))
					{
						selectedFilePath = text;
						renameString = fileNameWithoutExtension;
					}
				}
				GUI.EndScrollView();
				if (!string.IsNullOrEmpty(selectedFilePath) && File.Exists(selectedFilePath))
				{
					GUI.Label(new Rect(((Rect)(ref val2)).x + 20f, ((Rect)(ref val2)).y + 245f, 100f, 25f), "Rename to:");
					renameString = GUI.TextField(new Rect(((Rect)(ref val2)).x + 110f, ((Rect)(ref val2)).y + 245f, 240f, 25f), renameString);
					if (GUI.Button(new Rect(((Rect)(ref val2)).x + 360f, ((Rect)(ref val2)).y + 245f, 120f, 25f), "Apply Name") && !string.IsNullOrEmpty(renameString.Trim()))
					{
						string text3 = Path.Combine(SavesFolder, renameString.Trim() + ".json");
						if (!File.Exists(text3))
						{
							File.Move(selectedFilePath, text3);
							selectedFilePath = text3;
						}
					}
					if (GUI.Button(new Rect(((Rect)(ref val2)).x + 20f, ((Rect)(ref val2)).y + 290f, 210f, 40f), "LOAD SELECTED RUN"))
					{
						Cursor.visible = false;
						Cursor.lockState = (CursorLockMode)1;
						LoadRunDirect(selectedFilePath);
						showSaveSelection = false;
						showMenu = false;
						Time.timeScale = 1f;
						((MonoBehaviour)this).StartCoroutine(InitiateSequence(recording: false));
					}
				}
				else
				{
					GUI.Label(new Rect(((Rect)(ref val2)).x + 20f, ((Rect)(ref val2)).y + 250f, 460f, 30f), "Select a file from the list above to proceed...", GUI.skin.box);
				}
				if (GUI.Button(new Rect(((Rect)(ref val2)).x + 260f, ((Rect)(ref val2)).y + 290f, 220f, 40f), "BACK TO MENU"))
				{
					showSaveSelection = false;
					selectedFilePath = "";
				}
			}
		}
		if (!showMenu)
		{
			if (startTimer > 0f)
			{
				GUI.Label(new Rect(20f, 20f, 200f, 30f), $"GHOST STARTING: {startTimer:F1}s");
			}
			if (isRecording && GUI.Button(new Rect((float)(Screen.width - 140), (float)(Screen.height - 45), 130f, 35f), "SAVE RUN"))
			{
				SaveRun();
			}
		}
	}

	[IteratorStateMachine(typeof(<InitiateSequence>d__26))]
	private IEnumerator InitiateSequence(bool recording)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <InitiateSequence>d__26(0)
		{
			<>4__this = this,
			recording = recording
		};
	}

	private void RecordFrame()
	{
		if (!((Object)(object)player == (Object)null))
		{
			FrameData frameData = new FrameData();
			frameData.parts.Add(RecordTransformRecursive(player.transform));
			currentRun.Add(frameData);
		}
	}

	private PartData RecordTransformRecursive(Transform current)
	{
		//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_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		PartData partData = new PartData
		{
			name = ((Object)current).name,
			wPos = current.position,
			wRot = current.rotation
		};
		foreach (Transform item in current)
		{
			Transform current2 = item;
			partData.children.Add(RecordTransformRecursive(current2));
		}
		return partData;
	}

	private void ApplyFrame(int index)
	{
		if (!((Object)(object)ghost == (Object)null) && index < currentRun.Count)
		{
			FrameData frameData = currentRun[index];
			if (frameData.parts.Count > 0)
			{
				ApplyTransformRecursive(ghost.transform, frameData.parts[0]);
			}
		}
	}

	private void ApplyTransformRecursive(Transform current, PartData data)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)current == (Object)null || data == null)
		{
			return;
		}
		current.position = data.wPos;
		current.rotation = data.wRot;
		for (int i = 0; i < data.children.Count; i++)
		{
			if (i < current.childCount)
			{
				ApplyTransformRecursive(current.GetChild(i), data.children[i]);
			}
		}
	}

	private void SaveRun()
	{
		if (currentRun.Count != 0)
		{
			string text = $"run_{DateTime.Now:yyyyMMdd_HHmmss}.json";
			string path = Path.Combine(SavesFolder, text);
			File.WriteAllText(path, JsonUtility.ToJson((object)new RunWrapper
			{
				frames = currentRun
			}));
			Debug.Log((object)("Ghost Run Saved to: " + text));
		}
	}

	private void LoadRunDirect(string fullPath)
	{
		if (File.Exists(fullPath))
		{
			RunWrapper runWrapper = JsonUtility.FromJson<RunWrapper>(File.ReadAllText(fullPath));
			if (runWrapper != null && runWrapper.frames != null)
			{
				currentRun = runWrapper.frames;
			}
		}
	}
}