Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LPC TV Clips v1.0.1
plugins/TV_Loader.dll
Decompiled a month agousing 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."); } } }