Decompiled source of LPC TV Clips v1.0.1

plugins/TV_Loader.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TV_Loader")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TV_Loader")]
[assembly: AssemblyTitle("TV_Loader")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace TV_Loader
{
	internal class NewSavePatches
	{
		[HarmonyPatch(typeof(StartOfRound))]
		internal class NewSave
		{
			[HarmonyPatch("firstDayAnimation")]
			[HarmonyPostfix]
			internal static void StartPatching()
			{
				StartOfRound instance = StartOfRound.Instance;
				if (!((NetworkBehaviour)instance).NetworkManager.IsHost)
				{
					return;
				}
				List<UnlockableItem> unlockables = instance.unlockablesList.unlockables;
				foreach (UnlockableItem item in unlockables)
				{
					if (item.unlockableName == "Television")
					{
						UnlockShipItem(instance, unlockables.IndexOf(item), item.unlockableName);
						break;
					}
				}
			}

			private static void UnlockShipItem(StartOfRound instance, int unlockableID, string name)
			{
				try
				{
					((object)instance).GetType().GetMethod("UnlockShipObject", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(instance, new object[1] { unlockableID });
				}
				catch (NullReferenceException)
				{
				}
			}
		}
	}
	[BepInPlugin("LPC.TV_Loader", "TV Loader", "1.0.0")]
	public class TVLoaderExtendedPlugin : BaseUnityPlugin
	{
		private const string GUID = "LPC.TV_Loader";

		private const string Name = "TV Loader";

		private const string Version = "1.0.0";

		private static readonly Harmony Harmony = new Harmony("LPC.TV_Loader");

		public static ManualLogSource Log = new ManualLogSource("TV Loader");

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony.PatchAll();
			VideoManager.Load();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} is loaded ! Video Count: {1}", "TV Loader", VideoManager.Videos.Count));
		}
	}
	internal class TVPatches
	{
		[HarmonyPatch(typeof(TVScript))]
		internal class TVScriptPatches
		{
			[Serializable]
			[CompilerGenerated]
			private sealed class <>c
			{
				public static readonly <>c <>9 = new <>c();

				public static EventHandler <>9__22_0;

				internal void <PrepareVideo>b__22_0(VideoPlayer source)
				{
					TVLoaderExtendedPlugin.Log.LogInfo((object)"Prepared video!");
				}
			}

			private static FieldInfo currentClipProperty = typeof(TVScript).GetField("currentClip", BindingFlags.Instance | BindingFlags.NonPublic);

			private static FieldInfo currentTimeProperty = typeof(TVScript).GetField("currentClipTime", BindingFlags.Instance | BindingFlags.NonPublic);

			private static FieldInfo wasTvOnLastFrameProp = typeof(TVScript).GetField("wasTvOnLastFrame", BindingFlags.Instance | BindingFlags.NonPublic);

			private static FieldInfo timeSinceTurningOffTVProp = typeof(TVScript).GetField("timeSinceTurningOffTV", BindingFlags.Instance | BindingFlags.NonPublic);

			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 bool s_EverWasOn = false;

			private static RenderTexture renderTexture;

			private static List<string> m_Videos = new List<string>();

			private static int s_LastSeed = 0;

			private static int s_LastSeenIndex = -1;

			private static string GetVideoPath(int Index)
			{
				return GetFullPath(m_Videos[Index]);
			}

			private static int GetSeed(TVScript Instance)
			{
				return ((NetworkBehaviour)Instance).NetworkObjectId.ToString().GetHashCode();
			}

			private static void Shuffle<T>(List<T> List, int Seed)
			{
				Random random = new Random(Seed);
				int count = List.Count;
				for (int i = 0; i < count - 1; i++)
				{
					int index = i + random.Next(count - i);
					T value = List[index];
					List[index] = List[i];
					List[i] = value;
				}
			}

			public static List<string> GetClearList(List<string> Pathes)
			{
				List<string> list = new List<string>();
				for (int i = 0; i < Pathes.Count; i++)
				{
					string item = Pathes[i].Split(new string[1] { "plugins" }, StringSplitOptions.None)[1];
					list.Add(item);
				}
				list.Sort();
				return list;
			}

			public static string GetFullPath(string ShortPath)
			{
				foreach (string video in VideoManager.Videos)
				{
					if (video.EndsWith(ShortPath))
					{
						return video;
					}
				}
				return "";
			}

			public static void ShuffleVideos(TVScript Instance)
			{
				m_Videos = GetClearList(VideoManager.Videos);
				TVLoaderExtendedPlugin.Log.LogInfo((object)("[TVScriptExtended] ShuffleVideos " + GetSeed(Instance)));
				Shuffle(m_Videos, GetSeed(Instance));
				for (int i = 0; i < m_Videos.Count; i++)
				{
					TVLoaderExtendedPlugin.Log.LogInfo((object)("[TVScriptExtended] m_Videos[" + i + "] " + m_Videos[i]));
				}
			}

			public static void ClientUpdate(TVScript Instance)
			{
				int num = (int)currentClipProperty.GetValue(Instance);
				if (s_LastSeenIndex != num)
				{
					s_LastSeenIndex = num;
					TVLoaderExtendedPlugin.Log.LogInfo((object)("[ClientUpdate] currentClip " + num + " Instance.tvOn " + Instance.tvOn));
					if (Instance.tvOn)
					{
						PlayVideo(Instance);
					}
				}
			}

			public static bool PlayerIsHost(TVScript __instance)
			{
				return Object.op_Implicit((Object)(object)__instance) && ((NetworkBehaviour)__instance).NetworkManager.IsHost;
			}

			[HarmonyPrefix]
			[HarmonyPatch("Update")]
			public static bool Update(TVScript __instance)
			{
				if ((Object)(object)renderTexture == (Object)null)
				{
					renderTexture = ((Component)__instance).GetComponent<VideoPlayer>().targetTexture;
				}
				if (!PlayerIsHost(__instance))
				{
					ClientUpdate(__instance);
				}
				if (s_LastSeed != GetSeed(__instance))
				{
					s_LastSeed = GetSeed(__instance);
					ShuffleVideos(__instance);
					if (PlayerIsHost(__instance))
					{
						currentClipProperty.SetValue(__instance, 0);
					}
					else
					{
						currentClipProperty.SetValue(__instance, -1);
					}
					s_EverWasOn = false;
				}
				return false;
			}

			[HarmonyPrefix]
			[HarmonyPatch("TurnTVOnOff")]
			public static bool TurnTVOnOff(TVScript __instance, bool on)
			{
				TVLoaderExtendedPlugin.Log.LogInfo((object)$"TVOnOff: {on}");
				if (VideoManager.Videos.Count == 0)
				{
					return false;
				}
				int num = (int)currentClipProperty.GetValue(__instance);
				__instance.tvOn = on;
				if (PlayerIsHost(__instance))
				{
					if (on)
					{
						if (!s_EverWasOn)
						{
							s_EverWasOn = true;
						}
						else
						{
							int num2 = (num + 1) % VideoManager.Videos.Count;
							currentClipProperty.SetValue(__instance, num2);
						}
						PlayVideo(__instance);
					}
				}
				else if (on)
				{
					currentTimeProperty.SetValue(__instance, 0f);
				}
				if (on)
				{
					__instance.tvSFX.PlayOneShot(__instance.switchTVOn);
					WalkieTalkie.TransmitOneShotAudio(__instance.tvSFX, __instance.switchTVOn, 1f);
				}
				else
				{
					__instance.video.Stop();
					__instance.tvSFX.PlayOneShot(__instance.switchTVOff);
					WalkieTalkie.TransmitOneShotAudio(__instance.tvSFX, __instance.switchTVOff, 1f);
				}
				setMatMethod.Invoke(__instance, new object[1] { on });
				return false;
			}

			[HarmonyPrefix]
			[HarmonyPatch("TVFinishedClip")]
			public static bool TVFinishedClip(TVScript __instance, VideoPlayer source)
			{
				if (__instance.tvOn && PlayerIsHost(__instance))
				{
					TVLoaderExtendedPlugin.Log.LogInfo((object)"TVFinishedClip");
					int num = (int)currentClipProperty.GetValue(__instance);
					if (VideoManager.Videos.Count > 0)
					{
						num = (num + 1) % VideoManager.Videos.Count;
					}
					currentTimeProperty.SetValue(__instance, 0f);
					currentClipProperty.SetValue(__instance, num);
					PlayVideo(__instance);
				}
				return false;
			}

			private static void PrepareVideo(TVScript instance, int index)
			{
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Expected O, but got Unknown
				if (index < 0)
				{
					return;
				}
				string videoPath = GetVideoPath(index);
				Object.Destroy((Object)(object)instance.video);
				VideoPlayer val = ((Component)instance).gameObject.AddComponent<VideoPlayer>();
				val.playOnAwake = false;
				val.isLooping = false;
				val.source = (VideoSource)1;
				val.controlledAudioTrackCount = 1;
				val.audioOutputMode = (VideoAudioOutputMode)1;
				val.SetTargetAudioSource((ushort)0, instance.tvSFX);
				TVLoaderExtendedPlugin.Log.LogInfo((object)("Going to prepare: " + videoPath));
				val.url = "file://" + videoPath;
				val.skipOnDrop = true;
				val.Prepare();
				object obj = <>c.<>9__22_0;
				if (obj == null)
				{
					EventHandler val2 = delegate
					{
						TVLoaderExtendedPlugin.Log.LogInfo((object)"Prepared video!");
					};
					<>c.<>9__22_0 = val2;
					obj = (object)val2;
				}
				val.prepareCompleted += (EventHandler)obj;
				instance.video = val;
			}

			private static void PlayVideo(TVScript instance)
			{
				if (VideoManager.Videos.Count != 0)
				{
					currentTimeProperty.SetValue(instance, 0f);
					PrepareVideo(instance, (int)currentClipProperty.GetValue(instance));
					onEnableMethod.Invoke(instance, new object[0]);
					TVLoaderExtendedPlugin.Log.LogInfo((object)("TV Current Video Index " + (int)currentClipProperty.GetValue(instance)));
					instance.video.targetTexture = renderTexture;
					instance.video.Play();
					if (PlayerIsHost(instance))
					{
						instance.SyncTVServerRpc();
					}
				}
			}
		}
	}
	internal static class VideoManager
	{
		public static List<string> Videos = new List<string>();

		public static void Load()
		{
			Videos.Clear();
			string[] directories = Directory.GetDirectories(Paths.PluginPath);
			foreach (string text in directories)
			{
				string path = Path.Combine(Paths.PluginPath, text, "Television Videos");
				if (Directory.Exists(path))
				{
					string[] files = Directory.GetFiles(path, "*.mp4");
					Videos.AddRange(files);
					TVLoaderExtendedPlugin.Log.LogInfo((object)$"{text} has {files.Length} videos.");
				}
			}
			string path2 = Path.Combine(Paths.PluginPath, "Television Videos");
			if (!Directory.Exists(path2))
			{
				Directory.CreateDirectory(path2);
			}
			string[] files2 = Directory.GetFiles(path2, "*.mp4");
			Videos.AddRange(files2);
			TVLoaderExtendedPlugin.Log.LogInfo((object)$"Global has {files2.Length} videos.");
			TVLoaderExtendedPlugin.Log.LogInfo((object)$"Loaded {Videos.Count} total.");
		}
	}
}