using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using CustomTvVideos.Patches;
using GameNetcodeStuff;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Video;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomTvVideos")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Allowes you to set custom videos for the tv")]
[assembly: AssemblyFileVersion("0.1.3.0")]
[assembly: AssemblyInformationalVersion("0.1.3")]
[assembly: AssemblyProduct("CustomTvVideos")]
[assembly: AssemblyTitle("CustomTvVideos")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace CustomTvVideos
{
internal interface ITryGet<T>
{
bool TryGetValue(out T? value);
}
public class MyPluginInfo
{
public const string PLUGIN_GUID = "sakura.custom-tv-videos";
public const string PLUGIN_NAME = "CustomTvVideos";
public const string PLUGIN_VERSION = "0.1.3";
}
[BepInPlugin("sakura.custom-tv-videos", "CustomTvVideos", "0.1.3")]
public class CustomTvVideos : BaseUnityPlugin
{
private static string videosDir = Path.Combine(Paths.BepInExRootPath, "CustomTvVideos", "VideoClips");
private static ManualLogSource logger;
private Harmony harmony = new Harmony("sakura.custom-tv-videos");
[UsedImplicitly]
private void Awake()
{
try
{
logger = ((BaseUnityPlugin)this).Logger;
CreateDirectoryIfItDoesNotExist();
if (LoadClips())
{
harmony.PatchAll(typeof(TvScriptPatch));
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin sakura.custom-tv-videos is loaded!");
}
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogError((object)$"Encountered an error in Awake()\n {arg}");
}
}
private bool LoadClips()
{
if (new VideoGetter(((BaseUnityPlugin)this).Logger).TryGetValue(out var value))
{
List<FileInfo> list = new List<FileInfo>();
string[] array = value;
foreach (string fileName in array)
{
list.Add(new FileInfo(fileName));
}
FileInfo[] array2 = list.ToArray();
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Got {value.Length} video files.");
if (array2.Length == 0)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"No video clips where loaded, Aborting...");
((Component)this).gameObject.SetActive(false);
return false;
}
TvScriptPatch.Init(array2, logger);
return true;
}
((BaseUnityPlugin)this).Logger.LogFatal((object)"Unable to get video clips.");
((Component)this).gameObject.SetActive(false);
return false;
}
private void CreateDirectoryIfItDoesNotExist()
{
Directory.CreateDirectory(videosDir);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Video Directory: " + videosDir));
}
}
internal class VideoGetter : ITryGet<string[]>
{
[Flags]
private enum PlatformFlag
{
Unknown = 0,
Windows = 1,
MacOS = 2,
Linux = 4
}
private struct FileType
{
public string Extension;
public PlatformFlag Platform;
public FileType(string extension, PlatformFlag platform)
{
Extension = extension;
Platform = platform;
}
}
private ManualLogSource logger;
private static string videosDir = Path.Combine(Paths.BepInExRootPath, "CustomTvVideos", "VideoClips");
private static FileType[] videoFileTypes = new FileType[12]
{
new FileType(".asf", PlatformFlag.Windows),
new FileType(".avi", PlatformFlag.Windows),
new FileType(".dv", PlatformFlag.Windows | PlatformFlag.MacOS),
new FileType(".mv4", PlatformFlag.Windows | PlatformFlag.MacOS),
new FileType(".mov", PlatformFlag.Windows | PlatformFlag.MacOS),
new FileType(".mp4", PlatformFlag.Windows | PlatformFlag.MacOS),
new FileType(".mpg", PlatformFlag.Windows | PlatformFlag.MacOS),
new FileType(".mpeg", PlatformFlag.Windows | PlatformFlag.MacOS),
new FileType(".ogv", PlatformFlag.Windows | PlatformFlag.MacOS | PlatformFlag.Linux),
new FileType(".vp8", PlatformFlag.Windows | PlatformFlag.MacOS | PlatformFlag.Linux),
new FileType(".webm", PlatformFlag.Windows | PlatformFlag.MacOS | PlatformFlag.Linux),
new FileType(".wmv", PlatformFlag.Windows)
};
public VideoGetter(ManualLogSource logger)
{
this.logger = logger;
}
private static bool IsSupportedOnCurrentPlatform(string extension, PlatformFlag platform)
{
return videoFileTypes.Any((FileType x) => string.Compare(x.Extension, extension) == 0 && x.Platform.HasFlag(platform));
}
private string[] GetSupportedVideoFiles(string dir, PlatformFlag platform)
{
List<string> list = new List<string>();
foreach (string item in Directory.EnumerateFiles(dir))
{
FileInfo fileInfo = new FileInfo(item);
if (fileInfo.Exists)
{
if (IsSupportedOnCurrentPlatform(fileInfo.Extension, platform))
{
list.Add(fileInfo.FullName);
}
else
{
logger.LogWarning((object)("File: \"" + fileInfo.Name + "\" Is not supported."));
}
}
}
return list.ToArray();
}
public bool TryGetValue(out string[] value)
{
try
{
PlatformFlag currentPlatform = GetCurrentPlatform();
string[] supportedVideoFiles = GetSupportedVideoFiles(videosDir, currentPlatform);
value = supportedVideoFiles;
return true;
}
catch (Exception ex)
{
logger.LogError((object)ex);
value = null;
return false;
}
}
private static PlatformFlag GetCurrentPlatform()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Invalid comparison between Unknown and I4
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Invalid comparison between Unknown and I4
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
RuntimePlatform platform = Application.platform;
if ((int)platform != 1)
{
if ((int)platform != 2)
{
if ((int)platform == 13)
{
return PlatformFlag.Linux;
}
throw new PlatformNotSupportedException($"Platform: \"{platform}\" is not supported.");
}
return PlatformFlag.Windows;
}
return PlatformFlag.MacOS;
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "CustomTvVideos";
public const string PLUGIN_NAME = "CustomTvVideos";
public const string PLUGIN_VERSION = "0.1.3";
}
}
namespace CustomTvVideos.Patches
{
[HarmonyPatch(typeof(PlayerControllerB))]
internal static class PlayerControllerBPatch
{
}
[HarmonyPatch(typeof(TVScript))]
internal class TvScriptPatch
{
private static ManualLogSource logger;
private static FileInfo[] videoFiles;
private static int currentClip;
private static bool setupDone;
private static bool wasTvOnLastFrame;
private static float currentClipTime;
internal static void Init(FileInfo[] videos, ManualLogSource logSource)
{
videoFiles = videos;
logger = logSource;
}
private static void IncrementCurrentClip()
{
if (currentClip + 1 >= videoFiles.Length)
{
currentClip = 0;
}
else
{
currentClip++;
}
}
private static void SetVideo(TVScript tv, FileInfo videoFile)
{
tv.video.clip = null;
tv.tvSFX.clip = null;
tv.video.url = "file://" + videoFile.FullName;
tv.video.source = (VideoSource)1;
tv.video.controlledAudioTrackCount = 1;
tv.video.audioOutputMode = (VideoAudioOutputMode)1;
tv.video.SetTargetAudioSource((ushort)0, tv.tvSFX);
tv.video.Prepare();
tv.video.Stop();
tv.tvSFX.Stop();
}
[HarmonyPatch(typeof(TVScript), "TVFinishedClip")]
[HarmonyPrefix]
private static bool TV_TVFinishedClip(TVScript __instance, VideoPlayer source)
{
logger.LogInfo((object)"TV_TVFinishedClip");
if (__instance.tvOn && !GameNetworkManager.Instance.localPlayerController.isInsideFactory)
{
IncrementCurrentClip();
FileInfo fileInfo = videoFiles[currentClip];
logger.LogInfo((object)("Playing " + fileInfo.FullName));
SetVideo(__instance, fileInfo);
}
return false;
}
[HarmonyPatch(typeof(TVScript), "TurnTVOnOff")]
[HarmonyPrefix]
private static bool TV_TurnTVOnOff(TVScript __instance, bool on)
{
logger.LogInfo((object)"TV_TurnTVOnOff");
__instance.tvOn = on;
if (!setupDone)
{
__instance.video.clip = null;
__instance.tvSFX.clip = null;
IncrementCurrentClip();
FileInfo videoFile = videoFiles[currentClip];
SetVideo(__instance, videoFile);
setupDone = true;
}
if (on)
{
IncrementCurrentClip();
FileInfo videoFile2 = videoFiles[currentClip];
SetVideo(__instance, videoFile2);
SetTVScreenMaterial(__instance, b: true);
__instance.video.Play();
__instance.tvSFX.Play();
__instance.tvSFX.PlayOneShot(__instance.switchTVOn);
WalkieTalkie.TransmitOneShotAudio(__instance.tvSFX, __instance.switchTVOn, 1f);
}
else
{
SetTVScreenMaterial(__instance, b: false);
__instance.tvSFX.Stop();
__instance.tvSFX.PlayOneShot(__instance.switchTVOff);
__instance.video.Stop();
WalkieTalkie.TransmitOneShotAudio(__instance.tvSFX, __instance.switchTVOff, 1f);
}
return false;
}
[HarmonyPatch(typeof(TVScript), "Update")]
[HarmonyPrefix]
private static bool TV_Update(TVScript __instance)
{
if (NetworkManager.Singleton.ShutdownInProgress || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
return false;
}
if ((!__instance.tvOn || GameNetworkManager.Instance.localPlayerController.isInsideFactory) && wasTvOnLastFrame)
{
wasTvOnLastFrame = false;
SetTVScreenMaterial(__instance, b: false);
currentClipTime = (float)__instance.video.time;
__instance.video.Stop();
}
return false;
}
private static void SetTVScreenMaterial(TVScript instance, bool b)
{
((object)instance).GetType().GetMethod("SetTVScreenMaterial", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(instance, new object[1] { b });
}
}
}