Decompiled source of Flashcard Fixed v0.3.4

plugins/me.loaforc.Flashcard.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Flashcard.Config;
using Flashcard.Networking;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MyceliumNetworking;
using Photon.Pun;
using PlayEveryWare.VideoEncoding;
using Steamworks;
using Unity.Collections;
using UnityEngine;
using Zorro.Core.Serizalization;
using Zorro.PhotonUtility;
using Zorro.Recorder;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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]
	[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 Flashcard
{
	[BepInPlugin("me.loaforc.Flashcard", "Flashcard", "0.3.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class FlashcardPlugin : BaseUnityPlugin
	{
		internal static uint networkID = 102873u;

		public static FlashcardPlugin Instance { get; private set; } = null;

		internal static ManualLogSource Logger { get; private set; } = null;

		internal static Harmony Harmony { get; private set; } = null;

		internal static FlashcardConfig config { get; private set; } = null;

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Logger.LogInfo((object)"Initing Config.");
			config = new FlashcardConfig(((BaseUnityPlugin)this).Config);
			Logger.LogInfo((object)"Running Harmony Patches");
			Harmony = new Harmony("me.loaforc.Flashcard");
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
			foreach (Type type in typesFromAssembly)
			{
				if (((MemberInfo)type).GetCustomAttribute<HarmonyPatch>() != null)
				{
					try
					{
						Harmony.CreateClassProcessor(type).Patch();
					}
					catch (Exception arg)
					{
						Logger.LogError((object)$"Failed to apply {type.Name}: {arg}");
					}
				}
			}
			if (config.RECORDING_CLIP_FRAMERATE.Value != RecordingConstants.VIDEO_FRAME_RATE)
			{
				Logger.LogWarning((object)$"ClipFramerate is not supported by the game's new video encoder, recording at {RecordingConstants.VIDEO_FRAME_RATE} fps");
			}
			Logger.LogInfo((object)"Setting up FlashcardVideoUploader");
			new FlashcardVideoUploader();
			Logger.LogInfo((object)"me.loaforc.Flashcard:0.3.4 has loaded!");
			LogVerbose("Awake", "Flashcard loaded with verbose logging!");
		}

		internal static void LogVerbose(string origin, string message)
		{
			if (config.DEBUGGING_VERBOSE_LOGGING.Value)
			{
				Logger.LogInfo((object)("[" + origin + "] " + message));
			}
		}
	}
}
namespace Flashcard.Patches
{
	[HarmonyPatch(typeof(LibVEInitializer), "GetNewVeConfig")]
	internal static class EncoderConfigPatch
	{
		[HarmonyPostfix]
		private static void UpdateBitrate(ref ve_config __result)
		{
			uint? num = ParseQuality(FlashcardPlugin.config.RECORDING_CLIP_QUALITY.Value);
			if (num.HasValue)
			{
				__result.target_bitrate = num.Value;
				FlashcardPlugin.LogVerbose("Encoder", $"Target bitrate set to {num.Value} kbit/s");
			}
		}

		private static uint? ParseQuality(string value)
		{
			string text = value.Trim().ToLowerInvariant();
			if (text == "")
			{
				return null;
			}
			uint num = 1u;
			if (text.EndsWith("m"))
			{
				num = 1000u;
				text = text.Substring(0, text.Length - 1);
			}
			else if (text.EndsWith("k"))
			{
				text = text.Substring(0, text.Length - 1);
			}
			if (uint.TryParse(text, out var result) && result != 0)
			{
				return result * num;
			}
			FlashcardPlugin.Logger.LogError((object)("Invalid clip quality: " + value));
			return null;
		}
	}
	[HarmonyPatch(typeof(PhotonSendVideoHandler))]
	internal class PhotonSendVideoHandlerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("SendVideoThroughPhoton")]
		internal static void ReallyReallyForceVideoSharingOverSteamNetwork(PhotonSendVideoHandler __instance, ref bool isReRequest)
		{
			isReRequest = false;
			__instance.m_UseSteamNetwork = true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("RecieveClipChunk")]
		internal static void LogRecieveClipChunk(SendVideoChunkPackage package)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			FlashcardPlugin.LogVerbose("RecieveClipChunk", $"Recieved a chunk of a video! Chunk '{package.ChunkIndex}' for clip '{package.ClipID}'");
		}

		[HarmonyPostfix]
		[HarmonyPatch("SendVideoChunks")]
		internal static void FlashcardSendVideoChunks(ref IEnumerator __result, List<byte[]> videoChunks, ClipID clipID, VideoHandle videoID, ContentBuffer contentBuffer, bool isReRequest)
		{
			//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)
			__result = FlashcardVideoUploader.Instance.SendVideoChunks(videoChunks, clipID, videoID, contentBuffer, isReRequest);
		}
	}
	[HarmonyPatch(typeof(RecordingsHandler))]
	internal static class RecordingHandlerPatch
	{
		[HarmonyPatch("StartRecording")]
		[HarmonyPostfix]
		private static void LogStartRecording()
		{
			FlashcardPlugin.LogVerbose("RecordingHandlerPatch", "RecordingsHandler.StartRecording!!!");
		}
	}
	[HarmonyPatch(typeof(SurfaceNetworkHandler))]
	internal static class SurfaceNetworkHandlerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("InitSurface")]
		internal static void SpawnOnStartRun(SurfaceNetworkHandler __instance)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				SpawnExtraCamera(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnSlept")]
		internal static void SpawnOnNewDay(SurfaceNetworkHandler __instance)
		{
			if (PhotonNetwork.IsMasterClient && Object.FindObjectsOfType<VideoCamera>().Length < 2)
			{
				SpawnExtraCamera(__instance);
			}
		}

		private static void SpawnExtraCamera(SurfaceNetworkHandler handler)
		{
			//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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_0073: 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_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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.IsMasterClient && !(FlashcardPlugin.config.UPGRADES_EXTRA_CAMERA.Value == "disabled"))
			{
				FlashcardPlugin.Logger.LogInfo((object)"Spawning extra camera!");
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(-14.842f, 2.418f, 8.776f);
				Quaternion val2 = Quaternion.Euler(0f, -67.18f, 0f);
				PickupSpawner videoCameraSpawner = handler.m_VideoCameraSpawner;
				if ((Object)(object)videoCameraSpawner != (Object)null)
				{
					val = ((Component)videoCameraSpawner).transform.position - ((Component)videoCameraSpawner).transform.right * 0.4f;
					val2 = ((Component)videoCameraSpawner).transform.rotation;
				}
				PickupHandler.CreatePickup((byte)1, new ItemInstanceData(Guid.NewGuid()), val, val2);
			}
		}
	}
	[HarmonyPatch(typeof(VideoCamera))]
	public class VideoCameraPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch("ConfigItem")]
		private static IEnumerable<CodeInstruction> UpdateFilmAmount(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo objB = AccessTools.Field(typeof(VideoInfoEntry), "timeLeft");
			FieldInfo objB2 = AccessTools.Field(typeof(VideoInfoEntry), "maxTime");
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = 0;
			for (int i = 0; i + 1 < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_R4 && list[i].operand is float num2 && num2 == 90f && list[i + 1].opcode == OpCodes.Stfld && (object.Equals(list[i + 1].operand, objB) || object.Equals(list[i + 1].operand, objB2)))
				{
					list[i].operand = FlashcardPlugin.config.RECORDING_CLIP_LENGTH.Value;
					num++;
				}
			}
			if (num != 2)
			{
				FlashcardPlugin.Logger.LogWarning((object)$"ClipLength: expected 2 film length values in VideoCamera.ConfigItem, replaced {num}");
			}
			return list;
		}
	}
}
namespace Flashcard.Networking
{
	internal class FlashcardVideoUploader
	{
		internal static FlashcardVideoUploader Instance;

		private uint NetworkID => FlashcardPlugin.networkID;

		internal FlashcardVideoUploader()
		{
			MyceliumNetwork.RegisterNetworkObject((object)this, NetworkID, 0);
			Instance = this;
		}

		internal IEnumerator SendVideoChunks(List<byte[]> videoChunks, ClipID clipID, VideoHandle videoID, ContentBuffer contentBuffer, bool isReRequest)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			FlashcardPlugin.LogVerbose("Uploading", $"Sending Video Chunks! VideoID: {clipID.id}");
			for (ushort chunkIndex = 0; chunkIndex < videoChunks.Count; chunkIndex++)
			{
				SendVideoChunkPackage val = new SendVideoChunkPackage
				{
					ChunkCount = (ushort)videoChunks.Count,
					VideoChunkData = videoChunks[chunkIndex],
					ChunkIndex = chunkIndex,
					VideoHandle = videoID,
					ClipID = clipID
				};
				BinarySerializer val2 = null;
				if (chunkIndex == 0)
				{
					val2 = new BinarySerializer(512, (Allocator)4);
					contentBuffer.Serialize(val2);
					val.ContentEventData = val2.buffer;
				}
				BinarySerializer val3 = ((CustomCommandPackage<CustomCommandType>)(object)val).Serialize();
				byte[] array;
				try
				{
					array = val3.buffer.ToArray();
				}
				finally
				{
					((IDisposable)val3)?.Dispose();
				}
				if (val2 != null)
				{
					val2.Dispose();
				}
				CSteamID[] players = MyceliumNetwork.Players;
				foreach (CSteamID val4 in players)
				{
					if (val4 != SteamUser.GetSteamID())
					{
						MyceliumNetwork.RPCTarget(NetworkID, "RPC_RecieveChunk", val4, (ReliableType)1, new object[1] { array });
					}
				}
				FlashcardPlugin.LogVerbose("Uploading", $"Uploaded a chunk! VideoID: {clipID.id}, chunkIndex: {chunkIndex}");
				yield return (object)new WaitForSeconds(FlashcardPlugin.config.UPLOADING_DELAY_BETWEEN_PACKETS.Value);
			}
		}

		[CustomRPC]
		private void RPC_RecieveChunk(byte[] data)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			FlashcardPlugin.LogVerbose("Uploading", "Recieved Video Chunk! Deserializing and giving it back to PhotonSendVideoHandler.");
			BinaryDeserializer val = new BinaryDeserializer(new NativeArray<byte>(data, (Allocator)2));
			SendVideoChunkPackage val2 = new SendVideoChunkPackage();
			((CustomCommandPackage<CustomCommandType>)(object)val2).DeserializeData(val);
			val.Dispose();
			RetrievableSingleton<PhotonSendVideoHandler>.Instance.RecieveClipChunk(val2);
		}
	}
}
namespace Flashcard.Config
{
	internal class FlashcardConfig
	{
		internal ConfigEntry<string> UPGRADES_EXTRA_CAMERA;

		internal ConfigEntry<float> RECORDING_CLIP_LENGTH;

		internal ConfigEntry<int> RECORDING_CLIP_FRAMERATE;

		internal ConfigEntry<string> RECORDING_CLIP_QUALITY;

		internal ConfigEntry<float> UPLOADING_DELAY_BETWEEN_PACKETS;

		internal ConfigEntry<bool> DEBUGGING_VERBOSE_LOGGING;

		internal FlashcardConfig(ConfigFile cfgFile)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			UPGRADES_EXTRA_CAMERA = cfgFile.Bind<string>("Upgrades", "ExtraCamera", "disabled", new ConfigDescription("Should allow the Extra Camera Upgrade?", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "disabled", "always" }), Array.Empty<object>()));
			RECORDING_CLIP_LENGTH = cfgFile.Bind<float>("Recording", "ClipLength", 120f, "How many seconds should the camera be allowed to record?\nContentWarning's default is 90.");
			RECORDING_CLIP_FRAMERATE = cfgFile.Bind<int>("Recording", "ClipFramerate", 24, "Not supported by the game's current video encoder; the game always records at 24 fps.");
			RECORDING_CLIP_QUALITY = cfgFile.Bind<string>("Recording", "ClipQuality", "512k", "Target video bitrate, e.g. 512k or 1M. The game's default is 25k.\nHigher values look better but make clips bigger and slower to share.\nSet to empty to keep the game's default.");
			UPLOADING_DELAY_BETWEEN_PACKETS = cfgFile.Bind<float>("Uploading", "DelayBetweenPackets", 0.5f, "The delay between the packets for video chunk data being sent.");
			DEBUGGING_VERBOSE_LOGGING = cfgFile.Bind<bool>("Debugging", "VerboseLogging", false, "Whether flashcard should increase it's logs. Useful for debugging issues.");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}