Decompiled source of WeeklyRecap v1.0.1

plugins/ElfDevelop.WeeklyRecap.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.SceneManagement;

[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 WeeklyRecap
{
	[ContentWarningPlugin("ElfDevelop.WeeklyRecap", "1.0.1", true)]
	[BepInPlugin("ElfDevelop.WeeklyRecap", "WeeklyRecap", "1.0.1")]
	public class WeeklyRecapPlugin : BaseUnityPlugin
	{
		internal static WeekStats Week = new WeekStats();

		private static string? roomName;

		private static (int Week, bool Reached, WeekStats Stats)? pendingRecap;

		private static readonly Dictionary<string, float> lastDeath = new Dictionary<string, float>();

		private float nextPlayerScan;

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

		internal static WeeklyRecapPlugin Instance { get; private set; } = null;

		internal static bool IsRussian
		{
			get
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					Locale selectedLocale = LocalizationSettings.SelectedLocale;
					object obj;
					if (selectedLocale == null)
					{
						obj = null;
					}
					else
					{
						LocaleIdentifier identifier = selectedLocale.Identifier;
						obj = ((LocaleIdentifier)(ref identifier)).Code;
					}
					return ((string)obj)?.StartsWith("ru") ?? false;
				}
				catch
				{
					return false;
				}
			}
		}

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			new Harmony("ElfDevelop.WeeklyRecap").PatchAll();
			SceneManager.sceneLoaded += OnSceneLoaded;
			Logger.LogInfo((object)"WeeklyRecap 1.0.1 has loaded!");
		}

		private void Update()
		{
			if (Time.unscaledTime < nextPlayerScan)
			{
				return;
			}
			nextPlayerScan = Time.unscaledTime + 5f;
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			if (roomName != PhotonNetwork.CurrentRoom.Name)
			{
				roomName = PhotonNetwork.CurrentRoom.Name;
				Week = new WeekStats();
				pendingRecap = null;
			}
			if ((Object)(object)PlayerHandler.instance == (Object)null)
			{
				return;
			}
			foreach (Player player in PlayerHandler.instance.players)
			{
				if ((Object)(object)player != (Object)null && !player.ai)
				{
					Week.SeePlayer(NameOf(player));
				}
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "SurfaceScene" && pendingRecap.HasValue)
			{
				(int Week, bool Reached, WeekStats Stats) value = pendingRecap.Value;
				int item = value.Week;
				bool item2 = value.Reached;
				WeekStats item3 = value.Stats;
				pendingRecap = null;
				((MonoBehaviour)this).StartCoroutine(ShowAfter(4f, item, item2, item3));
			}
		}

		internal static void CountDeath(string name)
		{
			float unscaledTime = Time.unscaledTime;
			if (!lastDeath.TryGetValue(name, out var value) || !(unscaledTime - value < 2f))
			{
				lastDeath[name] = unscaledTime;
				Week.AddDeath(name);
			}
		}

		internal static string NameOf(Player player)
		{
			PlayerRefs refs = player.refs;
			object obj;
			if (refs == null)
			{
				obj = null;
			}
			else
			{
				PhotonView view = refs.view;
				if (view == null)
				{
					obj = null;
				}
				else
				{
					Player owner = view.Owner;
					obj = ((owner != null) ? owner.NickName : null);
				}
			}
			string text = (string)obj;
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return ((Object)player).name;
		}

		internal static string NameOfActor(int actorNumber)
		{
			Room currentRoom = PhotonNetwork.CurrentRoom;
			object obj;
			if (currentRoom == null)
			{
				obj = null;
			}
			else
			{
				Player player = currentRoom.GetPlayer(actorNumber, false);
				obj = ((player != null) ? player.NickName : null);
			}
			string text = (string)obj;
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			if (!IsRussian)
			{
				return $"Player {actorNumber}";
			}
			return $"Игрок {actorNumber}";
		}

		internal static void WeekEnded(int week, bool reached)
		{
			WeekStats week2 = Week;
			Week = new WeekStats();
			if (reached)
			{
				((MonoBehaviour)Instance).StartCoroutine(Instance.ShowAfter(4f, week, reached: true, week2));
			}
			else
			{
				pendingRecap = (week, false, week2);
			}
		}

		private IEnumerator ShowAfter(float seconds, int week, bool reached, WeekStats stats)
		{
			yield return (object)new WaitForSecondsRealtime(seconds);
			bool isRussian = IsRussian;
			string text = stats.BuildTitle(week, reached, isRussian);
			string text2 = stats.BuildBody(isRussian, (Func<int, string>)BigNumbers.ViewsToString);
			Logger.LogInfo((object)(text + "\n" + text2));
			SaveToHistory(text, text2);
			Modal.Show(text, text2, (ModalOption[])(object)new ModalOption[1]
			{
				new ModalOption(LocalizationKeys.GetLocalizedString((Keys)121), (Action)null)
			}, (Action)null);
		}

		private static void SaveToHistory(string title, string body)
		{
			try
			{
				File.AppendAllText(Path.Combine(Paths.BepInExRootPath, "WeeklyRecaps.txt"), $"{DateTime.Now:yyyy-MM-dd HH:mm} {title}\n{body}\n\n");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Can't save the recap to WeeklyRecaps.txt: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Player))]
	internal static class PlayerPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("RPCA_PlayerDie")]
		private static void Died(Player __instance)
		{
			if (!__instance.ai)
			{
				WeeklyRecapPlugin.CountDeath(WeeklyRecapPlugin.NameOf(__instance));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("RPCA_PlayerRevive")]
		private static void Revived(Player __instance)
		{
			if (!__instance.ai && !PhotonGameLobbyHandler.IsSurface)
			{
				WeeklyRecapPlugin.Week.AddRevive(WeeklyRecapPlugin.NameOf(__instance));
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("TakeDamage")]
		private static void Damaged(Player __instance, float damage)
		{
			if (!__instance.ai && !__instance.data.dead)
			{
				WeeklyRecapPlugin.Week.AddDamage(WeeklyRecapPlugin.NameOf(__instance), damage);
			}
		}
	}
	[HarmonyPatch]
	internal static class WeekPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(UploadVideoStation), "RPC_OnEvaluationComplete")]
		private static void VideoUploaded(float score, byte[] videoHandleData)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				VideoHandle val = default(VideoHandle);
				((VideoHandle)(ref val))..ctor(new Guid(videoHandleData));
				int currentDay = GameAPI.CurrentDay;
				int scoreToViews = BigNumbers.GetScoreToViews(score, currentDay);
				List<(string, float)> list = new List<(string, float)>();
				CameraRecording val2 = default(CameraRecording);
				if (RecordingsHandler.TryGetRecording(val, ref val2))
				{
					bool flag = BitConverter.ToInt32(val.id.ToByteArray(), 0) == int.MaxValue;
					ContentBuffer val3 = default(ContentBuffer);
					foreach (Clip allClip in val2.GetAllClips())
					{
						if (!allClip.Valid || !allClip.TryGetContentBuffer(ref val3))
						{
							continue;
						}
						string text = ((!flag) ? WeeklyRecapPlugin.NameOfActor(allClip.ownerID) : (WeeklyRecapPlugin.IsRussian ? "найденная камера" : "found camera"));
						list.Add((text, val3.GetScore()));
						foreach (BufferedContent item in val3.buffer)
						{
							ContentEvent contentEvent = item.frame.contentEvent;
							string text2 = ((contentEvent != null) ? contentEvent.GetName() : null);
							if (text2 != null)
							{
								WeeklyRecapPlugin.Week.AddMoment(text, text2, item.score, BigNumbers.GetScoreToViews(item.score, currentDay));
							}
						}
					}
				}
				WeeklyRecapPlugin.Week.AddVideo(scoreToViews, list);
			}
			catch (Exception ex)
			{
				WeeklyRecapPlugin.Logger.LogError((object)("Failed to count the uploaded video: " + ex));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SurfaceNetworkHandler), "RPCA_OnNewWeek")]
		private static void NewWeek(int currentRun)
		{
			WeeklyRecapPlugin.WeekEnded(Mathf.Max(1, currentRun), reached: true);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SurfaceNetworkHandler), "RPC_QuotaFailed")]
		private static void QuotaFailed()
		{
			WeeklyRecapPlugin.WeekEnded(((SurfaceNetworkHandler.RoomStats != null) ? SurfaceNetworkHandler.RoomStats.CurrentRun : 0) + 1, reached: false);
		}
	}
	internal class PlayerStats
	{
		public string Name = "";

		public int Deaths;

		public int Revives;

		public float Damage;

		public float FilmedScore;

		public int FilmedViews;
	}
	internal class WeekStats
	{
		private readonly Dictionary<string, PlayerStats> players = new Dictionary<string, PlayerStats>();

		private readonly Dictionary<string, float> eventScores = new Dictionary<string, float>();

		public int Videos { get; private set; }

		public int TotalViews { get; private set; }

		public string? BestShotOperator { get; private set; }

		public string? BestShotEvent { get; private set; }

		public int BestShotViews { get; private set; }

		public bool IsEmpty
		{
			get
			{
				if (Videos == 0)
				{
					return players.Values.All((PlayerStats p) => p.Deaths == 0 && p.Revives == 0 && p.Damage <= 0f);
				}
				return false;
			}
		}

		public PlayerStats Player(string name)
		{
			if (!players.TryGetValue(name, out PlayerStats value))
			{
				Dictionary<string, PlayerStats> dictionary = players;
				PlayerStats obj = new PlayerStats
				{
					Name = name
				};
				value = obj;
				dictionary[name] = obj;
			}
			return value;
		}

		public void SeePlayer(string name)
		{
			Player(name);
		}

		public void AddDeath(string name)
		{
			Player(name).Deaths++;
		}

		public void AddRevive(string name)
		{
			Player(name).Revives++;
		}

		public void AddDamage(string name, float damage)
		{
			if (damage > 0f)
			{
				Player(name).Damage += damage;
			}
		}

		public void AddVideo(int views, IList<(string Operator, float Score)> clips)
		{
			Videos++;
			TotalViews += Math.Max(0, views);
			float num = clips.Sum<(string, float)>(((string Operator, float Score) c) => Math.Max(0f, c.Score));
			foreach (var clip in clips)
			{
				PlayerStats playerStats = Player(clip.Operator);
				float num2 = Math.Max(0f, clip.Score);
				playerStats.FilmedScore += num2;
				if (num > 0f)
				{
					playerStats.FilmedViews += (int)Math.Round((float)views * (num2 / num));
				}
			}
		}

		public void AddMoment(string operatorName, string eventName, float score, int views)
		{
			if (!string.IsNullOrEmpty(eventName) && !(score <= 0f))
			{
				eventScores[eventName] = (eventScores.TryGetValue(eventName, out var value) ? (value + score) : score);
				if (BestShotEvent == null || views > BestShotViews)
				{
					BestShotOperator = operatorName;
					BestShotEvent = eventName;
					BestShotViews = views;
				}
			}
		}

		public string BuildTitle(int week, bool quotaReached, bool russian)
		{
			if (russian)
			{
				if (!quotaReached)
				{
					return $"ИТОГИ НЕДЕЛИ {week}: КВОТА ПРОВАЛЕНА";
				}
				return $"ИТОГИ НЕДЕЛИ {week}";
			}
			if (!quotaReached)
			{
				return $"WEEK {week} RECAP: QUOTA FAILED";
			}
			return $"WEEK {week} RECAP";
		}

		public string BuildBody(bool russian, Func<int, string> formatViews)
		{
			List<string> list = new List<string>();
			list.Add(T($"Videos: {Videos}, views: {formatViews(TotalViews)}", $"Видео: {Videos}, просмотров: {formatViews(TotalViews)}"));
			PlayerStats playerStats = (from p in players.Values
				where p.FilmedViews > 0
				orderby p.FilmedViews descending
				select p).FirstOrDefault();
			if (playerStats != null)
			{
				list.Add(T("Best camera operator: " + playerStats.Name + " (" + formatViews(playerStats.FilmedViews) + " views)", "Лучший оператор: " + playerStats.Name + " (" + formatViews(playerStats.FilmedViews) + " просмотров)"));
			}
			if (BestShotEvent != null)
			{
				list.Add(T("Shot of the week: " + BestShotEvent + " by " + BestShotOperator + " (+" + formatViews(BestShotViews) + ")", "Кадр недели: " + BestShotEvent + ", снял " + BestShotOperator + " (+" + formatViews(BestShotViews) + ")"));
			}
			if (eventScores.Count > 0)
			{
				string key = eventScores.OrderByDescending<KeyValuePair<string, float>, float>((KeyValuePair<string, float> e) => e.Value).First().Key;
				list.Add(T("Most filmed: " + key, "Чаще всего в кадре: " + key));
			}
			PlayerStats playerStats2 = (from p in players.Values
				where p.Deaths > 0
				orderby p.Deaths descending
				select p).FirstOrDefault();
			if (playerStats2 != null)
			{
				list.Add(T($"Died the most: {playerStats2.Name} ({playerStats2.Deaths})", $"Чаще всех умирал: {playerStats2.Name} ({playerStats2.Deaths})"));
			}
			PlayerStats playerStats3 = (from p in players.Values
				where p.Damage >= 1f
				orderby p.Damage descending
				select p).FirstOrDefault();
			if (playerStats3 != null)
			{
				string text = Math.Round(playerStats3.Damage).ToString(CultureInfo.InvariantCulture);
				list.Add(T("Took the most damage: " + playerStats3.Name + " (" + text + ")", "Больше всех получил урона: " + playerStats3.Name + " (" + text + ")"));
			}
			PlayerStats playerStats4 = (from p in players.Values
				where p.Revives > 0
				orderby p.Revives descending
				select p).FirstOrDefault();
			if (playerStats4 != null)
			{
				list.Add(T($"Revived the most: {playerStats4.Name} ({playerStats4.Revives})", $"Чаще всех воскресал: {playerStats4.Name} ({playerStats4.Revives})"));
			}
			List<string> list2 = (from p in players.Values
				where p.Deaths == 0
				select p.Name).OrderBy<string, string>((string n) => n, StringComparer.CurrentCultureIgnoreCase).ToList();
			if (list2.Count > 0 && list2.Count < players.Count)
			{
				list.Add(T("Never died: " + string.Join(", ", list2), "Ни разу не умер: " + string.Join(", ", list2)));
			}
			else if (list2.Count > 0 && players.Count > 0)
			{
				list.Add(T("Nobody died this week", "За неделю никто не умер"));
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in list)
			{
				stringBuilder.AppendLine(item);
			}
			return stringBuilder.ToString().TrimEnd();
			string T(string en, string ru)
			{
				if (!russian)
				{
					return en;
				}
				return ru;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}