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 System.Threading.Tasks;
using BepInEx;
using GameNetcodeStuff;
using HarmonyLib;
using LC_API.ServerAPI;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Pinger.Overrider;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Pinger")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Pings Player")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Pinger")]
[assembly: AssemblyTitle("Pinger")]
[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 Pinger
{
internal struct CustomScanNode
{
public long created { get; set; }
public ScanNodeProperties scanNode { get; set; }
public string owner { get; set; }
}
[JsonObject(/*Could not decode attribute arguments.*/)]
internal class PingData
{
[JsonProperty]
public float x { get; set; }
[JsonProperty]
public float y { get; set; }
[JsonProperty]
public float z { get; set; }
[JsonProperty]
public long created { get; set; }
[JsonProperty]
public string owner { get; set; }
[JsonProperty]
public bool isDanger { get; set; }
}
[BepInPlugin("Pinger", "Pinger", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private const string SIGNATURE = "player_ping";
private const int LIFESPAN = 10000;
private Harmony _harmony;
private ScanNodeProperties _scanNodeMaster;
private LinkedList<CustomScanNode> _scanNodes = new LinkedList<CustomScanNode>();
private static bool _isPatched;
private static bool _isPatching;
private static PlayerControllerB _mainPlayer;
private static HUDManager _hudManager;
public static Plugin Instance { get; private set; }
private void Awake()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
Instance = this;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Pinger is loaded!");
_harmony = new Harmony("Pinger");
_harmony.PatchAll(typeof(StartOfRound_Awake));
_harmony.PatchAll(typeof(KeyboardPing));
StartLogicLoop();
}
private async void StartLogicLoop()
{
while ((Object)(object)StartOfRound.Instance == (Object)null)
{
await Task.Delay(1000);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)"StartOfRound.Instance found...");
_mainPlayer = StartOfRound.Instance.localPlayerController;
while ((Object)(object)_mainPlayer == (Object)null)
{
await Task.Delay(250);
_mainPlayer = StartOfRound.Instance.localPlayerController;
}
while ((Object)(object)_hudManager == (Object)null)
{
await Task.Delay(250);
_hudManager = HUDManager.Instance;
}
_isPatched = true;
handleIncomingPings();
}
private void handleIncomingPings()
{
Networking.GetString = (Action<string, string>)Delegate.Combine(Networking.GetString, (Action<string, string>)delegate(string message, string signature)
{
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
if (signature.Equals("player_ping"))
{
PingData pingData = JsonConvert.DeserializeObject<PingData>(message);
if (pingData == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"Failed to parse ping data");
}
else
{
((BaseUnityPlugin)this).Logger.LogMessage((object)$"Received ping from {pingData.owner} at {pingData.x} {pingData.y} {pingData.z}");
float x = pingData.x;
float y = pingData.y;
float z = pingData.z;
RaycastHit hit = default(RaycastHit);
createPing(x, y, z, in hit, pingData.isDanger, pingData.owner);
}
}
});
}
private void DeletePings(string owner)
{
//IL_00ab: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
ScanNodeProperties[] array = Object.FindObjectsByType<ScanNodeProperties>((FindObjectsSortMode)0);
for (LinkedListNode<CustomScanNode> linkedListNode = _scanNodes.First; linkedListNode != null; linkedListNode = linkedListNode.Next)
{
if (!((Object)(object)linkedListNode.Value.scanNode == (Object)null))
{
if (linkedListNode.Value.owner != owner)
{
Debug.Log((object)$"Skipping ping at {((Component)linkedListNode.Value.scanNode).transform.position} (Predicate failed: {linkedListNode.Value.owner} != {owner})");
}
else
{
Debug.Log((object)$"Deleting ping at {((Component)linkedListNode.Value.scanNode).transform.position}");
Object.Destroy((Object)(object)linkedListNode.Value.scanNode);
for (int i = 0; i < array.Length; i++)
{
if (((Component)array[i]).transform.position == ((Component)linkedListNode.Value.scanNode).transform.position)
{
Object.Destroy((Object)(object)array[i]);
break;
}
}
}
}
}
}
private async void checkAndDeleteOldPings()
{
int lifespan = 10000;
while (true)
{
await Task.Delay(1000);
long now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
for (LinkedListNode<CustomScanNode> node = _scanNodes.First; node != null; node = node.Next)
{
if (!((Object)(object)node.Value.scanNode == (Object)null) && now - node.Value.created > lifespan)
{
((BaseUnityPlugin)this).Logger.LogMessage((object)$"Deleting ping at {((Component)node.Value.scanNode).transform.position}");
Object.Destroy((Object)(object)node.Value.scanNode);
_scanNodes.Remove(node);
}
}
}
}
private void OnDestroy()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
ScanNodeProperties[] array = Object.FindObjectsByType<ScanNodeProperties>((FindObjectsSortMode)0);
for (LinkedListNode<CustomScanNode> linkedListNode = _scanNodes.First; linkedListNode != null; linkedListNode = linkedListNode.Next)
{
Object.Destroy((Object)(object)linkedListNode.Value.scanNode);
for (int i = 0; i < array.Length; i++)
{
if (((Component)array[i]).transform.position == ((Component)linkedListNode.Value.scanNode).transform.position)
{
Object.Destroy((Object)(object)array[i]);
break;
}
}
}
}
public bool createPingWherePlayerIsLooking(bool is_danger = false)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: 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)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_mainPlayer == (Object)null || (Object)(object)_hudManager == (Object)null)
{
if (_isPatching)
{
return false;
}
StartLogicLoop();
_isPatching = true;
return false;
}
float x = ((Component)_mainPlayer.gameplayCamera).transform.position.x;
float y = ((Component)_mainPlayer.gameplayCamera).transform.position.y;
float z = ((Component)_mainPlayer.gameplayCamera).transform.position.z;
RaycastHit hit = shootRay(x, y, z);
float x2 = ((RaycastHit)(ref hit)).point.x;
float y2 = ((RaycastHit)(ref hit)).point.y;
float z2 = ((RaycastHit)(ref hit)).point.z;
((BaseUnityPlugin)this).Logger.LogMessage((object)("Creating Ping on the surface of " + ((Object)((RaycastHit)(ref hit)).transform).name));
CustomScanNode customScanNode = createPing(x2, y2, z2, in hit, is_danger);
if ((Object)(object)customScanNode.scanNode == (Object)null)
{
return false;
}
string text = JsonConvert.SerializeObject((object)new PingData
{
x = x2,
y = y2,
z = z2,
created = customScanNode.created,
owner = _mainPlayer.playerUsername,
isDanger = is_danger
});
Networking.Broadcast(text, "player_ping");
return true;
}
private CustomScanNode createPing(float x, float y, float z, in RaycastHit hit)
{
return createPing(x, y, z, in hit, isDanger: false, _mainPlayer.playerUsername);
}
private CustomScanNode createPing(float x, float y, float z, in RaycastHit hit, bool isDanger)
{
return createPing(x, y, z, in hit, isDanger, _mainPlayer.playerUsername);
}
private CustomScanNode createPing(float x, float y, float z, in RaycastHit hit, string playerName)
{
return createPing(x, y, z, in hit, isDanger: false, playerName);
}
private CustomScanNode createPing(float x, float y, float z, in RaycastHit hit, bool isDanger, string playerName)
{
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
if (hasPlayerPinged(playerName))
{
DeletePings(playerName);
}
string headerText = playerName + "'s ping";
string subText = "Player Ping <!>";
((BaseUnityPlugin)this).Logger.LogMessage((object)$"Creating Ping at : {x} {y} {z}");
ScanNodeProperties[] array = Object.FindObjectsByType<ScanNodeProperties>((FindObjectsSortMode)0);
if ((Object)(object)_scanNodeMaster == (Object)null)
{
if (array.Length == 0)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"No scan node master found");
return default(CustomScanNode);
}
_scanNodeMaster = array[0];
checkAndDeleteOldPings();
}
ScanNodeProperties val = Object.Instantiate<ScanNodeProperties>(_scanNodeMaster);
((Object)val).name = "PlayerPing";
val.headerText = headerText;
val.subText = subText;
((Component)val).transform.position = new Vector3(x, y, z);
val.maxRange = 200;
val.minRange = 0;
val.requiresLineOfSight = true;
if (isDanger)
{
val.nodeType = 1;
val.subText = "DANGER <!>";
}
else
{
val.nodeType = 2;
}
CustomScanNode customScanNode = default(CustomScanNode);
long created = DateTimeOffset.Now.ToUnixTimeMilliseconds();
customScanNode.created = created;
customScanNode.scanNode = val;
customScanNode.owner = playerName;
_scanNodes.AddLast(customScanNode);
if ((Object)(object)_hudManager == (Object)null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"HUDManager is null");
}
else if (customScanNode.owner == _mainPlayer.playerUsername)
{
_hudManager.UIAudio.PlayOneShot(_hudManager.scanSFX);
}
return customScanNode;
}
private bool hasPlayerPinged(string name)
{
for (LinkedListNode<CustomScanNode> linkedListNode = _scanNodes.First; linkedListNode != null; linkedListNode = linkedListNode.Next)
{
if (linkedListNode.Value.owner == name)
{
return true;
}
}
return false;
}
private RaycastHit shootRay(float x, float y, float z)
{
//IL_0018: 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_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_002e: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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_0048: Unknown result type (might be due to invalid IL or missing references)
float num = 2.5f;
Transform transform = ((Component)_mainPlayer.gameplayCamera).transform;
Vector3 val = transform.position + transform.forward * num;
RaycastHit result = default(RaycastHit);
Physics.Raycast(val, transform.forward, ref result, 1000f);
return result;
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "Pinger";
public const string PLUGIN_NAME = "Pinger";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace Pinger.Overrider
{
[HarmonyPatch(typeof(StartOfRound), "Awake")]
internal class StartOfRound_Awake
{
[HarmonyPatch(typeof(StartOfRound), "Awake")]
[HarmonyPrefix]
private static bool Prefix()
{
Debug.Log((object)"StartOfRound.Awake() is called");
return true;
}
}
[HarmonyPatch]
internal class KeyboardPing
{
private static float lastQPress;
private const float PING_RESET = 0.3f;
private static bool isWaiting;
private static bool pingPressed;
private static IEnumerator WaitForNextQ()
{
if (!isWaiting)
{
isWaiting = true;
yield return (object)new WaitForSeconds(0.3f);
if (!pingPressed)
{
Plugin.Instance.createPingWherePlayerIsLooking();
}
isWaiting = false;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "Update")]
[HarmonyPostfix]
private static void PingCommand(PlayerControllerB __instance)
{
long num = DateTimeOffset.Now.ToUnixTimeMilliseconds();
bool flag = false;
if (!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || __instance.inTerminalMenu || __instance.isTypingChat || __instance.isPlayerDead)
{
flag = true;
}
if (flag)
{
return;
}
if (((ButtonControl)Keyboard.current.qKey).wasPressedThisFrame)
{
if (!pingPressed)
{
pingPressed = true;
((MonoBehaviour)__instance).StartCoroutine(WaitForNextQ());
}
else
{
bool flag2 = Plugin.Instance.createPingWherePlayerIsLooking(is_danger: true);
}
}
else if (pingPressed)
{
lastQPress += Time.deltaTime;
if (lastQPress >= 0.3f)
{
pingPressed = false;
isWaiting = false;
lastQPress = 0f;
}
}
}
}
}
namespace Pinger.CircleHelper
{
public static class Helper
{
private const string TAG = "[Pinger::CircleHelper]";
public static void debug_DisplayEntireComponentTree(Transform obj)
{
if ((Object)(object)obj == (Object)null)
{
return;
}
int childCount = obj.childCount;
if (childCount > 0)
{
for (int i = 0; i < childCount; i++)
{
Transform child = obj.GetChild(i);
Debug.Log((object)("[Pinger::CircleHelper]: " + ((Object)obj).name + "/" + ((Object)child).name));
debug_DisplayComponent(obj);
debug_DisplayEntireComponentTree(child);
}
Debug.Log((object)("EOF - " + ((Object)obj).name));
}
}
private static void debug_DisplayComponent(Transform obj)
{
Debug.Log((object)string.Format("{0}: {1} :: typeof {2}", "[Pinger::CircleHelper]", ((Object)obj).name, ((object)obj).GetType()));
}
public static Transform debug_GrabInnerCircle(Transform obj)
{
if ((Object)(object)obj == (Object)null)
{
return null;
}
int childCount = obj.childCount;
if (childCount <= 0)
{
return null;
}
Transform result = null;
for (int i = 0; i < childCount; i++)
{
Transform child = obj.GetChild(i);
if (((Object)child).name == "Inner")
{
result = child;
break;
}
}
return result;
}
}
}
namespace Pinger.Adder
{
internal static class Adder
{
public static void AddToClass<T>(this T obj, Action action)
{
obj.GetType().GetMethod("AddToClass").Invoke(obj, new object[1] { action });
}
}
}