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)
{
}
}
}