Decompiled source of TombRetriever v1.0.2

TombRetriever.dll

Decompiled 6 days ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace TombRetriever;

[BepInPlugin("ryan.tombretriever", "Tomb Retriever", "1.0.2")]
public class TombRetrieverPlugin : BaseUnityPlugin
{
	public const string Guid = "ryan.tombretriever";

	public const string Name = "Tomb Retriever";

	public const string Version = "1.0.2";

	private const string RpcRequest = "TombRetriever_Request";

	private const string RpcReply = "TombRetriever_Reply";

	private const string TombstonePrefab = "Player_tombstone";

	private const string OwnerKey = "owner";

	private const string PlayerIdKey = "playerID";

	private const float AlreadyHereDistance = 4f;

	private const double ReplyTimeoutSeconds = 6.0;

	private static TombRetrieverPlugin _instance;

	private static ConfigEntry<int> _cooldownSeconds;

	private bool _broken;

	private ZRoutedRpc _registeredOn;

	private Terminal _terminal;

	private bool _waiting;

	private DateTime _waitingSince;

	private readonly Dictionary<long, DateTime> _lastUse = new Dictionary<long, DateTime>();

	private static readonly Dictionary<string, MemberInfo> Members = new Dictionary<string, MemberInfo>();

	private static ZRoutedRpc Rpc
	{
		get
		{
			object obj = GetStatic(typeof(ZRoutedRpc), "instance", "m_instance", "s_instance");
			return (ZRoutedRpc)((obj is ZRoutedRpc) ? obj : null);
		}
	}

	private static ZNet Net
	{
		get
		{
			object obj = GetStatic(typeof(ZNet), "instance", "m_instance", "s_instance");
			return (ZNet)((obj is ZNet) ? obj : null);
		}
	}

	private static ZDOMan ZdoMan
	{
		get
		{
			object obj = GetStatic(typeof(ZDOMan), "instance", "m_instance", "s_instance");
			return (ZDOMan)((obj is ZDOMan) ? obj : null);
		}
	}

	private static ZNetScene Scene
	{
		get
		{
			object obj = GetStatic(typeof(ZNetScene), "instance", "m_instance", "s_instance");
			return (ZNetScene)((obj is ZNetScene) ? obj : null);
		}
	}

	private static Player LocalPlayer
	{
		get
		{
			object obj = GetStatic(typeof(Player), "m_localPlayer", "localPlayer", "s_localPlayer");
			return (Player)((obj is Player) ? obj : null);
		}
	}

	private void Awake()
	{
		_instance = this;
		_cooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "CooldownSeconds", 10, "Seconds a player must wait between uses of the command. Read by the server (or the host). 0 turns the wait off.");
		RegisterCommand("retrievetomb");
		RegisterCommand("gettomb");
	}

	private void RegisterCommand(string command)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			new ConsoleCommand(command, "Brings your tombstone(s) to where you are standing.", new ConsoleEvent(OnCommand), false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not add the '" + command + "' command: " + ex));
		}
	}

	private void Update()
	{
		if (_broken)
		{
			return;
		}
		try
		{
			Tick();
		}
		catch (Exception ex)
		{
			_broken = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("Tomb Retriever has switched itself off because of an error: " + ex));
		}
	}

	private void Tick()
	{
		ZRoutedRpc rpc = Rpc;
		if (rpc != null && !object.ReferenceEquals(rpc, _registeredOn))
		{
			_registeredOn = rpc;
			_waiting = false;
			try
			{
				rpc.Register("TombRetriever_Request", (Action<long>)RPC_Request);
				rpc.Register<string>("TombRetriever_Reply", (Action<long, string>)RPC_Reply);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not register with the network: " + ex));
			}
		}
		if (_waiting && (DateTime.UtcNow - _waitingSince).TotalSeconds > 6.0)
		{
			_waiting = false;
			Say("No answer from the server. Tomb Retriever has to be installed on the server too.");
		}
	}

	private static void OnCommand(ConsoleEventArgs args)
	{
		TombRetrieverPlugin instance = _instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		try
		{
			instance.RememberTerminal(args);
		}
		catch (Exception)
		{
		}
		try
		{
			instance.SendRequest();
		}
		catch (Exception ex2)
		{
			instance._waiting = false;
			((BaseUnityPlugin)instance).Logger.LogError((object)("The command failed: " + ex2));
			instance.Say("The command failed. See the log.");
		}
	}

	private void RememberTerminal(ConsoleEventArgs args)
	{
		if (args != null && (Object)(object)args.Context != (Object)null)
		{
			_terminal = args.Context;
		}
	}

	private void SendRequest()
	{
		if ((Object)(object)Net == (Object)null || Rpc == null || (Object)(object)LocalPlayer == (Object)null)
		{
			Say("You need to be in a world, alive, to retrieve your tombstone.");
			return;
		}
		if (_waiting)
		{
			Say("Still waiting for the server...");
			return;
		}
		_waiting = true;
		_waitingSince = DateTime.UtcNow;
		Say("Looking for your tombstone...");
		Rpc.InvokeRoutedRPC("TombRetriever_Request", new object[0]);
	}

	private void RPC_Reply(long sender, string message)
	{
		_waiting = false;
		Say(message);
	}

	private void Say(string message)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		try
		{
			if ((Object)(object)_terminal != (Object)null)
			{
				_terminal.AddString("[Tomb Retriever] " + message);
			}
		}
		catch (Exception)
		{
		}
	}

	private void RPC_Request(long sender)
	{
		ZNet net = Net;
		if ((Object)(object)net == (Object)null || !net.IsServer())
		{
			return;
		}
		string text;
		try
		{
			text = Retrieve(sender);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Retrieving a tombstone failed: " + ex));
			text = "Something went wrong on the server. See the server log.";
		}
		try
		{
			Rpc.InvokeRoutedRPC(sender, "TombRetriever_Reply", new object[1] { text });
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not send the answer: " + ex2));
		}
	}

	private string Retrieve(long sender)
	{
		//IL_000b: 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)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: 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)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		long num = 0L;
		string text = "?";
		Vector3 b = default(Vector3);
		bool flag = false;
		ZDOMan zdoMan = ZdoMan;
		if (zdoMan == null)
		{
			return "The world is not ready yet. Try again in a moment.";
		}
		Player localPlayer = LocalPlayer;
		ZNetPeer peer = Net.GetPeer(sender);
		if (peer != null)
		{
			text = peer.m_playerName;
			if (!((ZDOID)(ref peer.m_characterID)).IsNone())
			{
				ZDO zDO = zdoMan.GetZDO(peer.m_characterID);
				if (zDO != null)
				{
					num = zDO.GetLong("playerID", 0L);
					b = zDO.GetPosition();
					flag = true;
				}
			}
		}
		else if ((Object)(object)localPlayer != (Object)null)
		{
			num = localPlayer.GetPlayerID();
			text = localPlayer.GetPlayerName();
			b = ((Component)localPlayer).transform.position;
			flag = true;
		}
		if (!flag || num == 0)
		{
			return "You need to be alive in the world first. Respawn, then try again.";
		}
		int value = _cooldownSeconds.Value;
		if (value > 0 && _lastUse.TryGetValue(num, out var value2))
		{
			double num2 = (double)value - (DateTime.UtcNow - value2).TotalSeconds;
			if (num2 > 0.0)
			{
				return "Wait " + Math.Ceiling(num2).ToString("0") + " more second(s) before trying again.";
			}
		}
		List<ZDO> list = new List<ZDO>();
		int num3 = 0;
		int num4 = 0;
		while (!zdoMan.GetAllZDOsWithPrefabIterative("Player_tombstone", list, ref num3) && ++num4 <= 2000000)
		{
		}
		int num5 = 0;
		int num6 = 0;
		double num7 = 0.0;
		long sessionID = ZDOMan.GetSessionID();
		ZNetScene scene = Scene;
		Vector3 position2 = default(Vector3);
		foreach (ZDO item in list)
		{
			if (item == null || item.GetLong("owner", 0L) != num)
			{
				continue;
			}
			num5++;
			Vector3 position = item.GetPosition();
			double num8 = Distance(position, b);
			if (num8 <= 4.0)
			{
				continue;
			}
			if (num8 > num7)
			{
				num7 = num8;
			}
			double num9 = (double)num6 * (Math.PI / 3.0);
			((Vector3)(ref position2))..ctor(b.x + (float)(Math.Cos(num9) * 1.5), b.y + 1f, b.z + (float)(Math.Sin(num9) * 1.5));
			item.SetOwner(sessionID);
			item.SetPosition(position2);
			if ((Object)(object)scene != (Object)null)
			{
				ZNetView val = scene.FindInstance(item);
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).transform.position = position2;
				}
			}
			num6++;
		}
		if (num5 == 0)
		{
			return "No tombstone of yours exists in this world.";
		}
		if (num6 == 0)
		{
			return "Your tombstone is already right here.";
		}
		_lastUse[num] = DateTime.UtcNow;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Moved " + num6 + " tombstone(s) to " + text + " (farthest was " + num7.ToString("0") + " m away)."));
		return "Brought " + num6 + ((num6 != 1) ? " tombstones" : " tombstone") + " to you. The farthest was " + num7.ToString("0") + " m away. It may take a moment to appear.";
	}

	private static object GetStatic(Type type, params string[] names)
	{
		if (!Members.TryGetValue(type.FullName, out var value))
		{
			foreach (string name in names)
			{
				value = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (value == null)
				{
					value = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (value != null)
				{
					break;
				}
			}
			Members[type.FullName] = value;
			if (value == null && (Object)(object)_instance != (Object)null)
			{
				((BaseUnityPlugin)_instance).Logger.LogError((object)("Could not find " + type.Name + "." + names[0] + " in this version of the game."));
			}
		}
		PropertyInfo propertyInfo = value as PropertyInfo;
		if (propertyInfo != null)
		{
			return propertyInfo.GetValue(null, null);
		}
		FieldInfo fieldInfo = value as FieldInfo;
		if (fieldInfo != null)
		{
			return fieldInfo.GetValue(null);
		}
		return null;
	}

	private static double Distance(Vector3 a, Vector3 b)
	{
		double num = a.x - b.x;
		double num2 = a.y - b.y;
		double num3 = a.z - b.z;
		return Math.Sqrt(num * num + num2 * num2 + num3 * num3);
	}
}