PTV.dll

Decompiled 7 hours ago
using System;
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 BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using PTV.NetcodePatcher;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("PTV")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PTV")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b31351bc-9f05-4a83-ab84-20ca395fc6df")]
[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")]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace PTV
{
	[BepInPlugin("Gavinboy3000.PTV", "PTV", "1.0.0")]
	public class PTV : BaseUnityPlugin
	{
		public const string modGUID = "Gavinboy3000.PTV";

		public const string modName = "PTV";

		public const string modVersion = "1.0.0";

		public static ConfigEntry<bool> configBeginWithIntro;

		public static ConfigEntry<bool> configTVInShop;

		private readonly Harmony harmony = new Harmony("Gavinboy3000.PTV");

		public static ManualLogSource logger = new ManualLogSource("Gavinboy3000.PTV");

		public static GameObject networkPrefab;

		private void Awake()
		{
			configBeginWithIntro = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "Begin With Intro", true, "Puts main intro at the beginning of every shuffle.");
			configTVInShop = ((BaseUnityPlugin)this).Config.Bind<bool>("QOL", "TV in Shop", true, "Makes it so the television is always in the shop.");
			NetcodePatcher();
			logger = ((BaseUnityPlugin)this).Logger;
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "asset");
			AssetBundle val = AssetBundle.LoadFromFile(text);
			networkPrefab = val.LoadAsset<GameObject>("Assets/NetworkHandler.prefab");
			networkPrefab.AddComponent<NetworkHandler>();
			VideoManager.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
			harmony.PatchAll();
			logger.LogInfo((object)"PTV version 1.0.0 has loaded!");
		}

		private static void NetcodePatcher()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(TVScript))]
	internal static class TVScriptPatch
	{
		private static MethodInfo setMatMethod = typeof(TVScript).GetMethod("SetTVScreenMaterial", BindingFlags.Instance | BindingFlags.NonPublic);

		private static MethodInfo onEnableMethod = typeof(TVScript).GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.NonPublic);

		private static TVScript tv;

		private static RenderTexture renderTexture;

		private static VideoPlayer currentVP;

		private static VideoPlayer nextVP;

		private static int currentIndex = -1;

		private static int nextIndex = 0;

		private static double forceTime = -1.0;

		[HarmonyPrefix]
		[HarmonyPatch("Update")]
		public static bool Update(TVScript __instance)
		{
			tv = __instance;
			if ((Object)(object)currentVP != (Object)null)
			{
				return false;
			}
			currentVP = ((Component)tv).GetComponent<VideoPlayer>();
			renderTexture = currentVP.targetTexture;
			if (VideoManager.Videos.Count < 1)
			{
				return false;
			}
			if (!NetworkHandler.Hosting())
			{
				return false;
			}
			TurnTVOnOff(tv, on: false);
			VideoManager.ShuffledVideos = new List<string>(VideoManager.Videos);
			VideoManager.Shuffle();
			currentIndex = -1;
			nextIndex = 0;
			PrepareNextVideo(tv);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("TurnTVOnOff")]
		public static bool TurnTVOnOff(TVScript __instance, bool on)
		{
			tv = __instance;
			if (VideoManager.Videos.Count < 1)
			{
				return false;
			}
			tv.tvOn = on;
			if (on)
			{
				PlayNextVideo();
				tv.tvSFX.PlayOneShot(tv.switchTVOn);
				WalkieTalkie.TransmitOneShotAudio(tv.tvSFX, tv.switchTVOn, 1f);
			}
			else
			{
				tv.video.Stop();
				tv.tvSFX.PlayOneShot(tv.switchTVOff);
				WalkieTalkie.TransmitOneShotAudio(tv.tvSFX, tv.switchTVOff, 1f);
			}
			setMatMethod.Invoke(tv, new object[1] { on });
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("TVFinishedClip")]
		public static bool TVFinishedClip(TVScript __instance, VideoPlayer source)
		{
			tv = __instance;
			PlayNextVideo();
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Terminal), "RotateShipDecorSelection")]
		public static void AddTV(Terminal __instance)
		{
			if (!PTV.configTVInShop.Value)
			{
				return;
			}
			int num = -1;
			for (int i = 0; i < StartOfRound.Instance.unlockablesList.unlockables.Count; i++)
			{
				if (StartOfRound.Instance.unlockablesList.unlockables[i].unlockableName == "Television")
				{
					num = i;
					break;
				}
			}
			if (num != -1)
			{
				TerminalNode shopSelectionNode = StartOfRound.Instance.unlockablesList.unlockables[num].shopSelectionNode;
				if (!__instance.ShipDecorSelection.Contains(shopSelectionNode))
				{
					__instance.ShipDecorSelection.Add(shopSelectionNode);
				}
			}
		}

		private static void PrepareNextVideo(TVScript tv)
		{
			if ((Object)(object)nextVP != (Object)null && ((Component)nextVP).gameObject.activeInHierarchy)
			{
				Object.Destroy((Object)(object)nextVP);
			}
			nextVP = ((Component)tv).gameObject.AddComponent<VideoPlayer>();
			nextVP.playOnAwake = false;
			nextVP.source = (VideoSource)1;
			nextVP.controlledAudioTrackCount = 1;
			nextVP.audioOutputMode = (VideoAudioOutputMode)1;
			nextVP.SetTargetAudioSource((ushort)0, tv.tvSFX);
			nextVP.skipOnDrop = true;
			if (NetworkHandler.Hosting())
			{
				nextVP.url = "file://" + VideoManager.ShuffledVideos[nextIndex];
			}
			else
			{
				nextVP.url = "file://" + VideoManager.Videos[nextIndex];
			}
			nextVP.Prepare();
		}

		private static void PlayNextVideo(int index = -1)
		{
			if (!((Object)(object)nextVP == (Object)null))
			{
				VideoPlayer val = currentVP;
				tv.video = (currentVP = nextVP);
				nextVP = null;
				Object.Destroy((Object)(object)val);
				onEnableMethod.Invoke(tv, new object[0]);
				currentIndex = nextIndex;
				if (NetworkHandler.Hosting())
				{
					nextIndex = VideoManager.NextIndex(currentIndex);
				}
				else if (index != -1)
				{
					nextIndex = index;
				}
				if (NetworkHandler.Hosting())
				{
					UpdateInfo();
				}
				tv.video.targetTexture = renderTexture;
				tv.video.Play();
				PrepareNextVideo(tv);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(NetworkManager), "SetSingleton")]
		public static void Init()
		{
			NetworkManager.Singleton.OnClientConnectedCallback += ClientConnected;
		}

		private static void ClientConnected(ulong id)
		{
			if (NetworkHandler.Hosting() && id != 0)
			{
				if (tv.tvOn)
				{
					UpdateInfo(1);
				}
				else
				{
					UpdateInfo(0);
				}
			}
		}

		private static void ForceTime(VideoPlayer source)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (forceTime != -1.0)
			{
				source.time = forceTime;
				source.prepareCompleted -= new EventHandler(ForceTime);
				forceTime = -1.0;
			}
		}

		public static void RecievedInfo(int current, double time, int next, int tvOn)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			if (NetworkHandler.Hosting())
			{
				return;
			}
			switch (tvOn)
			{
			case 0:
				TurnTVOnOff(tv, on: false);
				break;
			case 1:
				nextIndex = current;
				PrepareNextVideo(tv);
				TurnTVOnOff(tv, on: true);
				break;
			}
			if (currentIndex != current)
			{
				if (tv.tvOn)
				{
					nextIndex = current;
					PrepareNextVideo(tv);
					PlayNextVideo(next);
				}
				else
				{
					currentIndex = current;
					nextIndex = next;
					PrepareNextVideo(tv);
				}
			}
			else if (nextIndex != next)
			{
				nextIndex = next;
				PrepareNextVideo(tv);
			}
			double num = time - currentVP.time;
			if (Mathf.Abs((float)num) >= 1f)
			{
				forceTime = time;
				currentVP.prepareCompleted += new EventHandler(ForceTime);
			}
		}

		private static void UpdateInfo(int tvOn = -1)
		{
			NetworkHandler.instance.UpdateInfoClientRpc(VideoManager.GetTrueIndex(currentIndex), currentVP.time, VideoManager.GetTrueIndex(nextIndex), tvOn);
		}
	}
	internal static class VideoManager
	{
		public static List<string> Videos = new List<string>();

		public static List<string> ShuffledVideos;

		public static void Load(string basePath)
		{
			string text = Path.Combine(basePath, "Videos");
			if (!Directory.Exists(basePath))
			{
				return;
			}
			string[] files;
			if (!Directory.Exists(text))
			{
				files = Directory.GetFiles(basePath, "*.mp4");
				if (files.Length < 1)
				{
					return;
				}
				Directory.CreateDirectory(text);
				for (int i = 0; i < files.Length; i++)
				{
					string destFileName = Path.Combine(text, Path.GetFileName(files[i]));
					File.Move(files[i], destFileName);
				}
			}
			files = Directory.GetFiles(text, "*.mp4");
			Videos.AddRange(files);
			PTV.logger.LogInfo((object)$"Successfully loaded {Videos.Count} videos!");
		}

		public static void Shuffle()
		{
			int num = ShuffledVideos.Count;
			while (num > 1)
			{
				num--;
				int index = Random.Range(0, num + 1);
				string value = ShuffledVideos[index];
				ShuffledVideos[index] = ShuffledVideos[num];
				ShuffledVideos[num] = value;
			}
			if (PTV.configBeginWithIntro.Value)
			{
				string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Videos", "MainIntro.mp4");
				int num2 = ShuffledVideos.IndexOf(text);
				if (num2 != -1)
				{
					string value2 = ShuffledVideos[0];
					ShuffledVideos[0] = text;
					ShuffledVideos[num2] = value2;
				}
			}
		}

		public static int GetTrueIndex(int index)
		{
			if (index < 0)
			{
				index = 0;
			}
			int num = Videos.IndexOf(ShuffledVideos[index]);
			if (num == -1)
			{
				return index;
			}
			return num;
		}

		public static int NextIndex(int index)
		{
			if (index + 1 >= Videos.Count)
			{
				Shuffle();
			}
			return (index + 1) % Videos.Count;
		}
	}
	[HarmonyPatch]
	public class NetworkObjectManager
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		private static void Init(GameNetworkManager __instance)
		{
			((Component)__instance).GetComponent<NetworkManager>().AddNetworkPrefab(PTV.networkPrefab);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		private static void SpawnNetworkHandler()
		{
			if (NetworkHandler.Hosting())
			{
				GameObject val = Object.Instantiate<GameObject>(PTV.networkPrefab);
				val.GetComponent<NetworkObject>().Spawn(false);
			}
		}
	}
	public class NetworkHandler : NetworkBehaviour
	{
		public static NetworkHandler instance;

		public static bool Hosting()
		{
			return NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer;
		}

		public override void OnNetworkSpawn()
		{
			instance = this;
			((NetworkBehaviour)this).OnNetworkSpawn();
		}

		[ClientRpc]
		public void UpdateInfoClientRpc(int current, double time, int next, int tvOn)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2660303476u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, current);
					((FastBufferWriter)(ref val2)).WriteValueSafe<double>(ref time, default(ForPrimitives));
					BytePacker.WriteValueBitPacked(val2, next);
					BytePacker.WriteValueBitPacked(val2, tvOn);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2660303476u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					TVScriptPatch.RecievedInfo(current, time, next, tvOn);
				}
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_NetworkHandler()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(2660303476u, new RpcReceiveHandler(__rpc_handler_2660303476));
		}

		private static void __rpc_handler_2660303476(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int current = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref current);
				double time = default(double);
				((FastBufferReader)(ref reader)).ReadValueSafe<double>(ref time, default(ForPrimitives));
				int next = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref next);
				int tvOn = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref tvOn);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((NetworkHandler)(object)target).UpdateInfoClientRpc(current, time, next, tvOn);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "NetworkHandler";
		}
	}
}
namespace PTV.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}