Decompiled source of PeakThings v0.1.12
plugins/PeakThings/PeakThings.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; 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.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Evaisa.PeakThings.MonoBehaviours; using Evaisa.PeakThings.Recorder; using Evaisa.PeakThings.Recorder.CommandPackages; using Evaisa.PeakThings.Recorder.ImageEncoding; using Evaisa.PeakThings.extensions; using Evaisa.PeakThings.hooks; using Evaisa.PeakThings.modules; using ExitGames.Client.Photon; using HarmonyLib; using IL.Photon.Voice.Unity; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using On; using Photon.Pun; using Photon.Realtime; using Photon.Voice.Unity; using TMPro; using Unity.Burst; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; using Unity.Mathematics; using Unity.Profiling; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.UI; using UnityEngine.Video; using Zorro.Core; using Zorro.Core.Serizalization; using Zorro.PhotonUtility; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")] [assembly: AssemblyCompany("PeakThings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+dee5d4928f14ac4f1ee2fa917d4dce741520c1f1")] [assembly: AssemblyProduct("PeakThings")] [assembly: AssemblyTitle("PeakThings")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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 Evaisa.PeakThings { internal class CustomPrefabPool : IPunPrefabPool { public readonly Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>(); private DefaultPool? _defaultPool; public DefaultPool DefaultPool { get { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown if (_defaultPool == null) { _defaultPool = new DefaultPool(); } return _defaultPool; } set { if (value != null) { _defaultPool = value; } } } public bool RegisterPrefab(string prefabId, GameObject prefab) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { throw new ArgumentException("CustomPrefabPool: failed to register network prefab. Prefab is null."); } if (string.IsNullOrWhiteSpace(prefabId)) { throw new ArgumentException("CustomPrefabPool: failed to register network prefab. PrefabId is invalid."); } if (HasPrefab(prefabId)) { PeakThings.Log.LogError((object)("CustomPrefabPool: failed to register network prefab \"" + prefabId + "\". Prefab already exists in Resources with the same prefab id.")); return false; } if (Prefabs.TryGetValue(prefabId, out GameObject value, ignoreKeyCase: true)) { LogLevel val = (LogLevel)(((Object)(object)value == (Object)(object)prefab) ? 4 : 2); PeakThings.Log.Log(val, (object)("CustomPrefabPool: failed to register network prefab \"" + prefabId + "\". There is already a prefab registered with the same prefab id.")); return false; } Prefabs[prefabId] = prefab; PeakThings.Log.LogDebug((object)("CustomPrefabPool: registered network prefab \"" + prefabId + "\"")); return true; } public bool HasPrefab(GameObject prefab) { if (Prefabs.ContainsValue(prefab)) { return true; } return false; } public bool HasPrefab(string prefabId) { return (Object)(object)GetPrefab(prefabId) != (Object)null; } public string? GetPrefabId(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { PeakThings.Log.LogError((object)"Failed to get prefab id. GameObject is null."); return string.Empty; } return Prefabs.GetKeyOrDefault(prefab); } public GameObject? GetPrefab(string prefabId) { if (Prefabs.TryGetValue(prefabId, out GameObject value, ignoreKeyCase: true)) { return value; } return Resources.Load<GameObject>(prefabId); } public GameObject? Instantiate(string prefabId, Vector3 position, Quaternion rotation) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(prefabId)) { throw new ArgumentException("CustomPrefabPool: failed to spawn network prefab. PrefabId is null."); } GameObject val; if (!Prefabs.TryGetValue(prefabId, out GameObject value, ignoreKeyCase: true)) { val = DefaultPool.Instantiate(prefabId, position, rotation); if ((Object)(object)val == (Object)null) { PeakThings.Log.LogError((object)("CustomPrefabPool: failed to spawn network prefab \"" + prefabId + "\". GameObject is null.")); } return val; } bool activeSelf = value.activeSelf; if (activeSelf) { value.SetActive(false); } val = Object.Instantiate<GameObject>(value, position, rotation); if (activeSelf) { value.SetActive(true); } PeakThings.Log.LogInfo((object)$"CustomPrefabPool: spawned network prefab \"{prefabId}\" at position {position}, rotation {((Quaternion)(ref rotation)).eulerAngles}"); return val; } public void Destroy(GameObject gameObject) { Object.Destroy((Object)(object)gameObject); } } [BepInPlugin("evaisa.PeakThings", "PeakThings", "0.1.12")] public class PeakThings : BaseUnityPlugin { [CompilerGenerated] private sealed class <DelayedFunction>d__24 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Action action; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedFunction>d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; action(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadBundleAsync>d__34 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string path; public PeakThings <>4__this; private AssetBundleCreateRequest <bundleRequest>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadBundleAsync>d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <bundleRequest>5__2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; PeakThings peakThings = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <bundleRequest>5__2 = AssetBundle.LoadFromFileAsync(path); <>2__current = <bundleRequest>5__2; <>1__state = 1; return true; case 1: <>1__state = -1; Bundle = <bundleRequest>5__2.assetBundle; peakThings.Register(); VideoCamera.SetupCameraControllers(((Component)peakThings).gameObject); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string GUID = "evaisa.PeakThings"; public const string ModName = "PeakThings"; public const string Version = "0.1.12"; private bool patchedAwake; public Dictionary<string, GameObject> prefabs = new Dictionary<string, GameObject>(); public Dictionary<string, string> translationsRealNotFake = new Dictionary<string, string> { { "NAME_Camera", "Camera" }, { "NAME_ArsonItem", "Arson" }, { "NAME_TapeRecording", "Found Footage" }, { "Camera", "Camera" }, { "ArsonItem", "Arson" }, { "TapeRecording", "Found Footage" }, { "ToggleRecording", "Toggle Recording" }, { "FlipCamera", "Flip Camera" }, { "Zoom", "Zoom" }, { "Squeeze", "Squeeze!" }, { "DingusItem", "Dingus" }, { "Meow", "Meow" }, { "Toggle Music", "Toggle Music" } }; public ConfigEntry<float> MaxRecordingTime; public ConfigEntry<bool> DisableFolderShortcuts; public ConfigEntry<KeyCode> TempFileFolderKey; public ConfigEntry<KeyCode> CompletedRecordingFolderKey; public bool spawnedStuffThisRun; public static PeakThings Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static AssetBundle Bundle { get; set; } private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; LoadSettings(); ItemCookingHooks.Setup(); ItemHooks.Setup(); GameHandler.Awake += new hook_Awake(GameHandler_Awake); Character.Update += new hook_Update(Character_Update); Mirror.Start += new hook_Start(Mirror_Start); RunManager.StartRun += new hook_StartRun(RunManager_StartRun); DataEntryValue.GetNewFromValue += new hook_GetNewFromValue(DataEntryValue_GetNewFromValue); DataEntryValue.GetTypeValue += new hook_GetTypeValue(DataEntryValue_GetTypeValue); InRoomState.Enter += new hook_Enter(InRoomState_Enter); MainMenu.Start += new hook_Start(MainMenu_Start); Log.LogInfo((object)"PeakThings is loaded!"); MicWrapper.Read += new Manipulator(MicWrapper_Read); LocalizedText.LoadMainTable += new hook_LoadMainTable(LocalizedText_LoadMainTable); } public void LoadSettings() { MaxRecordingTime = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Max Recording Time", 180f, "Maximum recording time in seconds, -1 for unlimited."); DisableFolderShortcuts = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Disable Folder Shortcuts", false, "Disable folder shortcuts for open recording folders."); TempFileFolderKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "Temp Recording Folder Key", (KeyCode)284, "Key to open the temporary recordings folder."); CompletedRecordingFolderKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "Completed Recording Folder Key", (KeyCode)287, "Key to open the completed recordings folder. (Cleared upon new run)"); } [IteratorStateMachine(typeof(<DelayedFunction>d__24))] private IEnumerator DelayedFunction(Action action) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedFunction>d__24(0) { action = action }; } private void MainMenu_Start(orig_Start orig, MainMenu self) { RetrievableSingleton<RecordingsHandler>.Instance.ClearRecordings(); orig.Invoke(self); } private void LocalizedText_LoadMainTable(orig_LoadMainTable orig, bool forceSerialization) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(forceSerialization); foreach (Language value in Enum.GetValues(typeof(Language))) { foreach (KeyValuePair<string, string> item in translationsRealNotFake) { CreateLocalizationInternal(item.Key, item.Value, value); } } } internal static void CreateLocalizationInternal(string index, string translation, Language language) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected I4, but got Unknown string translation2 = translation; index = index.ToUpperInvariant(); if (!LocalizedText.MAIN_TABLE.TryGetValue(index, out var value)) { value = new List<string>(); value.AddRange(from Language _ in Enum.GetValues(typeof(Language)) select translation2); LocalizedText.MAIN_TABLE.Add(index, value); } else { value[(int)language] = translation2; } } private void MicWrapper_Read(ILContext il) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) MethodBody body = il.Body; ModuleDefinition module = ((MemberReference)body.Method).Module; VariableDefinition val = new VariableDefinition(module.ImportReference(typeof(RecorderAudioListener))); body.Variables.Add(val); body.InitLocals = true; MethodInfo getMethod = typeof(Singleton<RecorderAudioListener>).GetProperty("Instance").GetGetMethod(); MethodInfo getMethod2 = typeof(MicWrapper).GetProperty("SamplingRate").GetGetMethod(); MethodInfo getMethod3 = typeof(MicWrapper).GetProperty("Channels").GetGetMethod(); MethodInfo method = typeof(RecorderAudioListener).GetMethod("SendMic", new Type[3] { typeof(float[]), typeof(int), typeof(int) }); ILCursor val2 = new ILCursor(il); if (val2.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchCallvirt(instr, "Photon.Voice.Unity.MicrophoneRelay", "SendMic") })) { ILLabel val3 = val2.DefineLabel(); val2.Emit(OpCodes.Call, module.ImportReference((MethodBase)getMethod)); val2.Emit(OpCodes.Stloc, val); val2.Emit(OpCodes.Ldloc, val); val2.Emit(OpCodes.Brfalse_S, (object)val3); val2.Emit(OpCodes.Ldloc, val); val2.Emit(OpCodes.Ldarg_1); val2.Emit(OpCodes.Ldarg_0); val2.Emit(OpCodes.Callvirt, module.ImportReference((MethodBase)getMethod2)); val2.Emit(OpCodes.Ldarg_0); val2.Emit(OpCodes.Callvirt, module.ImportReference((MethodBase)getMethod3)); val2.Emit(OpCodes.Callvirt, module.ImportReference((MethodBase)method)); val2.MarkLabel(val3); } } private void LoadItems() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) spawnedStuffThisRun = true; Log.LogInfo((object)"Attempting to load items."); RetrievableSingleton<RecordingsHandler>.Instance.ClearRecordings(); if (PhotonNetwork.IsMasterClient && !(SceneManagerHelper.ActiveSceneName == "Airport")) { if (prefabs.ContainsKey("CamcorderItem")) { Transform transform = GameObject.Find("front half/Frame.007").transform; Instance.SpawnPrefab("CamcorderItem", transform.position + transform.forward * 1.2f + transform.right * 2.5f, Quaternion.LookRotation(-transform.right)); } if (prefabs.ContainsKey("ArsonItem")) { Transform transform2 = GameObject.Find("Back Half/Frame.001").transform; Instance.SpawnPrefab("ArsonItem", transform2.position + transform2.forward * 1.2f + transform2.right * 0.2f, Quaternion.LookRotation(-transform2.right)); } } } private void InRoomState_Enter(orig_Enter orig, InRoomState self) { orig.Invoke(self); Debug.Log((object)"InRoomState_Enter called, registering custom command packages."); CommandListener component = GameObject.Find("CustomCommandListener").GetComponent<CommandListener>(); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<StartRecordingCommandPackage>(new StartRecordingCommandPackage()); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<StopRecordingCommandPackage>(new StopRecordingCommandPackage()); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<SendVideoChunkPackage>(new SendVideoChunkPackage()); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<AddClipToShareQueuePackage>(new AddClipToShareQueuePackage()); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<ActivateNextSharingJobPackage>(new ActivateNextSharingJobPackage()); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<SendClipCompletedPackage>(new SendClipCompletedPackage()); ((CustomCommandListener<CustomCommandType>)(object)component).RegisterPackage<ReRequestClipPackage>(new ReRequestClipPackage()); } private byte DataEntryValue_GetTypeValue(orig_GetTypeValue orig, Type type) { if (type == typeof(VideoInfoEntry)) { return 53; } if (type == typeof(FlashcardEntry)) { return 54; } return orig.Invoke(type); } private DataEntryValue DataEntryValue_GetNewFromValue(orig_GetNewFromValue orig, byte value) { return (DataEntryValue)(value switch { 53 => new VideoInfoEntry(), 54 => new FlashcardEntry(), _ => orig.Invoke(value), }); } [IteratorStateMachine(typeof(<LoadBundleAsync>d__34))] private IEnumerator LoadBundleAsync(string path) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadBundleAsync>d__34(0) { <>4__this = this, path = path }; } private void RunManager_StartRun(orig_StartRun orig, RunManager self) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); Log.LogInfo((object)"RunManager_StartRun"); RecordingsHandler instance = RetrievableSingleton<RecordingsHandler>.Instance; PhotonSendVideoHandler instance2 = RetrievableSingleton<PhotonSendVideoHandler>.Instance; spawnedStuffThisRun = false; if (!PhotonNetwork.IsMasterClient || SceneManagerHelper.ActiveSceneName != "Airport") { if (SceneManagerHelper.ActiveSceneName.StartsWith("Level_") && PhotonNetwork.IsConnected && PhotonNetwork.IsMasterClient) { ((MonoBehaviour)this).StartCoroutine(DelayedFunction(LoadItems)); } } else { Log.LogInfo((object)"Spawning TVSet prefab"); Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(-15.29617f, 3.101736f, 106.5155f); Quaternion rotation = Quaternion.Euler(0f, 0f, 0f); SpawnPrefab("TVSet", position, rotation); } } public void RegisterPrefab(string id, string path) { if (prefabs.ContainsKey(id)) { Log.LogWarning((object)("Prefab " + id + " is already registered.")); return; } GameObject val = Bundle.LoadAsset<GameObject>(path); if ((Object)(object)val == (Object)null) { Log.LogError((object)("Prefab " + id + " could not be loaded from path " + path + ".")); } else { ((Object)val).name = "PeakThings_" + ((Object)val).name; FixPrefabReferences(val); prefabs[id] = val; NetworkPrefabs.RegisterNetworkPrefab("0_Items/" + ((Object)val).name, val); Log.LogInfo((object)("Registered prefab " + ((Object)val).name + " from path " + path + ".")); } } private void Mirror_Start(orig_Start orig, Mirror self) { Camera mirrorCamera = self.mirrorCamera; mirrorCamera.cullingMask |= 0x10000000; orig.Invoke(self); } public void Start() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline; UniversalRenderPipelineAsset val = (UniversalRenderPipelineAsset)(object)((currentRenderPipeline is UniversalRenderPipelineAsset) ? currentRenderPipeline : null); ScriptableRendererData obj = val.rendererDataList[0]; UniversalRendererData val2 = (UniversalRendererData)(object)((obj is UniversalRendererData) ? obj : null); val2.transparentLayerMask = LayerMask.op_Implicit(LayerMask.op_Implicit(val2.transparentLayerMask) | 0x10000000); val2.opaqueLayerMask = LayerMask.op_Implicit(LayerMask.op_Implicit(val2.opaqueLayerMask) | 0x10000000); HelperFunctions.AllPhysical = LayerMask.op_Implicit(LayerMask.op_Implicit(HelperFunctions.AllPhysical) | 0x10000000); HelperFunctions.AllPhysicalExceptCharacter = LayerMask.op_Implicit(LayerMask.op_Implicit(HelperFunctions.AllPhysicalExceptCharacter) | 0x10000000); HelperFunctions.DefaultMask = LayerMask.op_Implicit(LayerMask.op_Implicit(HelperFunctions.DefaultMask) | 0x10000000); } public void Register() { RegisterPrefab("CamcorderItem", "Assets/Custom/PeakThings/Items/Camcorder/CamcorderItem.prefab"); RegisterPrefab("ArsonItem", "Assets/Custom/PeakThings/Items/Arson/ArsonItem.prefab"); RegisterPrefab("TVSet", "Assets/Custom/PeakThings/Lobby/TVSet.prefab"); RegisterPrefab("TapeRecording", "Assets/Custom/PeakThings/Items/Tape/TapeRecording.prefab"); RegisterPrefab("Dingus", "Assets/Custom/PeakThings/Items/Dingus/Dingus.prefab"); RegisterItem(prefabs["CamcorderItem"].GetComponent<Item>()); RegisterItem(prefabs["ArsonItem"].GetComponent<Item>()); RegisterItem(prefabs["TapeRecording"].GetComponent<Item>()); RegisterItem(prefabs["Dingus"].GetComponent<Item>()); } private void RegisterItem(Item item) { ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance; byte[] value = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("evaisa.PeakThings" + ((Object)item).name)); ushort key = (item.itemID = BitConverter.ToUInt16(value, 0)); ((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects.Add(item); instance.itemLookup.Add(key, item); } private void GameHandler_Awake(orig_Awake orig, GameHandler self) { orig.Invoke(self); if (!patchedAwake) { Log.LogInfo((object)"Patching GameHandler.Awake"); patchedAwake = true; NetworkPrefabs.Initialize(); string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "peakthings"); ((MonoBehaviour)this).StartCoroutine(LoadBundleAsync(path)); } } private static Texture2D CreateReadableRGBA32(Texture2D src) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) RenderTexture temporary = RenderTexture.GetTemporary(((Texture)src).width, ((Texture)src).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0); Graphics.Blit((Texture)(object)src, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)src).width, ((Texture)src).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); return val; } public void FixPrefabReferences(GameObject prefab) { //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) Shader shader = Shader.Find("W/Peak_Standard"); Shader shader2 = Shader.Find("W/Peak_Transparent"); Shader shader3 = Shader.Find("Universal Render Pipeline/Lit"); Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] materials = val.materials; foreach (Material val2 in materials) { if (((Object)val2.shader).name == "W/Peak_Standard") { val2.shader = shader; } else if (((Object)val2.shader).name == "W/Peak_Transparent") { val2.shader = shader2; } else { val2.shader = shader3; } } } foreach (Material item in prefab.GetComponentsInChildren<Renderer>(true).SelectMany((Renderer r) => r.materials)) { if (!item.HasProperty("_BaseTexture")) { continue; } Texture texture = item.GetTexture("_BaseTexture"); Texture2D val3 = (Texture2D)(object)((texture is Texture2D) ? texture : null); if ((Object)(object)val3 != (Object)null) { Texture2D val4 = CreateReadableRGBA32(val3); Color[] pixels = val4.GetPixels(); for (int k = 0; k < pixels.Length; k++) { ref Color reference = ref pixels[k]; reference *= 1.2f; } val4.SetPixels(pixels); val4.Apply(); item.SetTexture("_BaseTexture", (Texture)(object)val4); } } Shader shader4 = Shader.Find("Shader Graphs/Decal"); DecalProjector[] componentsInChildren2 = prefab.GetComponentsInChildren<DecalProjector>(true); foreach (DecalProjector val5 in componentsInChildren2) { val5.material.shader = shader4; Log.LogInfo((object)("Fixed decal shader for " + ((Object)val5).name + " in prefab " + ((Object)prefab).name + ".")); } ParticleSystem[] componentsInChildren3 = prefab.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val6 in componentsInChildren3) { ParticleSystemRenderer component = ((Component)val6).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).material != (Object)null && ((Object)((Renderer)component).material).name.Contains("Smoke")) { ((Renderer)component).material = ((IEnumerable<Material>)Resources.FindObjectsOfTypeAll<Material>()).FirstOrDefault((Func<Material, bool>)((Material x) => ((Object)x).name == "Smoke")); } } TextMeshProUGUI[] componentsInChildren4 = prefab.GetComponentsInChildren<TextMeshProUGUI>(true); foreach (TextMeshProUGUI val7 in componentsInChildren4) { ((TMP_Text)val7).font = Resources.Load<TMP_FontAsset>("Font/DarumaDropOne-Regular SDF"); } } private void Character_Update(orig_Update orig, Character character) { orig.Invoke(character); } internal GameObject SpawnPrefab(string id, Vector3 position, Quaternion rotation) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return null; } if (!prefabs.ContainsKey(id)) { return null; } string name = ((Object)prefabs[id]).name; string text = "0_Items/" + name; if (!NetworkPrefabs.TryGetNetworkPrefab(text, out GameObject _)) { Log.LogError((object)("Failed to spawn prefab " + text + ". Prefab not found.")); return null; } try { GameObject result = PhotonNetwork.Instantiate(text, position, rotation, (byte)0, (object[])null); Log.LogInfo((object)$"Spawned prefab {text} at {position} with rotation {rotation}."); return result; } catch (Exception ex) { Log.LogError((object)("Error spawning prefab " + name + ": " + ex.Message)); } return null; } internal GameObject SpawnPrefab(string id, Character character) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) if (!PhotonNetwork.IsMasterClient) { return null; } Vector3 val = character.Center + Vector3.up * 1f + Random.insideUnitSphere * 1.5f; val.y = Mathf.Max(val.y, character.Center.y); Quaternion rotation = Quaternion.Euler(0f, 0f, 0f); return SpawnPrefab(id, val, rotation); } } public static class EnumerableExtensions { public static void ForEachTry<T>(this IEnumerable<T> list, Action<T> action, IDictionary<T, Exception> exceptions = null) { Action<T> action2 = action; IDictionary<T, Exception> exceptions2 = exceptions; list.ToList().ForEach(delegate(T element) { try { action2(element); } catch (Exception value) { exceptions2?.Add(element, value); } }); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "PeakThings"; public const string PLUGIN_NAME = "PeakThings"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace Evaisa.PeakThings.Recorder { public class AudioData { public float[] Data; public AudioData(float[] data) { Data = data; } } public class CameraHandler : Singleton<CameraHandler> { private Dictionary<Guid, VideoCamera> m_cameras = new Dictionary<Guid, VideoCamera>(); public static void RegisterCamera(Guid id, VideoCamera camera) { PeakThings.Log.LogInfo((object)$"Registering camera with ID: {id}"); if ((Object)(object)Singleton<CameraHandler>.Instance != (Object)null) { Singleton<CameraHandler>.Instance.m_cameras.Add(id, camera); PeakThings.Log.LogInfo((object)("Camera registered successfully: " + ((Object)camera).name)); } } public static void UnregisterCamera(Guid id) { if ((Object)(object)Singleton<CameraHandler>.Instance != (Object)null) { Singleton<CameraHandler>.Instance.m_cameras.Remove(id); } } public static bool TryGetCamera(Guid instanceDataGuid, out VideoCamera videoCamera) { if ((Object)(object)Singleton<CameraHandler>.Instance == (Object)null) { videoCamera = null; return false; } return Singleton<CameraHandler>.Instance.m_cameras.TryGetValue(instanceDataGuid, out videoCamera); } } public class CameraRecording : MonoBehaviour, IPlayableVideo { public VideoHandle videoHandle; private List<Clip> m_clips; public DateTime m_lastModified; public int ClipCount => m_clips.Count; public DateTime LastModified => m_lastModified; public bool ReadyToExtract(out string failureReason) { int clipCount = ClipCount; failureReason = $"video={videoHandle.id}:"; bool result = true; for (int i = 0; i < clipCount; i++) { Clip clip = GetClip(i); if (!clip.Valid) { continue; } if (clip.isRecording) { failureReason += $" clip {i} of {clipCount} ({clip.clipID.id}) still recording!"; result = false; continue; } if (clip.local && !clip.encoded) { failureReason += $" clip {i} of {clipCount} ({clip.clipID.id}) is local but not encoded!"; result = false; } if (!clip.local && !clip.hasBeenRecieved) { failureReason += $" clip {i} of {clipCount} ({clip.clipID.id}) is from another player but not downloaded!"; result = false; } } return result; } public void SetInfo(VideoHandle videoID) { videoHandle = videoID; m_clips = new List<Clip>(); } public void AddNewClip(Clip clip) { m_lastModified = DateTime.Now; m_clips.Add(clip); Debug.Log((object)$"video {GuidExtensions.ToShortString(videoHandle.id)} added new clip: {clip.clipID.ToShortString()}, total clips: {m_clips.Count}"); } public Clip EndCurrentClip() { if (m_clips.Count == 0) { Debug.LogWarning((object)"No clips to end"); return null; } List<Clip> clips = m_clips; Clip clip = clips[clips.Count - 1]; clip.EndClip(); return clip; } public Clip GetClip(int i) { return m_clips[i]; } public string GetDirectory() { return Path.Combine(RecordingsHandler.GetDirectory(), videoHandle.id.ToString()); } public List<Clip> GetAllClips() { return m_clips; } public bool TryGetLatestClip(out Clip clip) { if (m_clips.Count > 0) { List<Clip> clips = m_clips; clip = clips[clips.Count - 1]; return true; } clip = null; return false; } public bool SaveToDesktop(out string videoFileName) { if (!RecordingsHandler.TryGetRecordingPath(videoHandle, out string path)) { videoFileName = string.Empty; return false; } videoFileName = "content_warning_" + GuidExtensions.ToShortString(videoHandle.id) + ".webm"; string destFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), videoFileName); if (!File.Exists(path)) { Debug.LogError((object)("Video: " + path + " Does Not Exist!")); return false; } File.Copy(path, destFileName); return true; } public bool TryGetClip(ClipID clipID, out Clip clip) { foreach (Clip clip2 in m_clips) { if (clipID.Equals(clip2.clipID)) { clip = clip2; return true; } } clip = null; return false; } public bool TryGetVideoPath(out string path) { return RecordingsHandler.TryGetRecordingPath(videoHandle, out path); } } [Serializable] public class Clip { public CameraRecording m_recording; public ClipID clipID; public bool local; public int ownerID; public bool isRecording; public bool encoded; public bool hasBeenRecieved; public float m_timeStarted; public float m_timeEnded; private VideoRecorder m_recorder; public bool Valid { get; protected set; } public float ClipLength => m_timeEnded - m_timeStarted; public Clip(ClipID clipID, bool local, int ownerID, CameraRecording recording) { this.ownerID = ownerID; this.clipID = clipID; this.local = local; isRecording = true; m_recording = recording; m_timeStarted = Time.time; Valid = true; } public void EndClip() { m_timeEnded = Time.time; isRecording = false; if ((Object)(object)m_recorder != (Object)null && !m_recorder.HasRecorded) { Debug.LogError((object)"Clip: CLIP HAS NO FRAMES!"); } PeakThings.Log.LogInfo((object)("Ended clip: " + clipID.ToShortString())); } public void SetRecorder(VideoRecorder recorder) { m_recorder = recorder; } public VideoRecorder GetRecorder() { return m_recorder; } public string GetClipDirectory() { return Path.Combine(m_recording.GetDirectory(), clipID.id.ToString()); } public void SetValid(bool validClip) { Valid = validClip; } } public struct ClipID : IComparable<ClipID>, IEquatable<ClipID> { public Guid id; public ClipID(Guid id) { this.id = id; } public int CompareTo(ClipID other) { return id.CompareTo(other.id); } public bool Equals(ClipID other) { return id.Equals(other.id); } public override string ToString() { return id.ToString(); } public string ToShortString() { return id.ToString().Substring(0, 8); } public string ToMiniString() { return id.ToString().Substring(0, 3); } } public enum FfmpegDeadline { None, Realtime } public class FfmpegEncoder { [CompilerGenerated] private sealed class <>c__DisplayClass5_0 { public Task<string> outputTask; internal bool <RunFfmpeg>b__0() { return outputTask.IsCompleted; } } [CompilerGenerated] private sealed class <Encode>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public FfmpegEncoder <>4__this; public bool mic; public byte framerate; public FfmpegDeadline deadline; public bool displayWindow; private DirectoryInfo <directory>5__2; private int <audioSampleRate>5__3; private int <micSampleRate>5__4; private int <micChannels>5__5; private string <fullAudioPath>5__6; private string <fullMicAudioPath>5__7; private int <frameCount>5__8; private float <duration>5__9; private string <outputPath>5__10; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Encode>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <directory>5__2 = null; <fullAudioPath>5__6 = null; <fullMicAudioPath>5__7 = null; <outputPath>5__10 = null; <>1__state = -2; } private bool MoveNext() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; FfmpegEncoder ffmpegEncoder = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <directory>5__2 = ffmpegEncoder.m_session.Pipe.GetDirectory(); <audioSampleRate>5__3 = AudioSettings.outputSampleRate; <micSampleRate>5__4 = 24000; <micChannels>5__5 = 2; if (ffmpegEncoder.m_session.MicSampleRate.IsSome) { <micSampleRate>5__4 = ffmpegEncoder.m_session.MicSampleRate.Value; } if (ffmpegEncoder.m_session.MicChannels.IsSome) { <micChannels>5__5 = ffmpegEncoder.m_session.MicChannels.Value; } <fullAudioPath>5__6 = ffmpegEncoder.m_session.GetAudioPath(); <fullMicAudioPath>5__7 = ffmpegEncoder.m_session.GetMicAudioPath(); ffmpegEncoder.SaveAudioBlobs(mic); <>2__current = (object)new WaitForSecondsRealtime(0.1f); <>1__state = 1; return true; case 1: { <>1__state = -1; <frameCount>5__8 = <directory>5__2.GetFiles().Length; <duration>5__9 = (float)<frameCount>5__8 / (float)(int)framerate; List<string> list = new List<string>(); string item = <directory>5__2.FullName + "/Test%04d.png"; <outputPath>5__10 = <directory>5__2.FullName + "/output.webm"; string item2 = "24000"; list.Add("-y"); list.Add("-thread_queue_size"); list.Add("512"); list.Add("-r"); list.Add(framerate.ToString()); list.Add("-i"); list.Add(item); if (!string.IsNullOrEmpty(<fullAudioPath>5__6)) { list.Add("-f"); list.Add("f32le"); list.Add("-ac"); list.Add("2"); list.Add("-ar"); list.Add(<audioSampleRate>5__3.ToString()); list.Add("-thread_queue_size"); list.Add("512"); list.Add("-i"); list.Add(<fullAudioPath>5__6); } if (mic) { list.Add("-f"); list.Add("f32le"); list.Add("-ac"); list.Add(<micChannels>5__5.ToString()); list.Add("-ar"); list.Add(<micSampleRate>5__4.ToString()); list.Add("-thread_queue_size"); list.Add("512"); list.Add("-i"); list.Add(<fullMicAudioPath>5__7); } if (!string.IsNullOrEmpty(<fullAudioPath>5__6)) { list.Add("-map"); list.Add("0:0"); list.Add("-map"); list.Add("1:0"); list.Add("-c:a"); list.Add("libvorbis"); list.Add("-ac"); list.Add("2"); list.Add("-ar"); list.Add(item2); if (mic) { list.Add("-filter_complex"); list.Add("amix=inputs=2"); } } list.Add("-c:v"); list.Add("libvpx"); list.Add("-cpu-used"); list.Add("-5"); if (deadline == FfmpegDeadline.Realtime) { list.Add("-deadline"); list.Add("realtime"); } list.Add("-pix_fmt"); list.Add("yuv420p"); list.Add("-speed"); list.Add("1"); list.Add("-preset"); list.Add("ultrafast"); list.Add(<outputPath>5__10); <>2__current = ffmpegEncoder.RunFfmpeg(list, displayWindow); <>1__state = 2; return true; } case 2: { <>1__state = -1; float num2 = (float)(ffmpegEncoder.m_session.AudioFrames * ffmpegEncoder.m_session.AudioDataSize) / ((float)AudioSettings.outputSampleRate * 2f); Debug.Log((object)$"Encoded {<directory>5__2.FullName}, {<frameCount>5__8} frames, Audio Frames {ffmpegEncoder.m_session.AudioFrames}, Audio Data Size {ffmpegEncoder.m_session.AudioDataSize}, Audio Duration {num2:F}s, Video Duration {<duration>5__9:F}s"); if (!File.Exists(<outputPath>5__10)) { if (ffmpegEncoder.ErrorTitle == null) { ffmpegEncoder.ErrorTitle = "Encode FAIL, Video path not found"; ffmpegEncoder.ErrorBody = <outputPath>5__10; } Debug.LogError((object)("Encode FAIL, Video path not found" + <outputPath>5__10)); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RunFfmpeg>d__5 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public List<string> arguments; public bool displayWindow; public FfmpegEncoder <>4__this; private <>c__DisplayClass5_0 <>8__1; private Stopwatch <stopwatch>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RunFfmpeg>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <stopwatch>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown int num = <>1__state; FfmpegEncoder ffmpegEncoder = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; <>8__1 = new <>c__DisplayClass5_0(); Debug.Log((object)("Running FFmpeg encode... " + string.Join(" ", arguments))); <stopwatch>5__2 = new Stopwatch(); <stopwatch>5__2.Start(); ProcessStartInfo processStartInfo = new ProcessStartInfo { FileName = ExecutablePath, UseShellExecute = displayWindow, CreateNoWindow = !displayWindow, RedirectStandardInput = false, RedirectStandardOutput = false, RedirectStandardError = true }; foreach (string argument in arguments) { processStartInfo.ArgumentList.Add(argument); } try { ffmpegEncoder.m_ffmpegProcess = Process.Start(processStartInfo); } catch (Exception ex) { Debug.LogException(ex); Debug.LogError((object)"Process.Start threw exception, see above (as a result, we probably failed to encode)"); ffmpegEncoder.ErrorTitle = "Failed to start ffmpeg to encode video"; if (ex is Win32Exception ex2 && ex2.ToString().Contains("Access is denied")) { ffmpegEncoder.ErrorTitle += " (Access is denied)"; } ffmpegEncoder.ErrorBody = ex.ToString(); return false; } if (ffmpegEncoder.m_ffmpegProcess == null) { Debug.LogError((object)"Process.Start returned null (as a result, we probably failed to encode)"); ffmpegEncoder.ErrorTitle = "Failed to start ffmpeg to encode video"; ffmpegEncoder.ErrorBody = "Process.Start returned null"; return false; } <>8__1.outputTask = ffmpegEncoder.m_ffmpegProcess.StandardError.ReadToEndAsync(); goto IL_01bd; } case 1: <>1__state = -1; goto IL_01bd; case 2: { <>1__state = -1; break; } IL_01bd: if (!ffmpegEncoder.m_ffmpegProcess.HasExited) { <>2__current = null; <>1__state = 1; return true; } if (!<>8__1.outputTask.IsCompleted) { <>2__current = (object)new WaitUntil((Func<bool>)(() => <>8__1.outputTask.IsCompleted)); <>1__state = 2; return true; } break; } string result = <>8__1.outputTask.Result; <stopwatch>5__2.Stop(); Debug.Log((object)$"FFmpeg took {<stopwatch>5__2.Elapsed.TotalSeconds:F3}s to encode the video."); if (!string.IsNullOrWhiteSpace(result)) { Debug.Log((object)$"Encoder FFmpeg stderr (exit code {ffmpegEncoder.m_ffmpegProcess.ExitCode}) {result}"); } ffmpegEncoder.m_ffmpegProcess.Dispose(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private Process m_ffmpegProcess; private RecordingSession m_session; public string ErrorTitle; public string ErrorBody; public static string ExecutablePath { get { //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_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 RuntimePlatform platform = Application.platform; if ((int)platform > 1) { if ((int)platform == 13 || (int)platform == 16) { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ffmpeg"); } return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ffmpeg.exe"); } return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ffmpeg"); } } public FfmpegEncoder(RecordingSession session) { m_session = session; } [IteratorStateMachine(typeof(<Encode>d__3))] public IEnumerator Encode(byte framerate, FfmpegDeadline deadline, bool displayWindow, bool mic) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Encode>d__3(0) { <>4__this = this, framerate = framerate, deadline = deadline, displayWindow = displayWindow, mic = mic }; } private void SaveAudioBlobs(bool saveMic) { m_session.Pipe.GetDirectory().Create(); byte[] audioBlob = m_session.GetAudioBlob(); string audioPath = m_session.GetAudioPath(); try { if (audioBlob != null) { File.WriteAllBytes(audioPath, audioBlob); } if (saveMic) { byte[] micAudioBlob = m_session.GetMicAudioBlob(); string micAudioPath = m_session.GetMicAudioPath(); if (micAudioBlob != null) { File.WriteAllBytes(micAudioPath, micAudioBlob); } } } catch (IOException ex) when (ex.HResult == -2147024784) { Debug.LogException((Exception)ex); Debug.LogError((object)"Failed to write to disk due to the above exception"); ErrorTitle = "Disk full"; ErrorBody = "Recording failed due to full disk. Please clear out your disk and restart the game.\n" + ex.Message; } catch (Exception ex2) { Debug.LogException(ex2); Debug.LogError((object)"Failed to write to disk due to the above exception"); ErrorTitle = "Failed to write camera recording image to disk"; ErrorBody = ex2.ToString(); } } [IteratorStateMachine(typeof(<RunFfmpeg>d__5))] private IEnumerator RunFfmpeg(List<string> arguments, bool displayWindow) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RunFfmpeg>d__5(0) { <>4__this = this, arguments = arguments, displayWindow = displayWindow }; } } public static class FFmpegStitcher { public static void StichVideos(string[] videos, string outputDirectory) { string text = Path.Combine(outputDirectory, "videoList.txt"); string item = Path.Combine(outputDirectory, "fullRecording.webm"); string text2 = ""; foreach (string text3 in videos) { if (text3.Contains('\'')) { Debug.LogWarning((object)("Video path contains single quote character \"'\", will attempt to escape it: " + text3)); } text2 = text2 + "file '" + text3.Replace("'", "'\\''") + "'\n"; if (!File.Exists(text3)) { Debug.LogError((object)("Video File Not Found: " + text3)); } } File.WriteAllText(text, text2); Debug.Log((object)("Stitching videos together: " + text2)); ProcessStartInfo processStartInfo = new ProcessStartInfo { FileName = FfmpegEncoder.ExecutablePath, UseShellExecute = false, RedirectStandardOutput = false, RedirectStandardError = true, CreateNoWindow = true }; processStartInfo.ArgumentList.Add("-y"); processStartInfo.ArgumentList.Add("-f"); processStartInfo.ArgumentList.Add("concat"); processStartInfo.ArgumentList.Add("-safe"); processStartInfo.ArgumentList.Add("0"); processStartInfo.ArgumentList.Add("-i"); processStartInfo.ArgumentList.Add(text); processStartInfo.ArgumentList.Add("-c"); processStartInfo.ArgumentList.Add("copy"); processStartInfo.ArgumentList.Add(item); Debug.Log((object)("Starting FFmpegStitcher: " + string.Join(" ", processStartInfo.ArgumentList))); Process process = Process.Start(processStartInfo); if (process == null) { Debug.LogError((object)"Video stitch ffmpeg Process.Start returned null"); return; } string arg = process.StandardError.ReadToEnd(); process.WaitForExit(); Debug.Log((object)$"Video stitch ffmpeg stderr (exit code {process.ExitCode}): {arg}"); } } public class FlashcardEntry : DataEntryValue { public VideoHandle videoID; public string title = "Found Footage"; public override void SerializeValue(BinarySerializer serializer) { serializer.WriteGuid(videoID.id); serializer.WriteString(title, Encoding.UTF8); } public override void DeserializeValue(BinaryDeserializer deserializer) { videoID = new VideoHandle(deserializer.ReadGuid()); title = deserializer.ReadString(Encoding.UTF8); } } public interface IPlayableVideo { bool TryGetVideoPath(out string path); } public class PngEncodeJobHandle { public JobHandle JobHandle; public NativeList<byte> OutputBuffer; public PngEncodeJobHandle(JobHandle jobHandle, NativeList<byte> outputBuffer) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) JobHandle = jobHandle; OutputBuffer = outputBuffer; } } public class QueuedFrame { public RenderTexture Frame; public AsyncGPUReadbackRequest ReadbackRequest; public QueuedFrame(RenderTexture frame, AsyncGPUReadbackRequest readbackRequest) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Frame = frame; ReadbackRequest = readbackRequest; } } public class RecorderAudioListener : Singleton<RecorderAudioListener> { private VideoRecorder m_videoRecorder; private void OnAudioFilterRead(float[] data, int channels) { try { if ((Object)(object)m_videoRecorder != (Object)null) { m_videoRecorder.AudioRead(data); } } catch (Exception ex) { Debug.Log((object)ex.ToString()); } } public void SendAudioTo(VideoRecorder recorder) { Debug.Log((object)("Setting camera to send audio to " + (((Object)(object)recorder == (Object)null) ? "null" : ((Object)recorder).name))); m_videoRecorder = recorder; } public void RemoveRecorder(VideoRecorder recorder) { if ((Object)(object)m_videoRecorder == (Object)(object)recorder) { m_videoRecorder = null; } } public void SendMic(float[] buffer, int sampleRate, int channels) { if ((Object)(object)m_videoRecorder != (Object)null) { m_videoRecorder.PushMicData(CanRecordMic() ? buffer : new float[buffer.Length], sampleRate, channels); } } public virtual bool CanRecordMic() { return true; } } public class RecordingPipe : IDisposable { private uint m_width; private uint m_height; private int m_frameCount; private Queue<PngEncodeJobHandle> m_encodePngJobHandles; private ProfilerMarker m_flushMarker = new ProfilerMarker("RecordingPipe.Flush"); private static string tempPath; private string path; private static string ErrorTitle; private static string ErrorBody; public DirectoryInfo GetDirectory() { return new DirectoryInfo(path); } public RecordingPipe(uint width, uint height, string directory) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) path = directory; m_width = width; m_height = height; m_frameCount = 0; if (GetDirectory().Exists) { GetDirectory().Delete(recursive: true); } m_encodePngJobHandles = new Queue<PngEncodeJobHandle>(3); } public void Dispose() { } public void Flush() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) AutoScope val = ((ProfilerMarker)(ref m_flushMarker)).Auto(); try { if (m_encodePngJobHandles.Count > 0 && ((JobHandle)(ref m_encodePngJobHandles.Peek().JobHandle)).IsCompleted) { FlushLastHandle(); } } finally { ((IDisposable)(AutoScope)(ref val)).Dispose(); } } private void FlushLastHandle() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) DirectoryInfo directory = GetDirectory(); PngEncodeJobHandle pngEncodeJobHandle = m_encodePngJobHandles.Dequeue(); ((JobHandle)(ref pngEncodeJobHandle.JobHandle)).Complete(); NativeList<byte> outputBuffer = pngEncodeJobHandle.OutputBuffer; byte[] array = new byte[outputBuffer.Length]; new NativeSlice<byte>(NativeList<byte>.op_Implicit(outputBuffer)).CopyTo(array); outputBuffer.Dispose(); string text = m_frameCount.ToString(); int num = 4; if (text.Length < num) { text = text.PadLeft(num, '0'); } string text2 = "Test" + text + ".png"; try { File.WriteAllBytes(directory.FullName + "/" + text2, array); } catch (IOException ex) when (ex.HResult == -2147024784) { Debug.LogException((Exception)ex); Debug.LogError((object)"Failed to write to disk due to the above exception"); ErrorTitle = "Disk full"; ErrorBody = "Recording failed due to full disk. Please clear out your disk and restart the game.\n" + ex.Message; } catch (Exception ex2) { Debug.LogException(ex2); Debug.LogError((object)"Failed to write to disk due to the above exception"); ErrorTitle = "Failed to write camera recording image to disk"; ErrorBody = ex2.ToString(); } m_frameCount++; } public void PushFrameData(NativeArray<byte> getData) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) DirectoryInfo directory = GetDirectory(); if (!directory.Exists) { directory.Create(); } NativeArray<byte> input = default(NativeArray<byte>); input..ctor(getData.Length, (Allocator)4, (NativeArrayOptions)1); NativeList<byte> val = default(NativeList<byte>); val..ctor(AllocatorHandle.op_Implicit((Allocator)4)); input.CopyFrom(getData); getData.Dispose(); EncodePngJob encodePngJob = default(EncodePngJob); encodePngJob.Input = input; encodePngJob.Output = val; encodePngJob.Width = m_width; encodePngJob.Height = m_height; EncodePngJob encodePngJob2 = encodePngJob; if (m_encodePngJobHandles.Count > 3) { FlushLastHandle(); } m_encodePngJobHandles.Enqueue(new PngEncodeJobHandle(IJobExtensions.Schedule<EncodePngJob>(encodePngJob2, default(JobHandle)), val)); } public static bool CheckErrorPopup(out string title, out string body) { title = ErrorTitle; body = ErrorBody; ErrorTitle = null; ErrorBody = null; return title != null; } } public class RecordingSession : IDisposable { private RecordingPipe m_pipe; private NativeList<float> m_audioData; private NativeList<float> m_micAudioData; private Material m_blitMaterial; private Queue<AsyncGPUReadbackRequest> _readbackQueue = new Queue<AsyncGPUReadbackRequest>(4); private ProfilerMarker m_processQueueMarker = new ProfilerMarker("RecordingSession.ProcessQueue"); private ProfilerMarker m_queueFrameMarker = new ProfilerMarker("RecordingSession.QueueFrame"); public int Frames { get; set; } public int AudioFrames { get; private set; } public int MicAudioFrames { get; private set; } public int AudioDataSize { get; set; } public int MicAudioDataSize { get; set; } public Optionable<int> MicSampleRate { get; set; } public Optionable<int> MicChannels { get; set; } public RecordingPipe Pipe => m_pipe; public RecordingSession(uint width, uint height, string directory) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) m_pipe = new RecordingPipe(width, height, directory); m_audioData = new NativeList<float>(100000, AllocatorHandle.op_Implicit((Allocator)4)); m_micAudioData = new NativeList<float>(100000, AllocatorHandle.op_Implicit((Allocator)4)); AudioFrames = 0; } public void PushFrame(RenderTexture frame) { if (m_pipe != null) { m_pipe.Flush(); ProcessQueue(); if ((Object)(object)frame != (Object)null) { QueueFrame(frame); } } } private void QueueFrame(RenderTexture frame) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) AutoScope val = ((ProfilerMarker)(ref m_queueFrameMarker)).Auto(); try { if (_readbackQueue.Count <= 6) { AsyncGPUReadbackRequest item = AsyncGPUReadback.Request((Texture)(object)frame, 0, (Action<AsyncGPUReadbackRequest>)null); _readbackQueue.Enqueue(item); } } finally { ((IDisposable)(AutoScope)(ref val)).Dispose(); } } private void ProcessQueue() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) AutoScope val = ((ProfilerMarker)(ref m_processQueueMarker)).Auto(); try { AsyncGPUReadbackRequest result; while (_readbackQueue.TryPeek(out result)) { if (!((AsyncGPUReadbackRequest)(ref result)).done) { bool flag = false; foreach (AsyncGPUReadbackRequest item in _readbackQueue) { AsyncGPUReadbackRequest current = item; flag |= ((AsyncGPUReadbackRequest)(ref current)).done; } if (!flag) { break; } ((AsyncGPUReadbackRequest)(ref result)).WaitForCompletion(); } _readbackQueue.Dequeue(); if (((AsyncGPUReadbackRequest)(ref result)).hasError) { Debug.LogError((object)"GPU readback error was detected."); continue; } m_pipe.PushFrameData(((AsyncGPUReadbackRequest)(ref result)).GetData<byte>(0)); Frames++; } } finally { ((IDisposable)(AutoScope)(ref val)).Dispose(); } } public void Dispose() { m_pipe?.Dispose(); m_audioData.Dispose(); m_micAudioData.Dispose(); } public void PushAudio(float[] data) { AudioDataSize = data.Length; for (int i = 0; i < data.Length; i++) { m_audioData.Add(ref data[i]); } AudioFrames++; } public byte[] GetAudioBlob() { //IL_0001: 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) NativeSlice<byte> val = new NativeSlice<float>(NativeList<float>.op_Implicit(m_audioData)).SliceConvert<byte>(); byte[] array = new byte[val.Length]; val.CopyTo(array); return array; } public byte[] GetMicAudioBlob() { //IL_0001: 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) NativeSlice<byte> val = new NativeSlice<float>(NativeList<float>.op_Implicit(m_micAudioData)).SliceConvert<byte>(); byte[] array = new byte[val.Length]; val.CopyTo(array); return array; } public string GetAudioPath() { return Pipe.GetDirectory()?.ToString() + "/audio.raw"; } public string GetMicAudioPath() { return Pipe.GetDirectory()?.ToString() + "/mic.raw"; } public void PushMicAudio(float[] data, int sampleRate, int channels) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) float num = 1.5f; if (MicSampleRate.IsNone) { MicSampleRate = Optionable<int>.Some(sampleRate); Debug.Log((object)("Setting sample rate to: " + MicSampleRate.Value)); } if (MicChannels.IsNone) { MicChannels = Optionable<int>.Some(channels); Debug.Log((object)("Setting channels to " + MicChannels.Value)); } MicAudioDataSize = data.Length; for (int i = 0; i < data.Length; i++) { ref NativeList<float> micAudioData = ref m_micAudioData; float num2 = data[i] * num; micAudioData.Add(ref num2); } MicAudioFrames++; } private float MicrophoneLevelMax(float[] data) { int num = 128; float num2 = 0f; for (int i = 0; i < num; i++) { float num3 = data[i] * data[i]; if (num2 < num3) { num2 = num3; } } return num2; } private float MicrophoneLevelMaxDecibels(float level) { return 20f * Mathf.Log10(Mathf.Abs(level)); } } public class RecordingsHandler : RetrievableSingleton<RecordingsHandler> { [CompilerGenerated] private sealed class <CheckIfClipIsComplete>d__26 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Clip clip; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckIfClipIsComplete>d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; if (!clip.local && !clip.hasBeenRecieved) { Debug.LogError((object)$"Clip chunk has not been recieved for {clip.clipID}, re-requesting..."); RetrievableSingleton<PhotonSendVideoHandler>.Instance.ClearChunksForClip(clip.clipID); CustomCommands<CustomCommandType>.SendPackage((CustomCommandPackage<CustomCommandType>)new ReRequestClipPackage { ClipID = clip.clipID, VideoHandle = clip.m_recording.videoHandle }, (ReceiverGroup)1); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <Encode>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Clip clip; public RecordingsHandler <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Encode>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; RecordingsHandler recordingsHandler = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; clip.encoded = false; <>2__current = recordingsHandler.m_encoder.Encode(24, FfmpegDeadline.Realtime, displayWindow: false, mic: true); <>1__state = 1; return true; case 1: { <>1__state = -1; if (recordingsHandler.m_encoder.ErrorTitle != null || recordingsHandler.m_encoder.ErrorBody != null) { PeakThings.Log.LogError((object)("Ffmpeg encoding error: " + recordingsHandler.m_encoder.ErrorTitle + " - " + recordingsHandler.m_encoder.ErrorBody)); } Debug.Log((object)"Encoding done!"); recordingsHandler.m_encoder = null; clip.encoded = true; DirectoryInfo directoryInfo = new DirectoryInfo(clip.GetClipDirectory()); Array.Empty<FileInfo>(); if (directoryInfo.Exists) { FileInfo[] files = directoryInfo.GetFiles("*.png"); for (int i = 0; i < files.Length; i++) { File.Delete(files[i].FullName); } } CustomCommands<CustomCommandType>.SendPackage((CustomCommandPackage<CustomCommandType>)new AddClipToShareQueuePackage { ClipID = clip.clipID, VideoHandle = clip.m_recording.videoHandle, ClipOwner = PhotonNetwork.LocalPlayer.ActorNumber, isReRequest = false }, (ReceiverGroup)1); return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ShareClipJob>d__7 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public RecordingsHandler <>4__this; public Clip clip; public bool isReRequest; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ShareClipJob>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; RecordingsHandler recordingsHandler = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = recordingsHandler.m_sendVideoHandler.SendVideoThroughPhoton(clip, isReRequest); <>1__state = 1; return true; case 1: <>1__state = -1; Debug.Log((object)$"Clip: {clip.clipID} has sent!"); CustomCommands<CustomCommandType>.SendPackage((CustomCommandPackage<CustomCommandType>)new SendClipCompletedPackage { ClipID = clip.clipID, VideoHandle = clip.m_recording.videoHandle }, (ReceiverGroup)1); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private Dictionary<VideoHandle, CameraRecording> m_recordings = new Dictionary<VideoHandle, CameraRecording>(); private BidirectionalDictionary<Guid, VideoHandle> m_camerasCurrentRecording = new BidirectionalDictionary<Guid, VideoHandle>(10); private BidirectionalDictionary<int, VideoHandle> m_playersRecording = new BidirectionalDictionary<int, VideoHandle>(10); private ListenerHandle startRecordingHandle = ListenerHandle.Invalid; private ListenerHandle stopRecordingHandle = ListenerHandle.Invalid; private ListenerHandle clipEncodedHandle = ListenerHandle.Invalid; private ListenerHandle activateNextSharingJobHandle = ListenerHandle.Invalid; private ListenerHandle sendClipCompletedHandle = ListenerHandle.Invalid; private ListenerHandle reRequestClipHandle = ListenerHandle.Invalid; private List<VideoClipShareJob> m_sharingQueue = new List<VideoClipShareJob>(); private VideoClipShareJob m_currentJob; private FfmpegEncoder m_encoder; private PhotonSendVideoHandler m_sendVideoHandler; private Dictionary<ClipID, int> m_clipRequestCount = new Dictionary<ClipID, int>(); protected override void OnCreated() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) base.OnCreated(); Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); m_clipRequestCount = new Dictionary<ClipID, int>(); startRecordingHandle = CustomCommands<CustomCommandType>.RegisterListener<StartRecordingCommandPackage>((Action<StartRecordingCommandPackage>)OnStartRecording); stopRecordingHandle = CustomCommands<CustomCommandType>.RegisterListener<StopRecordingCommandPackage>((Action<StopRecordingCommandPackage>)OnStopRecording); clipEncodedHandle = CustomCommands<CustomCommandType>.RegisterListener<AddClipToShareQueuePackage>((Action<AddClipToShareQueuePackage>)AddClipToShareQueue); activateNextSharingJobHandle = CustomCommands<CustomCommandType>.RegisterListener<ActivateNextSharingJobPackage>((Action<ActivateNextSharingJobPackage>)OnActivateNextSharingJob); sendClipCompletedHandle = CustomCommands<CustomCommandType>.RegisterListener<SendClipCompletedPackage>((Action<SendClipCompletedPackage>)SendIsComplete); reRequestClipHandle = CustomCommands<CustomCommandType>.RegisterListener<ReRequestClipPackage>((Action<ReRequestClipPackage>)OnReRequestClip); m_sendVideoHandler = RetrievableSingleton<PhotonSendVideoHandler>.Instance; DirectoryInfo directoryInfo = new DirectoryInfo(GetDirectory()); try { if (directoryInfo.Exists) { directoryInfo.Delete(recursive: true); } } catch (Exception ex) { Debug.LogError((object)("Failed to delete directory: " + directoryInfo.FullName + " " + ex.Message)); } directoryInfo.Create(); FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(directoryInfo.FullName); fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.Security; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.EnableRaisingEvents = true; fileSystemWatcher.Changed += OnFileSystemChanged; fileSystemWatcher.Created += OnFileSystemChanged; fileSystemWatcher.Deleted += OnFileSystemChanged; fileSystemWatcher.Renamed += OnRenamed; fileSystemWatcher.Error += OnFileSystemError; fileSystemWatcher.BeginInit(); } private void OnRenamed(object sender, RenamedEventArgs e) { Debug.Log((object)$"File Watcher Event: {e.ChangeType}, old name: {e.OldName}, new name: {e.Name}, fullpath: {e.FullPath}"); } private void OnFileSystemError(object sender, ErrorEventArgs e) { Debug.LogError((object)("File system error: " + e.GetException().Message)); } private void OnFileSystemChanged(object sender, FileSystemEventArgs e) { Debug.Log((object)$"File Watcher Event: {e.ChangeType}, name: {e.Name}, fullpath: {e.FullPath}"); } private void OnDestroy() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) CustomCommands<CustomCommandType>.UnregisterListener(startRecordingHandle); CustomCommands<CustomCommandType>.UnregisterListener(stopRecordingHandle); CustomCommands<CustomCommandType>.UnregisterListener(clipEncodedHandle); CustomCommands<CustomCommandType>.UnregisterListener(activateNextSharingJobHandle); CustomCommands<CustomCommandType>.UnregisterListener(sendClipCompletedHandle); CustomCommands<CustomCommandType>.UnregisterListener(reRequestClipHandle); } private void LateUpdate() { //IL_0348: Unknown result type (might be due to invalid IL or missing references) if (RecordingPipe.CheckErrorPopup(out string title, out string body)) { PeakThings.Log.LogError((object)("RecordingPipe error: " + title + " - " + body)); } HashSet<int> hashSet = PhotonNetwork.PlayerList.Select((Player player) => player.ActorNumber).ToHashSet(); foreach (CameraRecording value2 in m_recordings.Values) { int clipCount = value2.ClipCount; for (int i = 0; i < clipCount; i++) { Clip clip = value2.GetClip(i); if (!clip.local && !clip.hasBeenRecieved && clip.Valid && !hashSet.Contains(clip.ownerID)) { Debug.Log((object)("Player has left, clip " + clip.clipID.ToMiniString() + " is invalid...")); clip.SetValid(validClip: false); } } } if (PhotonNetwork.IsMasterClient && m_sharingQueue.Count > 0 && m_currentJob == null) { m_currentJob = m_sharingQueue[0]; m_sharingQueue.RemoveAt(0); CustomCommands<CustomCommandType>.SendPackage((CustomCommandPackage<CustomCommandType>)new ActivateNextSharingJobPackage { ClipID = m_currentJob.ClipID }, (ReceiverGroup)0); } VideoClipShareJob currentJob = m_currentJob; if (currentJob != null && currentJob.IsLocal && !currentJob.sending && PhotonNetwork.InRoom && m_recordings.TryGetValue(m_currentJob.VideoHandle, out CameraRecording value)) { PeakThings.Log.LogMessage((object)$"Starting share/send video clip job: {m_currentJob.ClipID.ToShortString()} for video {value.videoHandle.id}"); m_currentJob.sending = true; if (value.TryGetClip(m_currentJob.ClipID, out Clip clip2)) { ((MonoBehaviour)this).StartCoroutine(ShareClipJob(clip2, m_currentJob.isReRequest)); } else { Debug.LogError((object)$"Error: Current share/send video clip job references clip that doesn't exist: clip {m_currentJob.ClipID.id} in video {value.videoHandle.id}"); m_currentJob = null; } } if (m_encoder == null) { foreach (CameraRecording value3 in m_recordings.Values) { int clipCount2 = value3.ClipCount; for (int j = 0; j < clipCount2; j++) { Clip clip3 = value3.GetClip(j); if (clip3.local && !clip3.encoded && !clip3.isRecording && clip3.Valid) { PeakThings.Log.LogInfo((object)("Start encoding... " + clip3.clipID.ToMiniString())); m_encoder = new FfmpegEncoder(clip3.GetRecorder().Session); ((MonoBehaviour)this).StartCoroutine(Encode(clip3)); } } } } if (m_encoder != null || !Input.GetKeyDown(PeakThings.Instance.TempFileFolderKey.Value) || PeakThings.Instance.DisableFolderShortcuts.Value) { return; } Debug.Log((object)"F3 pressed"); foreach (CameraRecording value4 in m_recordings.Values) { if (ExtractRecording(value4)) { DirectoryInfo directoryInfo = new DirectoryInfo(value4.GetDirectory()); FileInfo[] files = directoryInfo.GetFiles(); if (files.Length != 0) { ShowExplorer(files.First().FullName); } else { ShowExplorer(directoryInfo.FullName); } } } static void ShowExplorer(string itemPath) { itemPath = itemPath.Replace("/", "\\"); Process.Start("explorer.exe", "/select," + itemPath); } } public bool ExtractRecording(CameraRecording recording) { if (!recording.ReadyToExtract(out string failureReason)) { Debug.LogWarning((object)("RecordingsHandler.ExtractRecording - ReadyToExtract false: " + failureReason)); return false; } int clipCount = recording.ClipCount; Clip[] source = (from clip in recording.GetAllClips() where clip.Valid select clip).ToArray(); Debug.Log((object)"All clips ready, starting stitching..."); if (clipCount == 1) { FileInfo fileInfo = new FileInfo(Path.Combine(recording.GetClip(0).GetClipDirectory(), "output.webm")); if (!fileInfo.Exists) { Debug.LogError((object)("No file found to stitch: " + fileInfo.FullName)); return false; } string text = Path.Combine(recording.GetDirectory(), "fullRecording.webm"); Debug.Log((object)("Copying file " + fileInfo.FullName + " to: " + text)); File.Copy(fileInfo.FullName, text, overwrite: true); } else { FFmpegStitcher.StichVideos(source.Select((Clip clip) => Path.Combine(clip.GetClipDirectory(), "output.webm")).ToArray(), recording.GetDirectory()); } return true; } [IteratorStateMachine(typeof(<ShareClipJob>d__7))] private IEnumerator ShareClipJob(Clip clip, bool isReRequest) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ShareClipJob>d__7(0) { <>4__this = this, clip = clip, isReRequest = isReRequest }; } [IteratorStateMachine(typeof(<Encode>d__8))] private IEnumerator Encode(Clip clip) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Encode>d__8(0) { <>4__this = this, clip = clip }; } private void OnStartRecording(StartRecordingCommandPackage package) { Guid cameraDataGuid = package.CameraDataGuid; VideoHandle videoID = package.VideoID; int cameraOwner = package.CameraOwner; ClipID clipID = package.ClipID; if (m_camerasCurrentRecording.ContainsKey(cameraDataGuid)) { Debug.LogError((object)"Camera is already recording"); return; } Guid guid = default(Guid); if (m_camerasCurrentRecording.TryGetValue(videoID, ref guid)) { Guid guid2 = guid; Debug.LogWarning((object)("Video ID is already in use by camera, stopping previous camera " + guid2)); OnStopRecording(guid, validClip: true); } if (videoID.Equals(VideoHandle.Invalid)) { Debug.LogError((object)$"Video ID is invalid, {videoID}"); return; } if (!m_recordings.TryGetValue(videoID, out CameraRecording value)) { m_recordings.Add(videoID, value = CreateNewRecording(videoID)); } m_camerasCurrentRecording.Add(cameraDataGuid, videoID); m_playersRecording.Add(cameraOwner, videoID); bool local = cameraOwner == PhotonNetwork.LocalPlayer.ActorNumber; Clip clip = new Clip(package.ClipID, local, cameraOwner, value); value.AddNewClip(clip); Debug.Log((object)$"Start recording, camera instance id:{cameraDataGuid}, video ID: {videoID}, clip ID: {clipID}"); if (clip.local) { if (CameraHandler.TryGetCamera(cameraDataGuid, out VideoCamera videoCamera)) { videoCamera.StartRecording(clip); } else { Debug.LogError((object)$"Failed to find VideoCamera with instance id {cameraDataGuid} to start recording local clip"); } } } private CameraRecording CreateNewRecording(VideoHandle entryVideoID) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) Guid id = entryVideoID.id; Debug.Log((object)("Creating new recording: " + id)); id = entryVideoID.id; CameraRecording cameraRecording = new GameObject("Recording: " + id).AddComponent<CameraRecording>(); ((Component)cameraRecording).transform.SetParent(((Component)this).transform); cameraRecording.SetInfo(entryVideoID); return cameraRecording; } private void OnStopRecording(StopRecordingCommandPackage package) { Guid cameraDataGuid = package.CameraDataGuid; OnStopRecording(cameraDataGuid, package.IsValidClip); } private void OnStopRecording(Guid instanceDataID, bool validClip) { if (!m_camerasCurrentRecording.ContainsKey(instanceDataID)) { Debug.LogWarning((object)"Camera is not recording any video... "); return; } VideoHandle fromKey = m_camerasCurrentRecording.GetFromKey(instanceDataID); m_camerasCurrentRecording.RemoveFromKey(instanceDataID); Clip clip = m_recordings[fromKey].EndCurrentClip(); clip.SetValid(validClip); if (m_playersRecording.Contains(fromKey)) { int num = m_playersRecording.Get(fromKey); m_playersRecording.RemoveFromValue(fromKey); PeakThings.Log.LogInfo((object)$"Removed player {num} from recording"); } if (clip.local) { if (CameraHandler.TryGetCamera(instanceDataID, out VideoCamera videoCamera)) { videoCamera.StopRecording(); } else { Debug.LogError((object)$"Failed to find VideoCamera with instance id {instanceDataID} to stop recording local clip"); } } Debug.Log((object)$"Stop recording, camera instance id:{instanceDataID}, video ID: {fromKey.id}, clip ID: {clip.clipID.id}"); } public void StartRecording(ItemInstanceData data, PhotonView playerView) { VideoInfoEntry videoInfoEntry = default(VideoInfoEntry); if (!data.TryGetDataEntry<VideoInfoEntry>((DataEntryKey)53, ref videoInfoEntry)) { Debug.LogError((object)"No VideoInfoEntry found in instance data"); return; } Guid guid = data.guid; if (videoInfoEntry.videoID.Equals(VideoHandle.Invalid)) { videoInfoEntry.videoID = new VideoHandle(Guid.NewGuid()); Debug.Log((object)$"Camera has no video ID, creating new video ID, {videoInfoEntry.videoID}"); } videoInfoEntry.isRecording = true; videoInfoEntry.SetDirty(); int num = -1; num = ((!((Object)(object)playerView != (Object)null)) ? FindFreePlayer() : playerView.OwnerActorNr); if (num == -1) { Debug.LogError((object)"No free player found to record camera..."); return; } if (RetrievableSingleton<RecordingsHandler>.Instance.m_playersRecording.ContainsKey(num)) { VideoHandle fromKey = RetrievableSingleton<RecordingsHandler>.Instance.m_playersRecording.GetFromKey(num); ItemInstanceData data2 = default(ItemInstanceData); if (RetrievableSingleton<RecordingsHandler>.Instance.m_camerasCurrentRecording.Contains(fromKey) && ItemInstanceDataHandler.TryGetInstanceData(RetrievableSingleton<RecordingsHandler>.Instance.m_camerasCurrentRecording.Get(fromKey), ref data2)) { StopRecording(data2); StartRecording(data2, null); } } StartRecordingCommandPackage startRecordingCommandPackage = new StartRecordingCommandPackage { CameraDataGuid = guid, VideoID = videoInfoEntry.videoID, ClipID = new ClipID(Guid.NewGuid()), CameraOwner = num }; OnStartRecording(startRecordingCommandPackage); CustomCommands<CustomCommandType>.SendPackage((CustomCommandPackage<CustomCommandType>)startRecordingCommandPackage, (ReceiverGroup)0); } private static int FindFreePlayer() { Player[] players = PhotonNetwork.PlayerList; int[] source = RetrievableSingleton<RecordingsHandler>.Instance.m_playersRecording.GetKeys().ToArray(); int i; for (i = 0; i < players.Length; i++) { if (!source.Any((int playerID) => playerID == players[i].ActorNumber)) { return players[i].ActorNumber; } } Debug.LogError((object)"No free player found to record camera..."); return -1; } public void StopRecording(ItemInstanceData data) { VideoInfoEntry videoInfoEntry = default(VideoInfoEntry); if (!data.TryGetDataEntry<VideoInfoEntry>((DataEntryKey)53, ref videoInfoEntry)) { Debug.LogError((object)"No VideoInfoEntry found in instance data"); return; } if (!TryGetRecording(videoInfoEntry.videoID, out CameraRecording recording)) { Guid id = videoInfoEntry.videoID.id; Debug.LogError((object)("No recording found with video ID: " + id)); return; } if (!recording.TryGetLatestClip(out Clip clip)) { Guid id2 = videoInfoEntry.videoID.id; Debug.LogError((object)("No clip found in recording: " + id2)); return; } bool isValidClip = true; VideoRecorder recorder = clip.GetRecorder(); if ((Object)(object)recorder == (Object)null) { Debug.LogError((object)("Failed to find recorder for clip: " + clip.clipID.ToShortString())); isValidClip = false; } else if (!recorder.HasRecorded) { Debug.LogError((object)"RecordingsHandler: CLIP HAS NO FRAMES!"); isValidClip = false; } videoInfoEntry.isRecording = false; videoInfoEntry.SetDirty(); Guid guid = data.guid; StopRecordingCommandPackage stopRecordingCommandPackage = new StopRecordingCommandPackage { CameraDataGuid = guid, IsValidClip = isValidClip }; OnStopRecording(stopRecordingCommandPackage); CustomCommands<CustomCommandType>.SendPackage((CustomCommandPackage<CustomCommandType>)stopRecordingCommandPackage, (ReceiverGroup)0); } public static Dictionary<VideoHandle, CameraRecording> GetRecordings() { return RetrievableSingleton<RecordingsHandler>.Instance.m_recordings; } public static BidirectionalDictionary<Guid, VideoHandle> GetCamerasCurrentRecording() { return RetrievableSingleton<RecordingsHandler>.Instance.m_camerasCurrentRecording; } public static BidirectionalDictionary<int, VideoHandle> GetPlayersRecording() { return RetrievableSingleton<RecordingsHandler>.Instance.m_playersRecording; } public static string GetDirectory() { return Path.Combine(Path.GetTempPath(), "rec"); } private void AddClipToShareQueue(AddClipToShareQueuePackage package) { VideoClipShareJob item = new VideoClipShareJob(package.VideoHandle, package.ClipID, package.ClipOwner, package.isReRequest); m_sharingQueue.Add(item); Debug.Log((object)$"Player {package.ClipOwner} encoded clip {package.ClipID}, added to sharing queue"); } public static List<VideoClipShareJob> GetSharingQueue() { return RetrievableSingleton<RecordingsHandler>.Instance.m_sharingQueue; } public static VideoClipShareJob GetCurrentSharingJob() { return RetrievableSingleton<RecordingsHandler>.Instance.m_currentJob; } private void OnActivateNextSharingJob(ActivateNextSharingJobPackage package) { if (m_sharingQueue[0].ClipID.Equals(package.ClipID)) { m_currentJob = m_sharingQueue[0]; m_sharingQueue.RemoveAt(0); } else { Debug.LogError((object)"FATAL SHARING ERROR. Clip ID's do not match, JOBS ARE NOW WRONG VERY BAD..."); } } private void SendIsComplete(SendClipCompletedPackage package) { PeakThings.Log.LogMessage((object)("Received clip is complete package: " + package.ClipID.ToShortString())); ClipID clipID = package.ClipID; if (TryGetRecording(package.VideoHandle, out CameraRecording recording) && recording.TryGetClip(clipID, out Clip clip)) { ((MonoBehaviour)this).StartCoroutine(CheckIfClipIsComplete(clip)); } if (PhotonNetwork.IsMasterClient) { if (m_currentJob == null) { Debug.LogError((object)"No current job to check"); } else if (m_currentJob.ClipID.Equals(package.ClipID))