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.Logging;
using HarmonyLib;
using TVLoaderExtended.Utils;
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("TVLoaderExtended")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TVLoaderExtended")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5F5ACB51-F9E6-4E85-B3A4-028FEE7B0650")]
[assembly: AssemblyFileVersion("1.1.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.3.0")]
namespace TVLoaderExtended
{
[BepInPlugin("Filigrani.TVLoaderExtended", "TVLoaderExtended", "1.1.3")]
public class TVLoaderExtendedPlugin : BaseUnityPlugin
{
private const string MyGUID = "Filigrani.TVLoaderExtended";
private const string PluginName = "TVLoaderExtended";
private const string VersionString = "1.1.3";
private static readonly Harmony Harmony = new Harmony("Filigrani.TVLoaderExtended");
public static ManualLogSource Log = new ManualLogSource("TVLoaderExtended");
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
Harmony.PatchAll();
VideoManager.Load();
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("PluginName: {0}, VersionString: {1} is loaded. Video Count: {2}", "TVLoaderExtended", "1.1.3", VideoManager.Videos.Count));
}
}
}
namespace TVLoaderExtended.Utils
{
internal static class VideoManager
{
public static List<string> Videos = new List<string>();
public static void Load()
{
Videos.Clear();
string[] directories = Directory.GetDirectories(Paths.PluginPath);
string[] array = directories;
foreach (string text in array)
{
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.");
}
}
}
namespace TVLoaderExtended.Patches
{
[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 text = Pathes[i];
string[] separator = new string[1] { "plugins" };
string[] array = text.Split(separator, StringSplitOptions.None);
string item = array[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)
{
if (Object.op_Implicit((Object)(object)__instance))
{
return ((NetworkBehaviour)__instance).NetworkManager.IsHost;
}
return false;
}
[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
{
num = (num + 1) % VideoManager.Videos.Count;
currentClipProperty.SetValue(__instance, num);
}
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_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: 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();
}
}
}
}
}