using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using HighQuotaHelper;
using HighQuotaStatTracking;
using HighQuotaStatTracking.Patches;
using Microsoft.CodeAnalysis;
using StaticNetcodeLib;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HighQuotaStatTracking")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f8e0d6d247ebb0f9f817b92e848fb1996e03cf88")]
[assembly: AssemblyProduct("My first plugin")]
[assembly: AssemblyTitle("HighQuotaStatTracking")]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace HighQuotaHelper
{
[StaticNetcode]
public class NetworkRPC
{
public delegate void ReceivedStats(ClientPlayer player);
public delegate void ReceivedPickupItem(ulong networkID, ulong steamID);
public delegate void ReceivedLog(string displayName, ulong steamID, LogLevel logLevel, string message, bool logOnServer);
public static event ReceivedStats OnReceivedStats;
public static event ReceivedPickupItem OnReceivedPickupItem;
public static event ReceivedLog OnReceivedLog;
[ServerRpc(RequireOwnership = false)]
public static void ReportStatsServerRpc(ClientPlayer playerStats)
{
if (NetworkRPC.OnReceivedStats != null)
{
NetworkRPC.OnReceivedStats(playerStats);
}
}
[ServerRpc(RequireOwnership = false)]
public static void ReportPickedUpObjectServerRpc(ulong networkID, ulong steamID)
{
if (NetworkRPC.OnReceivedPickupItem != null)
{
NetworkRPC.OnReceivedPickupItem(networkID, steamID);
}
}
[ServerRpc(RequireOwnership = false)]
public static void LogServerRpc(string displayName, ulong steamID, LogLevel logLevel, string message, bool logOnServer)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
if (NetworkRPC.OnReceivedLog != null)
{
NetworkRPC.OnReceivedLog(displayName, steamID, logLevel, message, logOnServer);
}
}
}
}
namespace HighQuotaStatTracking
{
public class ClientPlayer
{
public ulong SteamID { get; set; }
public DateTime? DiedTime { get; set; }
public ushort Jumps { get; set; }
public short DoorsOpened { get; set; }
public float DistanceTraveled { get; set; }
public float DistanceJetpacked { get; set; }
public float DistanceCrouched { get; set; }
public float DistanceSprinted { get; set; }
public float DistanceWalked { get; set; }
public float DistanceLaddered { get; set; }
public float DistanceCruisered { get; set; }
public TimeSpan TotalWalkieTime { get; set; }
public float TotalFlashlightTime { get; set; }
public ushort DamageTaken { get; set; }
public float TotalStamina { get; set; }
public int StaminaCounts { get; set; }
public float TimeSpentAbove19PoundsInside { get; set; }
public float TZPHighTime { get; set; }
public Dictionary<ulong, DateTime> ObtainedItems { get; set; } = new Dictionary<ulong, DateTime>();
}
[BepInPlugin("HighQuotaStatTracking", "High Quota Stat Tracking", "1.12.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "HighQuotaStatTracking";
public const string PluginName = "High Quota Stat Tracking";
public const string PluginVersion = "1.12.1";
internal static ManualLogSource LogSource;
private readonly Harmony harmony = new Harmony("HighQuotaStatTracking");
private void Awake()
{
LogSource = ((BaseUnityPlugin)this).Logger;
LogSource.LogInfo((object)"Plugin HighQuotaStatTracking is loaded!");
harmony.PatchAll(typeof(StartOfRoundPatch));
harmony.PatchAll(typeof(PlayerControllerBPatch));
harmony.PatchAll(typeof(WalkieTalkiePatch));
harmony.PatchAll(typeof(DoorLockPatch));
harmony.PatchAll(typeof(BeltBagItemPatch));
harmony.PatchAll(typeof(VehicleControllerPatch));
LogSource.LogInfo((object)"Patched");
}
}
public class StatManager
{
private static StatManager _instance;
public static StatManager Instance
{
get
{
if (_instance == null)
{
_instance = new StatManager();
}
return _instance;
}
}
public bool IsOnMoon { get; private set; }
public ClientPlayer LocalPlayer { get; private set; }
public DateTime LandedTime { get; private set; }
public void ResetLocalPlayer()
{
LocalPlayer = new ClientPlayer
{
SteamID = GameNetworkManager.Instance.localPlayerController.playerSteamId
};
}
public void StartRound()
{
ResetLocalPlayer();
IsOnMoon = true;
LandedTime = DateTime.UtcNow;
GrabbableObject[] itemSlots = GameNetworkManager.Instance.localPlayerController.ItemSlots;
foreach (GrabbableObject val in itemSlots)
{
if ((Object)(object)val != (Object)null)
{
TrackObjectGrabbed(((NetworkBehaviour)val).NetworkObjectId);
}
}
}
public void EndRound()
{
WalkieTalkiePatch.StartUseTime = null;
IsOnMoon = false;
NetworkRPC.ReportStatsServerRpc(LocalPlayer);
}
public void TrackObjectGrabbed(ulong networkID)
{
Utils.Log((LogLevel)32, $"Sending object grabbed {networkID} {GameNetworkManager.Instance.localPlayerController.playerSteamId}");
NetworkRPC.ReportPickedUpObjectServerRpc(networkID, GameNetworkManager.Instance.localPlayerController.playerSteamId);
}
}
public static class Utils
{
public static void Log(LogLevel logLevel, string message, ManualLogSource logSource = null)
{
//IL_0012: 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_0049: Unknown result type (might be due to invalid IL or missing references)
if (logSource == null)
{
Plugin.LogSource.Log(logLevel, (object)message);
}
else
{
logSource.Log(logLevel, (object)message);
}
if ((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null)
{
NetworkRPC.LogServerRpc(GameNetworkManager.Instance.localPlayerController.playerUsername, GameNetworkManager.Instance.localPlayerController.playerSteamId, logLevel, message, logSource == null);
}
}
}
}
namespace HighQuotaStatTracking.Patches
{
public static class BeltBagItemPatch
{
[HarmonyPrefix]
[HarmonyPatch(typeof(BeltBagItem), "PutObjectInBagLocalClient")]
private static void PutObjectInBagLocalClient(GrabbableObject gObject, BeltBagItem __instance)
{
if (!((Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null) && StatManager.Instance.IsOnMoon && GameNetworkManager.Instance.localPlayerController.playerSteamId == ((GrabbableObject)__instance).playerHeldBy.playerSteamId)
{
StatManager.Instance.TrackObjectGrabbed(((NetworkBehaviour)gObject).NetworkObject.NetworkObjectId);
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (localPlayer != null)
{
Utils.Log((LogLevel)32, $"Picked up {((NetworkBehaviour)gObject).NetworkObject.NetworkObjectId} in belt bag at {DateTime.UtcNow}");
localPlayer.ObtainedItems.TryAdd(((NetworkBehaviour)gObject).NetworkObject.NetworkObjectId, DateTime.UtcNow);
}
}
}
}
public class DoorLockPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(DoorLock), "OpenOrCloseDoor")]
private static void OpenOrCloseDoor(PlayerControllerB playerWhoTriggered, DoorLock __instance)
{
if (!((Object)(object)playerWhoTriggered != (Object)(object)GameNetworkManager.Instance.localPlayerController) && StatManager.Instance.IsOnMoon && (bool)typeof(DoorLock).GetField("isDoorOpened", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance))
{
StatManager.Instance.LocalPlayer.DoorsOpened++;
}
}
}
public class PlayerControllerBPatch
{
[CompilerGenerated]
private sealed class <OnJoin>d__7 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <OnJoin>d__7(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(10f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
Utils.Log((LogLevel)16, "Connected with plugin version 1.12.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 static Vector3 lastPosition;
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
public static void LateUpdate(PlayerControllerB __instance)
{
//IL_004d: 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_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: 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_0278: Unknown result type (might be due to invalid IL or missing references)
//IL_027d: Unknown result type (might be due to invalid IL or missing references)
if (!StatManager.Instance.IsOnMoon || __instance.isInElevator)
{
return;
}
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (!__instance.isPlayerControlled || __instance.isPlayerDead || localPlayer == null || localPlayer.SteamID != __instance.playerSteamId)
{
return;
}
_ = lastPosition;
Vector3 val = lastPosition - ((Component)__instance).transform.localPosition;
float magnitude = ((Vector3)(ref val)).magnitude;
bool flag = (bool)typeof(PlayerControllerB).GetField("teleportingThisFrame", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
if (!__instance.teleportedLastFrame && !flag)
{
bool flag2 = false;
Object.FindObjectOfType<VehicleController>();
if (__instance.jetpackControls && (Object)(object)__instance.ItemSlots[__instance.currentItemSlot] != (Object)null)
{
GrabbableObject obj = __instance.ItemSlots[__instance.currentItemSlot];
JetpackItem val2 = (JetpackItem)(object)((obj is JetpackItem) ? obj : null);
if (val2 != null)
{
flag2 = (bool)typeof(JetpackItem).GetField("jetpackActivated", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val2);
}
}
if (flag2)
{
localPlayer.DistanceJetpacked += magnitude;
}
else if (__instance.isSprinting)
{
localPlayer.DistanceSprinted += magnitude;
}
else if (__instance.isCrouching)
{
localPlayer.DistanceCrouched += magnitude;
}
else
{
localPlayer.DistanceWalked += magnitude;
}
localPlayer.DistanceTraveled += magnitude;
}
else if (__instance.teleportedLastFrame && __instance.isClimbingLadder)
{
localPlayer.DistanceLaddered += magnitude;
localPlayer.DistanceTraveled += magnitude;
}
localPlayer.TotalStamina += __instance.sprintMeter;
localPlayer.StaminaCounts++;
if (Mathf.RoundToInt(Mathf.Clamp(__instance.carryWeight - 1f, 0f, 100f) * 105f) > 19 && __instance.isInsideFactory)
{
localPlayer.TimeSpentAbove19PoundsInside += Time.deltaTime;
}
if (__instance.drunkness > 0f)
{
localPlayer.TZPHighTime += Time.deltaTime;
}
GrabbableObject[] itemSlots = __instance.ItemSlots;
foreach (GrabbableObject val3 in itemSlots)
{
if ((Object)(object)val3 != (Object)null)
{
FlashlightItem val4 = (FlashlightItem)(object)((val3 is FlashlightItem) ? val3 : null);
if (val4 != null && ((GrabbableObject)val4).isBeingUsed)
{
localPlayer.TotalFlashlightTime += Time.deltaTime;
break;
}
}
}
lastPosition = ((Component)__instance).transform.localPosition;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerControllerB), "PlayerJump")]
public static void PlayerJump(PlayerControllerB __instance)
{
if (StatManager.Instance.IsOnMoon)
{
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (localPlayer != null && localPlayer.SteamID == __instance.playerSteamId)
{
localPlayer.Jumps++;
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
public static void DamagePlayer(int damageNumber, PlayerControllerB __instance)
{
if (StatManager.Instance.IsOnMoon && ((NetworkBehaviour)__instance).IsOwner && !__instance.isPlayerDead && __instance.AllowPlayerDeath())
{
if (__instance.health - damageNumber <= 0 && !__instance.criticallyInjured && damageNumber < 50)
{
_ = __instance.health;
}
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (localPlayer != null && localPlayer.SteamID == __instance.playerSteamId)
{
Utils.Log((LogLevel)32, $"Damage Taken: {damageNumber}");
localPlayer.DamageTaken += (ushort)damageNumber;
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
private static void KillPlayer(PlayerControllerB __instance)
{
if (!StatManager.Instance.IsOnMoon || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerDead)
{
return;
}
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (localPlayer != null && localPlayer.SteamID == __instance.playerSteamId)
{
if (!Environment.StackTrace.Contains("DamagePlayer"))
{
Utils.Log((LogLevel)32, $"Kill called from somewhere other than DamagePlayer. Adding health as damage {__instance.health}");
localPlayer.DamageTaken += (ushort)__instance.health;
}
StatManager.Instance.LocalPlayer.DiedTime = DateTime.UtcNow;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")]
private static void GrabObjectClientRpc(bool grabValidated, NetworkObjectReference grabbedObject, PlayerControllerB __instance)
{
NetworkObject val = default(NetworkObject);
if (StatManager.Instance.IsOnMoon && GameNetworkManager.Instance.localPlayerController.playerSteamId == __instance.playerSteamId && grabValidated && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null))
{
StatManager.Instance.TrackObjectGrabbed(val.NetworkObjectId);
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (localPlayer != null)
{
Utils.Log((LogLevel)32, $"Picked up {val.NetworkObjectId} at {DateTime.UtcNow}");
localPlayer.ObtainedItems.TryAdd(val.NetworkObjectId, DateTime.UtcNow);
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
private static void ConnectClientToPlayerObject(PlayerControllerB __instance)
{
((MonoBehaviour)__instance).StartCoroutine(OnJoin());
}
[IteratorStateMachine(typeof(<OnJoin>d__7))]
private static IEnumerator OnJoin()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <OnJoin>d__7(0);
}
}
public class StartOfRoundPatch
{
[HarmonyPatch(typeof(StartOfRound), "openingDoorsSequence")]
[HarmonyPrefix]
public static void openingDoorsSequence(StartOfRound __instance)
{
StatManager.Instance.StartRound();
}
[HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")]
[HarmonyPrefix]
public static void ShipHasLeft(StartOfRound __instance)
{
StatManager.Instance.EndRound();
}
}
public class VehicleControllerPatch
{
private static Dictionary<VehicleController, Vector3> m_LastCruiserPositions = new Dictionary<VehicleController, Vector3>();
[HarmonyPrefix]
[HarmonyPatch(typeof(VehicleController), "LateUpdate")]
public static void LateUpdate(VehicleController __instance)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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)
float num = 0f;
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
ClientPlayer localPlayer = StatManager.Instance.LocalPlayer;
if (m_LastCruiserPositions.ContainsKey(__instance))
{
Vector3 val = m_LastCruiserPositions[__instance] - ((Component)__instance).transform.localPosition;
num = ((Vector3)(ref val)).magnitude;
}
else
{
m_LastCruiserPositions.Add(__instance, ((Component)__instance).transform.localPosition);
}
if ((Object)(object)localPlayerController.physicsParent != (Object)null && (Object)(object)localPlayerController.physicsParent == (Object)(object)((Component)__instance).transform)
{
localPlayer.DistanceCruisered += num;
}
m_LastCruiserPositions[__instance] = ((Component)__instance).transform.localPosition;
}
}
public class WalkieTalkiePatch
{
public static DateTime? StartUseTime;
[HarmonyPrefix]
[HarmonyPatch(typeof(WalkieTalkie), "SetLocalClientSpeaking")]
private static void SetLocalClientSpeaking(bool speaking, WalkieTalkie __instance)
{
if ((Object)(object)((GrabbableObject)__instance).playerHeldBy != (Object)(object)GameNetworkManager.Instance.localPlayerController || !StatManager.Instance.IsOnMoon)
{
return;
}
if (speaking)
{
StartUseTime = DateTime.UtcNow;
return;
}
if (!StartUseTime.HasValue)
{
StartUseTime = StatManager.Instance.LandedTime;
}
StatManager.Instance.LocalPlayer.TotalWalkieTime += DateTime.UtcNow - StartUseTime.Value;
}
}
}