Decompiled source of SlipStream v1.0.15

SlipStream.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("SlipStream")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("SlipStream")]
[assembly: AssemblyFileVersion("1.0.15.0")]
[assembly: AssemblyInformationalVersion("1.0.15+93e4786fd6da7213e58c36dcb338f01050b95c14")]
[assembly: AssemblyProduct("SlipStream")]
[assembly: AssemblyTitle("SlipStream")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.15.0")]
[module: UnverifiableCode]
[module: UnverifiableCode]
namespace Slipstream;

internal static class CoOp
{
	private static bool _registered;

	private static object _console;

	private static MethodInfo _submit;

	private static readonly List<string> _pending = new List<string>();

	public static void Register()
	{
		if (_registered)
		{
			if (_pending.Count > 0)
			{
				FlushPending();
			}
			return;
		}
		Type type = Hook.Type("RoR2.Console");
		if (type == null)
		{
			return;
		}
		_console = Hook.Get(Hook.Member(type, "instance", "_instance"), null);
		if (_console == null)
		{
			return;
		}
		_submit = Hook.Method(type, "SubmitCmd");
		Type type2 = Hook.Type("RoR2.ConVarFlags") ?? type.GetNestedType("ConVarFlags", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		object flags = 1;
		if (type2 != null && type2.IsEnum)
		{
			try
			{
				flags = Enum.Parse(type2, "ExecuteOnServer");
			}
			catch
			{
				flags = Enum.ToObject(type2, 1);
			}
		}
		bool num = AddCommand(type, "slipstream_t", flags, new Action<object>(OnToggle)) & AddCommand(type, "slipstream_item", flags, new Action<object>(OnItem)) & AddCommand(type, "slipstream_giveall", flags, new Action<object>(OnGiveAll)) & AddCommand(type, "slipstream_clear", flags, new Action<object>(OnClear)) & AddCommand(type, "slipstream_equip", flags, new Action<object>(OnEquip)) & AddCommand(type, "slipstream_money", flags, new Action<object>(OnMoney)) & AddCommand(type, "slipstream_void", flags, new Action<object>(OnVoid)) & AddCommand(type, "slipstream_lunar", flags, new Action<object>(OnLunar)) & AddCommand(type, "slipstream_revive", flags, new Action<object>(OnRevive)) & AddCommand(type, "slipstream_spawnas", flags, new Action<object>(OnSpawnAs)) & AddCommand(type, "slipstream_team", flags, new Action<object>(OnTeam)) & AddCommand(type, "slipstream_skin", flags, new Action<object>(OnSkin));
		AddCommand(type, "slipstream_buff", flags, new Action<object>(OnBuff));
		_registered = num;
		if (num)
		{
			Log.Info("Co-op host commands ready.");
			FlushPending();
			ReplayLocalToggles();
		}
		else
		{
			Log.Warn("Could not register co-op host commands. Clients cannot gift items or god themselves until the host has SlipStream and this registers.");
		}
	}

	public static void Submit(string command)
	{
		if (!string.IsNullOrEmpty(command))
		{
			Register();
			if (_submit == null || _console == null || !_registered)
			{
				_pending.Add(command);
			}
			else
			{
				Send(command);
			}
		}
	}

	public static bool AskHost(string command)
	{
		if (Game.IsServer)
		{
			return false;
		}
		Submit(command);
		return true;
	}

	private static void Send(string command)
	{
		object obj = Game.LocalActor()?.NetworkUser ?? Game.FirstLocalNetworkUser();
		if (obj == null)
		{
			_pending.Add(command);
			return;
		}
		try
		{
			ParameterInfo[] parameters = _submit.GetParameters();
			if (parameters.Length == 2)
			{
				_submit.Invoke(_console, new object[2] { obj, command });
			}
			else if (parameters.Length >= 3)
			{
				_submit.Invoke(_console, new object[3] { obj, command, false });
			}
			else
			{
				MethodInfo submit = _submit;
				object console = _console;
				object[] parameters2 = new string[1] { command };
				submit.Invoke(console, parameters2);
			}
		}
		catch (Exception ex)
		{
			Log.Warn("Host command failed: " + ex.Message);
			_pending.Add(command);
		}
	}

	private static void FlushPending()
	{
		if (_pending.Count != 0)
		{
			string[] array = _pending.ToArray();
			_pending.Clear();
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Send(array2[i]);
			}
		}
	}

	private static void ReplayLocalToggles()
	{
		if (!Game.IsServer && Session.LocalMods.Any)
		{
			Actor actor = Game.LocalActor();
			if (actor != null)
			{
				Game.PushLocalToggles(actor);
			}
		}
	}

	private static bool AddCommand(Type consoleType, string name, object flags, Delegate raw)
	{
		IDictionary dictionary = Hook.Field(consoleType, "concommandCatalog", "_concommandCatalog")?.GetValue(_console) as IDictionary;
		Type type = ((dictionary != null) ? Nested(consoleType, "ConCommand") : null);
		Type type2 = Nested(consoleType, "ConCommandDelegate");
		if (dictionary == null || type == null || type2 == null)
		{
			return TryRegisterMethod(consoleType, name, flags, raw);
		}
		try
		{
			Delegate obj = BindHandler(type2, raw.Method);
			if ((object)obj == null)
			{
				return TryRegisterMethod(consoleType, name, flags, raw);
			}
			object obj2;
			try
			{
				obj2 = Activator.CreateInstance(type);
			}
			catch
			{
				obj2 = Activator.CreateInstance(type, nonPublic: true);
			}
			FieldInfo fieldInfo = Hook.Field(type, "flags");
			FieldInfo fieldInfo2 = Hook.Field(type, "action", "fn", "callback");
			FieldInfo fieldInfo3 = Hook.Field(type, "helpText", "help");
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(obj2, Hook.Coerce(flags, fieldInfo.FieldType));
			}
			if (fieldInfo2 != null)
			{
				fieldInfo2.SetValue(obj2, obj);
			}
			if (fieldInfo3 != null && fieldInfo3.FieldType == typeof(string))
			{
				fieldInfo3.SetValue(obj2, "");
			}
			dictionary[name] = obj2;
			return true;
		}
		catch (Exception ex)
		{
			Log.Warn("Could not add " + name + ": " + ex.Message);
			return TryRegisterMethod(consoleType, name, flags, raw);
		}
	}

	private static bool TryRegisterMethod(Type consoleType, string name, object flags, Delegate raw)
	{
		MethodInfo[] methods = consoleType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo.Name.IndexOf("RegisterConCommand", StringComparison.OrdinalIgnoreCase) < 0)
			{
				continue;
			}
			ParameterInfo[] parameters = methodInfo.GetParameters();
			try
			{
				if (parameters.Length == 4)
				{
					Delegate obj = BindHandler(parameters[3].ParameterType, raw.Method);
					if ((object)obj != null)
					{
						methodInfo.Invoke(_console, new object[4] { name, flags, "", obj });
						return true;
					}
				}
			}
			catch
			{
			}
		}
		return false;
	}

	private static Delegate BindHandler(Type delType, MethodInfo handler)
	{
		if (delType == null || handler == null)
		{
			return null;
		}
		ParameterInfo[] array = delType.GetMethod("Invoke")?.GetParameters();
		if (array == null || array.Length != 1)
		{
			return null;
		}
		try
		{
			ParameterExpression parameterExpression = Expression.Parameter(array[0].ParameterType, "args");
			MethodCallExpression body = Expression.Call(handler, Expression.Convert(parameterExpression, typeof(object)));
			return Expression.Lambda(delType, body, parameterExpression).Compile();
		}
		catch
		{
			return null;
		}
	}

	private static Type Nested(Type type, string name)
	{
		Type type2 = type;
		while (type2 != null)
		{
			Type nestedType = type2.GetNestedType(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (nestedType != null)
			{
				return nestedType;
			}
			type2 = type2.BaseType;
		}
		return Hook.Type(type.FullName + "+" + name);
	}

	private static Actor Sender(object args)
	{
		if (args == null)
		{
			return null;
		}
		object obj = Hook.Get(Hook.Member(args.GetType(), "sender"), args);
		if (obj == null)
		{
			return null;
		}
		foreach (Actor item in Game.Players())
		{
			if (item.NetworkUser != null && item.NetworkUser == obj)
			{
				return item;
			}
		}
		uint num = Game.NetIdOf(obj);
		Actor actor = ((num != 0) ? Game.FindByNetId(num) : null);
		if (actor != null)
		{
			return actor;
		}
		uint num2 = Game.NetIdOf(Hook.Get(Hook.Member(obj.GetType(), "masterObject", "master"), obj));
		if (num2 == 0)
		{
			return null;
		}
		return Game.FindByNetId(num2);
	}

	private static string[] Tokens(object args)
	{
		if (args == null)
		{
			return Array.Empty<string>();
		}
		Type type = args.GetType();
		if (Hook.Get(Hook.Member(type, "userArgs", "args", "userTokenList"), args) is IList { Count: >0 } list)
		{
			string[] array = new string[list.Count];
			for (int i = 0; i < list.Count; i++)
			{
				array[i] = list[i]?.ToString() ?? "";
			}
			return array;
		}
		MethodInfo methodInfo = Hook.Method(type, "GetArgString") ?? Hook.Method(type, "GetArg");
		MemberInfo memberInfo = Hook.Member(type, "Count", "count");
		object obj = ((memberInfo != null) ? Hook.Get(memberInfo, args) : null);
		if (methodInfo != null && obj != null)
		{
			int num = Convert.ToInt32(obj);
			if (num > 0)
			{
				string[] array2 = new string[num];
				for (int j = 0; j < num; j++)
				{
					try
					{
						array2[j] = methodInfo.Invoke(args, new object[1] { j })?.ToString() ?? "";
					}
					catch
					{
						array2[j] = "";
					}
				}
				return array2;
			}
		}
		MethodInfo method = type.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(int) }, null);
		if (method != null && obj != null)
		{
			int num2 = Convert.ToInt32(obj);
			string[] array3 = new string[num2];
			for (int k = 0; k < num2; k++)
			{
				try
				{
					array3[k] = method.Invoke(args, new object[1] { k })?.ToString() ?? "";
				}
				catch
				{
					array3[k] = "";
				}
			}
			return array3;
		}
		return Array.Empty<string>();
	}

	private static uint UIntAt(string[] tokens, int i)
	{
		if (tokens == null || i < 0 || i >= tokens.Length)
		{
			return 0u;
		}
		uint.TryParse(tokens[i], out var result);
		return result;
	}

	private static int IntAt(string[] tokens, int i)
	{
		if (tokens == null || i < 0 || i >= tokens.Length)
		{
			return 0;
		}
		int.TryParse(tokens[i], out var result);
		return result;
	}

	private static void OnToggle(object args)
	{
		if (!Game.IsServer)
		{
			return;
		}
		string[] array = Tokens(args);
		if (array.Length < 2)
		{
			return;
		}
		uint num = UIntAt(array, 0);
		int num2 = IntAt(array, 1);
		if (num == 0)
		{
			return;
		}
		Actor actor = Game.FindByNetId(num);
		if (actor == null || actor.IsLocal)
		{
			return;
		}
		ActorMods actorMods = Session.RemoteModsFor(num);
		if (actorMods != null)
		{
			actorMods.God = (num2 & 1) != 0;
			actorMods.InfiniteSprint = (num2 & 2) != 0;
			actorMods.InfiniteSkills = (num2 & 4) != 0;
			actorMods.Noclip = (num2 & 8) != 0;
			Game.SetGod(actor, actorMods.God);
			if (!actorMods.Noclip)
			{
				Ticker.RestoreNoclip(actor);
			}
		}
	}

	private static void OnItem(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.GiveItemLocal(actor, IntAt(tokens, 1), IntAt(tokens, 2));
			}
		}
	}

	private static void OnGiveAll(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.GiveAllItemsLocal(actor, IntAt(tokens, 1));
			}
		}
	}

	private static void OnClear(object args)
	{
		if (Game.IsServer)
		{
			Actor actor = Game.FindByNetId(UIntAt(Tokens(args), 0));
			if (actor != null)
			{
				Game.ClearInventoryLocal(actor);
			}
		}
	}

	private static void OnEquip(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.SetEquipmentLocal(actor, IntAt(tokens, 1));
			}
		}
	}

	private static void OnMoney(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.SetMoney(actor, UIntAt(tokens, 1));
			}
		}
	}

	private static void OnVoid(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.SetVoidCoins(actor, UIntAt(tokens, 1));
			}
		}
	}

	private static void OnLunar(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.AwardLunar(actor, UIntAt(tokens, 1));
			}
		}
	}

	private static void OnRevive(object args)
	{
		if (Game.IsServer)
		{
			Actor actor = Game.FindByNetId(UIntAt(Tokens(args), 0));
			if (actor != null)
			{
				Game.Revive(actor);
			}
		}
	}

	private static void OnSpawnAs(object args)
	{
		if (Game.IsServer)
		{
			string[] array = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(array, 0));
			string bodyName = ((array != null && array.Length > 1) ? array[1] : null);
			if (actor != null)
			{
				Game.SpawnAsNamed(actor, bodyName);
			}
		}
	}

	private static void OnTeam(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.ApplyTeamLocal(actor, IntAt(tokens, 1));
			}
		}
	}

	private static void OnBuff(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.SetBuffLocal(actor, IntAt(tokens, 1), IntAt(tokens, 2));
			}
		}
	}

	private static void OnSkin(object args)
	{
		if (Game.IsServer)
		{
			string[] tokens = Tokens(args);
			Actor actor = Game.FindByNetId(UIntAt(tokens, 0));
			if (actor != null)
			{
				Game.ApplySkin(actor, IntAt(tokens, 1));
			}
		}
	}
}
internal static class Esp
{
	private struct Mark
	{
		public Vector3 World;

		public string Label;

		public Color Color;
	}

	private static readonly List<Mark> Marks = new List<Mark>(128);

	private static float _nextRefresh;

	private static GUIStyle _style;

	public static void Draw()
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: 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_006e: Expected O, but got Unknown
		//IL_0078: 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)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Expected O, but got Unknown
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		if (!Session.EspAny || (Object)(object)Camera.main == (Object)null)
		{
			return;
		}
		if (Time.unscaledTime >= _nextRefresh)
		{
			Rebuild();
			_nextRefresh = Time.unscaledTime + 0.35f;
		}
		if (_style == null)
		{
			_style = new GUIStyle(GUI.skin.label)
			{
				fontSize = 12,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4,
				richText = false
			};
			_style.normal.textColor = Color.white;
		}
		Camera main = Camera.main;
		int height = Screen.height;
		int num = ((Marks.Count < 96) ? Marks.Count : 96);
		for (int i = 0; i < num; i++)
		{
			Mark mark = Marks[i];
			Vector3 val = main.WorldToScreenPoint(mark.World);
			if (!(val.z <= 0f))
			{
				float x = val.x;
				float num2 = (float)height - val.y;
				_style.normal.textColor = mark.Color;
				string label = mark.Label;
				Vector2 val2 = _style.CalcSize(new GUIContent(label));
				GUI.Label(new Rect(x - val2.x * 0.5f, num2 - 8f, val2.x + 4f, val2.y), label, _style);
			}
		}
	}

	private static void Rebuild()
	{
		//IL_0031: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_02af: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_036c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_041f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0424: Unknown result type (might be due to invalid IL or missing references)
		//IL_0467: Unknown result type (might be due to invalid IL or missing references)
		//IL_046c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0476: Unknown result type (might be due to invalid IL or missing references)
		//IL_047b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0495: Unknown result type (might be due to invalid IL or missing references)
		//IL_049a: Unknown result type (might be due to invalid IL or missing references)
		Marks.Clear();
		Actor actor = Game.LocalActor();
		Vector3 origin = (((Object)(object)actor?.Transform != (Object)null) ? actor.Transform.position : Vector3.zero);
		if (Session.EspTeleporter)
		{
			AddTracked("RoR2.TeleporterInteraction", "TP", new Color(1f, 0.55f, 0.2f), origin, 280f);
		}
		if (Session.EspChests)
		{
			AddTracked("RoR2.ChestBehavior", "Chest", new Color(0.95f, 0.85f, 0.35f), origin, 280f);
			AddNamed("chest", "Chest", new Color(0.95f, 0.85f, 0.35f), origin, 280f);
		}
		if (Session.EspShops)
		{
			AddTracked("RoR2.ShopTerminalBehavior", "Shop", new Color(0.55f, 0.75f, 1f), origin, 280f);
		}
		if (Session.EspBarrels)
		{
			AddTracked("RoR2.BarrelInteraction", "Barrel", new Color(0.7f, 0.55f, 0.3f), origin, 280f);
		}
		if (Session.EspScrappers)
		{
			AddTracked("RoR2.ScrapperController", "Scrapper", new Color(0.4f, 0.9f, 0.55f), origin, 280f);
		}
		if (Session.EspSecrets)
		{
			AddTracked("RoR2.PressurePlateController", "Plate", new Color(0.85f, 0.4f, 0.9f), origin, 280f);
			AddNamed("pressureplate", "Secret", new Color(0.85f, 0.4f, 0.9f), origin, 280f);
		}
		if (Session.EspPrinters)
		{
			AddTracked("RoR2.PurchaseInteraction", "Printer", new Color(0.4f, 0.85f, 1f), origin, 280f, "duplicator", "printer");
			AddNamed("duplicator", "Printer", new Color(0.4f, 0.85f, 1f), origin, 280f);
		}
		if (Session.EspNewt)
		{
			AddNamed("newt", "Newt", new Color(0.45f, 0.55f, 1f), origin, 280f);
			AddNamed("bazaar", "Newt", new Color(0.45f, 0.55f, 1f), origin, 280f);
		}
		if (Session.EspDrones)
		{
			AddTracked("RoR2.SummonMasterBehavior", "Drone", new Color(0.7f, 0.7f, 0.75f), origin, 280f);
			AddNamed("drone", "Drone", new Color(0.7f, 0.7f, 0.75f), origin, 280f);
		}
		if (Session.EspShrines)
		{
			AddNamed("shrine", "Shrine", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
			AddTracked("RoR2.ShrineChanceBehavior", "Shrine", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
			AddTracked("RoR2.ShrineBossBehavior", "Mountain", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
			AddTracked("RoR2.ShrineBloodBehavior", "Blood", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
			AddTracked("RoR2.ShrineCombatBehavior", "Combat", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
			AddTracked("RoR2.ShrineRestackBehavior", "Order", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
			AddTracked("RoR2.ShrineHealingBehavior", "Woods", new Color(0.95f, 0.45f, 0.45f), origin, 280f);
		}
		if (!Session.EspPlayers)
		{
			return;
		}
		foreach (Actor item in Game.Players())
		{
			if (!((Object)(object)item.Transform == (Object)null))
			{
				Add(item.Transform.position + Vector3.up * 2f, item.Name, new Color(0.45f, 1f, 0.55f), origin, 400f);
			}
		}
	}

	private static void AddTracked(string typeName, string label, Color color, Vector3 origin, float maxDist, params string[] nameContains)
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		Type type = Hook.Type(typeName);
		IList list = Game.Tracked(type);
		if (list != null)
		{
			foreach (object item in list)
			{
				Transform val = Hook.TransformOf(item);
				if (!((Object)(object)val == (Object)null) && (nameContains == null || nameContains.Length == 0 || NameMatches(((Object)((Component)val).gameObject).name, nameContains)))
				{
					Add(val.position, LabelFor(((Object)((Component)val).gameObject).name, label), color, origin, maxDist);
				}
			}
			return;
		}
		if (type == null)
		{
			return;
		}
		Object[] array = Object.FindObjectsOfType(type);
		for (int i = 0; i < array.Length; i++)
		{
			Transform val2 = Hook.TransformOf(array[i]);
			if (!((Object)(object)val2 == (Object)null) && (nameContains == null || nameContains.Length == 0 || NameMatches(((Object)((Component)val2).gameObject).name, nameContains)))
			{
				Add(val2.position, LabelFor(((Object)((Component)val2).gameObject).name, label), color, origin, maxDist);
			}
		}
	}

	private static void AddNamed(string fragment, string label, Color color, Vector3 origin, float maxDist)
	{
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		Type type = Hook.Type("RoR2.PurchaseInteraction") ?? Hook.Type("RoR2.GenericInteraction");
		if (type == null)
		{
			return;
		}
		IEnumerable enumerable = Game.Tracked(type);
		if (enumerable == null)
		{
			enumerable = Object.FindObjectsOfType(type);
		}
		foreach (object item in enumerable)
		{
			Transform val = Hook.TransformOf(item);
			if (!((Object)(object)val == (Object)null) && ((Object)((Component)val).gameObject).name.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				Add(val.position, LabelFor(((Object)((Component)val).gameObject).name, label), color, origin, maxDist);
			}
		}
	}

	private static bool NameMatches(string name, string[] fragments)
	{
		foreach (string value in fragments)
		{
			if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static string LabelFor(string objectName, string fallback)
	{
		if (!Session.EspAdvanced)
		{
			return fallback;
		}
		string text = objectName.Replace("(Clone)", "").Trim();
		if (text.Length <= 22)
		{
			return text;
		}
		return text.Substring(0, 22);
	}

	private static void Add(Vector3 world, string label, Color color, Vector3 origin, float maxDist)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = world - origin;
		if (!(((Vector3)(ref val)).sqrMagnitude > maxDist * maxDist))
		{
			Marks.Add(new Mark
			{
				World = world,
				Label = label,
				Color = color
			});
		}
	}
}
internal sealed class Actor
{
	public int Id;

	public string Name;

	public bool IsLocal;

	public object NetworkUser;

	public object Master;

	public object Body;

	public object Motor;

	public object Health;

	public object Inventory;

	public object InputBank;

	public object Team;

	public object Direction;

	public Transform Transform;
}
internal sealed class CatalogItem
{
	public int Index;

	public string Name;

	public string Pickup;

	public bool Hidden;

	public object Def;

	public Texture Icon;

	public Rect IconUv = new Rect(0f, 0f, 1f, 1f);

	public Color IconColor = new Color(0.18f, 0.22f, 0.26f, 1f);

	public bool IconResolved;
}
internal static class Game
{
	private struct PendingGive
	{
		public int ActorId;

		public uint NetId;

		public int ItemIndex;

		public int Count;
	}

	public static bool Ready;

	public static Harmony Harmony;

	public static Type TCharacterBody;

	public static Type TCharacterMaster;

	public static Type THealthComponent;

	public static Type TCharacterMotor;

	public static Type TInventory;

	public static Type TNetworkUser;

	public static Type TPlayerCharacterMasterController;

	public static Type TLocalUserManager;

	public static Type TTeamComponent;

	public static Type TInputBank;

	public static Type TCharacterDirection;

	public static Type TSkillLocator;

	public static Type TGenericSkill;

	public static Type TItemCatalog;

	public static Type TItemDef;

	public static Type TEquipmentCatalog;

	public static Type TEquipmentDef;

	public static Type TBuffCatalog;

	public static Type TBuffDef;

	public static Type TSurvivorCatalog;

	public static Type TSurvivorDef;

	public static Type TBodyCatalog;

	public static Type TMasterCatalog;

	public static Type TEliteCatalog;

	public static Type TEliteDef;

	public static Type TSceneCatalog;

	public static Type TSceneDef;

	public static Type TRun;

	public static Type TTeamManager;

	public static Type TTeleporterInteraction;

	public static Type THoldoutZoneController;

	public static Type TCombatDirector;

	public static Type TLanguage;

	public static Type TNetworkServer;

	public static Type TInstanceTracker;

	public static Type TTeleportHelper;

	public static Type TDirectorSpawnRequest;

	public static Type TDirectorPlacementRule;

	public static Type TSpawnCard;

	public static Type TInteractableSpawnCard;

	public static Type TCharacterSpawnCard;

	public static Type TRoR2Application;

	public static Type TNetworkManagerSystem;

	public static Type TMapZone;

	public static Type TBaseAI;

	public static Type TKinematicMotor;

	public static Type TItemIndex;

	public static Type TEquipmentIndex;

	public static Type TBuffIndex;

	public static Type TTeamIndex;

	public static Type THurtBox;

	public static Type TPickupIndex;

	public static Type TGenericPickupController;

	public static Type TSkinDef;

	public static Type TModelLocator;

	public static Type TModelSkinController;

	public static Type TBodyIndex;

	private static MemberInfo _bodyInstances;

	private static MemberInfo _playerInstances;

	private static MemberInfo _networkUsers;

	private static MemberInfo _localUsers;

	private static MemberInfo _runInstance;

	private static MemberInfo _teamManagerInstance;

	private static MemberInfo _teleporterInstance;

	private static MethodInfo _languageGet;

	private static MethodInfo _giveItem;

	private static MethodInfo _removeItem;

	private static MethodInfo _getItemCount;

	private static MethodInfo _onInventoryChanged;

	private static FieldInfo _itemStacks;

	private static MethodInfo _setEquipment;

	private static MethodInfo _getEquipment;

	private static MethodInfo _suicide;

	private static MethodInfo _respawn;

	private static MethodInfo _respawnAt;

	private static MethodInfo _getBody;

	private static MethodInfo _setBuffCount;

	private static MethodInfo _getBuffCount;

	private static MethodInfo _addTimedBuff;

	private static MethodInfo _clearTimedBuffs;

	private static MethodInfo _awardLunar;

	private static MethodInfo _advanceStage;

	private static MethodInfo _getSceneDef;

	private static MethodInfo _findSceneDef;

	private static MethodInfo _allSceneDefs;

	private static MethodInfo _itemCount;

	private static MethodInfo _getItemDef;

	private static MethodInfo _equipCount;

	private static MethodInfo _getEquipDef;

	private static MethodInfo _buffCount;

	private static MethodInfo _getBuffDef;

	private static MethodInfo _allSurvivors;

	private static MethodInfo _getBodyPrefab;

	private static MethodInfo _findBodyPrefab;

	private static MethodInfo _findBodyIndex;

	private static MethodInfo _transformBody;

	private static MethodInfo _getMasterPrefab;

	private static MethodInfo _bodyCount;

	private static MethodInfo _masterCount;

	private static MethodInfo _eliteCount;

	private static MethodInfo _getEliteDef;

	private static MethodInfo _instanceTrackerGet;

	private static MethodInfo _teleportBody;

	private static MethodInfo _spawnCardDoSpawn;

	private static MethodInfo _networkServerSpawn;

	private static MethodInfo _networkServerActive;

	private static MethodInfo _serverKick;

	private static MethodInfo _serverBan;

	private static MethodInfo _giveTeamMoney;

	private static MethodInfo _giveTeamExp;

	private static MethodInfo _getBodySkins;

	private static MethodInfo _applySkin;

	private static MethodInfo _applySkinAsync;

	private static MethodInfo _skinDefApply;

	private static MethodInfo _setLoadoutServer;

	private static MethodInfo _setSkinIndex;

	private static FieldInfo _directorCombatDisableField;

	private static MemberInfo _masterGod;

	private static MemberInfo _healthGod;

	private static MemberInfo _masterMoney;

	private static MemberInfo _voidCoins;

	private static MemberInfo _lunarCoins;

	private static MemberInfo _bodyMaster;

	private static MemberInfo _bodyHealth;

	private static MemberInfo _bodyMotor;

	private static MemberInfo _bodyInventory;

	private static MemberInfo _bodyInput;

	private static MemberInfo _bodyTeam;

	private static MemberInfo _bodySkill;

	private static MemberInfo _bodyDirection;

	private static MemberInfo _bodySprinting;

	private static MemberInfo _masterInventory;

	private static MemberInfo _masterBodyPrefab;

	private static MemberInfo _masterPcmc;

	private static MemberInfo _pcmcMaster;

	private static MemberInfo _nuMaster;

	private static MemberInfo _nuUserName;

	private static MemberInfo _motorGravity;

	private static MemberInfo _motorVelocity;

	private static FieldInfo _tpShop;

	private static FieldInfo _tpGold;

	private static FieldInfo _tpCelestial;

	private static FieldInfo _tpHoldout;

	private static FieldInfo _tpShrineStacks;

	private static FieldInfo _holdoutCharge;

	private static MemberInfo _kcmLayers;

	private static FieldInfo _itemNameToken;

	private static FieldInfo _itemHidden;

	private static FieldInfo _itemTier;

	private static MemberInfo _itemPickupToken;

	private static MemberInfo _itemDescToken;

	private static FieldInfo _equipNameToken;

	private static FieldInfo _buffNameToken;

	private static FieldInfo _survivorNameToken;

	private static MemberInfo _survivorBodyPrefab;

	private static FieldInfo _sceneNameToken;

	private static FieldInfo _sceneCachedName;

	private static FieldInfo _eliteNameToken;

	private static FieldInfo _eliteEquipment;

	private static MemberInfo _bodyNameToken;

	private static MemberInfo _allBodyPrefabs;

	private static MemberInfo _bodyIndex;

	private static MemberInfo _bodySkinIndex;

	private static FieldInfo _modelTransform;

	private static FieldInfo _mscSkins;

	private static MemberInfo _mscCurrentSkin;

	private static FieldInfo _skinNameToken;

	private static FieldInfo _catalogSkins;

	private static MemberInfo _masterLoadout;

	private static FieldInfo _loadoutBodyManager;

	private static FieldInfo _masterBodyPrefabField;

	private static PropertyInfo _inputMove;

	private static PropertyInfo _inputAim;

	private static FieldInfo _placementMode;

	private static FieldInfo _placementPosition;

	private static FieldInfo _spawnRequestTeam;

	private static FieldInfo _spawnRequestIgnoreLimit;

	private static object _directPlacementMode;

	private static FieldInfo[] _mouseSkillFields;

	private static FieldInfo _buttonDown;

	private static FieldInfo _buttonWasDown;

	private static bool _loggedMissing;

	public static string LastActionMessage;

	private static readonly List<Action> _pendingPlayer = new List<Action>();

	private static readonly List<PendingGive> _pendingGives = new List<PendingGive>();

	private static bool _skinBusy;

	private static float _skinBusyUntil;

	public static bool IsServer
	{
		get
		{
			try
			{
				if (_networkServerActive != null)
				{
					return (bool)_networkServerActive.Invoke(null, null);
				}
			}
			catch
			{
			}
			try
			{
				object obj2 = LocalActor()?.Master;
				Component val = (Component)((obj2 is Component) ? obj2 : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					PropertyInfo propertyInfo = Hook.Prop(((object)val).GetType(), "isServer") ?? Hook.Prop(Hook.Type("UnityEngine.Networking.NetworkBehaviour"), "isServer");
					if (propertyInfo != null)
					{
						return (bool)propertyInfo.GetValue(val, null);
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}

	public static object RunInstance
	{
		get
		{
			if (!(_runInstance == null))
			{
				return Hook.Get(_runInstance, null);
			}
			return null;
		}
	}

	public static bool SkinBusy
	{
		get
		{
			if (_skinBusy)
			{
				return Time.unscaledTime < _skinBusyUntil;
			}
			return false;
		}
	}

	public static void Init(Harmony harmony)
	{
		Harmony = harmony;
		try
		{
			Resolve();
			if (Ready)
			{
				Patches.Apply(harmony);
				CoOp.Register();
			}
		}
		catch (Exception message)
		{
			Log.Error(message);
			Ready = TCharacterBody != null;
		}
	}

	public static void Resolve()
	{
		if (Ready)
		{
			return;
		}
		TCharacterBody = Hook.Type("RoR2.CharacterBody");
		if (TCharacterBody == null)
		{
			if (!_loggedMissing)
			{
				Log.Warn("RoR2 types not loaded yet.");
				_loggedMissing = true;
			}
			return;
		}
		TCharacterMaster = Hook.Type("RoR2.CharacterMaster");
		THealthComponent = Hook.Type("RoR2.HealthComponent");
		TCharacterMotor = Hook.Type("RoR2.CharacterMotor");
		TInventory = Hook.Type("RoR2.Inventory");
		TNetworkUser = Hook.Type("RoR2.NetworkUser");
		TPlayerCharacterMasterController = Hook.Type("RoR2.PlayerCharacterMasterController");
		TLocalUserManager = Hook.Type("RoR2.LocalUserManager");
		TTeamComponent = Hook.Type("RoR2.TeamComponent");
		TInputBank = Hook.Type("RoR2.InputBankTest") ?? Hook.Type("RoR2.InputBank");
		TCharacterDirection = Hook.Type("RoR2.CharacterDirection");
		TSkillLocator = Hook.Type("RoR2.SkillLocator");
		TGenericSkill = Hook.Type("RoR2.GenericSkill");
		TItemCatalog = Hook.Type("RoR2.ItemCatalog");
		TItemDef = Hook.Type("RoR2.ItemDef");
		TEquipmentCatalog = Hook.Type("RoR2.EquipmentCatalog");
		TEquipmentDef = Hook.Type("RoR2.EquipmentDef");
		TBuffCatalog = Hook.Type("RoR2.BuffCatalog");
		TBuffDef = Hook.Type("RoR2.BuffDef");
		TSurvivorCatalog = Hook.Type("RoR2.SurvivorCatalog");
		TSurvivorDef = Hook.Type("RoR2.SurvivorDef");
		TBodyCatalog = Hook.Type("RoR2.BodyCatalog");
		TMasterCatalog = Hook.Type("RoR2.MasterCatalog");
		TEliteCatalog = Hook.Type("RoR2.EliteCatalog");
		TEliteDef = Hook.Type("RoR2.EliteDef");
		TSceneCatalog = Hook.Type("RoR2.SceneCatalog");
		TSceneDef = Hook.Type("RoR2.SceneDef");
		TRun = Hook.Type("RoR2.Run");
		TTeamManager = Hook.Type("RoR2.TeamManager");
		TTeleporterInteraction = Hook.Type("RoR2.TeleporterInteraction");
		THoldoutZoneController = Hook.Type("RoR2.HoldoutZoneController");
		TCombatDirector = Hook.Type("RoR2.CombatDirector");
		TLanguage = Hook.Type("RoR2.Language");
		TNetworkServer = Hook.Type("UnityEngine.Networking.NetworkServer") ?? Hook.Type("RoR2.NetworkServer");
		TInstanceTracker = Hook.Type("RoR2.InstanceTracker");
		TTeleportHelper = Hook.Type("RoR2.TeleportHelper");
		TDirectorSpawnRequest = Hook.Type("RoR2.DirectorSpawnRequest");
		TDirectorPlacementRule = Hook.Type("RoR2.DirectorPlacementRule");
		TSpawnCard = Hook.Type("RoR2.SpawnCard");
		TInteractableSpawnCard = Hook.Type("RoR2.InteractableSpawnCard");
		TCharacterSpawnCard = Hook.Type("RoR2.CharacterSpawnCard");
		TRoR2Application = Hook.Type("RoR2.RoR2Application");
		TNetworkManagerSystem = Hook.Type("RoR2.Networking.NetworkManagerSystem") ?? Hook.Type("RoR2.NetworkManagerSystem");
		TMapZone = Hook.Type("RoR2.MapZone");
		TBaseAI = Hook.Type("RoR2.CharacterAI.BaseAI");
		TKinematicMotor = Hook.Type("KinematicCharacterController.KinematicCharacterMotor");
		TItemIndex = Hook.Type("RoR2.ItemIndex");
		TEquipmentIndex = Hook.Type("RoR2.EquipmentIndex");
		TBuffIndex = Hook.Type("RoR2.BuffIndex");
		TTeamIndex = Hook.Type("RoR2.TeamIndex");
		THurtBox = Hook.Type("RoR2.HurtBox");
		TPickupIndex = Hook.Type("RoR2.PickupIndex");
		TGenericPickupController = Hook.Type("RoR2.GenericPickupController");
		TSkinDef = Hook.Type("RoR2.SkinDef");
		TModelLocator = Hook.Type("RoR2.ModelLocator");
		TModelSkinController = Hook.Type("RoR2.ModelSkinController");
		TBodyIndex = Hook.Type("RoR2.BodyIndex");
		_bodyInstances = Hook.Member(TCharacterBody, "readOnlyInstancesList", "instancesList", "instances");
		_playerInstances = Hook.Member(TPlayerCharacterMasterController, "instances", "_instances", "instancesList", "readOnlyInstancesList");
		_networkUsers = Hook.Member(TNetworkUser, "readOnlyInstancesList", "instances", "instancesList");
		_localUsers = Hook.Member(TLocalUserManager, "readOnlyLocalUsersList") ?? Hook.Method(TLocalUserManager, "GetFirstLocalUser");
		_runInstance = Hook.Member(TRun, "instance", "_instance");
		_teamManagerInstance = Hook.Member(TTeamManager, "instance");
		_teleporterInstance = Hook.Member(TTeleporterInteraction, "instance");
		_directorCombatDisableField = Hook.Field(TCombatDirector, "cvDirectorCombatDisable");
		_languageGet = Hook.Method(TLanguage, "GetString", typeof(string)) ?? Hook.Method(TLanguage, "GetLocalizedStringByToken", typeof(string));
		_giveItem = FindMethod(TInventory, "GiveItem", 2) ?? FindMethod(TInventory, "GiveItem", 3) ?? FindMethod(TInventory, "GiveItem", 1) ?? Hook.Method(TInventory, "GiveItem");
		_removeItem = FindMethod(TInventory, "RemoveItem", 2) ?? Hook.Method(TInventory, "RemoveItem");
		_getItemCount = FindMethod(TInventory, "GetItemCount", 1) ?? Hook.Method(TInventory, "GetItemCount");
		_onInventoryChanged = Hook.Method(TInventory, "OnInventoryChanged");
		_itemStacks = Hook.Field(TInventory, "itemStacks", "_itemStacks");
		_setEquipment = FindMethod(TInventory, "SetEquipmentIndex", 1) ?? FindMethod(TInventory, "SetEquipmentIndex", 2);
		_getEquipment = Hook.Method(TInventory, "GetEquipmentIndex") ?? Hook.Prop(TInventory, "currentEquipmentIndex")?.GetGetMethod();
		_suicide = FindMethod(THealthComponent, "Suicide", 3) ?? FindMethod(THealthComponent, "Suicide", 0) ?? Hook.Method(THealthComponent, "Suicide");
		_respawn = Hook.Method(TCharacterMaster, "RespawnExtraLife") ?? Hook.Method(TCharacterMaster, "RespawnExtraLifeVoid");
		_respawnAt = FindMethod(TCharacterMaster, "Respawn", 2) ?? FindMethod(TCharacterMaster, "Respawn", 3);
		_getBody = Hook.Method(TCharacterMaster, "GetBody");
		_setBuffCount = FindMethod(TCharacterBody, "SetBuffCount", 2);
		_getBuffCount = FindMethod(TCharacterBody, "GetBuffCount", 1);
		_addTimedBuff = FindMethod(TCharacterBody, "AddTimedBuff", 2) ?? FindMethod(TCharacterBody, "AddTimedBuff", 3);
		_clearTimedBuffs = FindMethod(TCharacterBody, "ClearTimedBuffs", 1);
		_awardLunar = Hook.Method(TNetworkUser, "AwardLunarCoins") ?? FindMethod(TNetworkUser, "AwardLunarCoins", 1);
		_advanceStage = FindMethod(TRun, "AdvanceStage", 1);
		_getSceneDef = Hook.Method(TSceneCatalog, "GetSceneDefForCurrentScene");
		_findSceneDef = Hook.Method(TSceneCatalog, "FindSceneDef", typeof(string)) ?? Hook.Method(TSceneCatalog, "GetSceneDefFromSceneName", typeof(string));
		_allSceneDefs = Hook.Prop(TSceneCatalog, "allSceneDefs")?.GetGetMethod() ?? Hook.Method(TSceneCatalog, "GetAllSceneDefs");
		_itemCount = Hook.Prop(TItemCatalog, "itemCount")?.GetGetMethod();
		_getItemDef = Hook.Method(TItemCatalog, "GetItemDef");
		_equipCount = Hook.Prop(TEquipmentCatalog, "equipmentCount")?.GetGetMethod();
		_getEquipDef = Hook.Method(TEquipmentCatalog, "GetEquipmentDef");
		_buffCount = Hook.Prop(TBuffCatalog, "buffCount")?.GetGetMethod();
		_getBuffDef = Hook.Method(TBuffCatalog, "GetBuffDef");
		_allSurvivors = Hook.Prop(TSurvivorCatalog, "allSurvivorDefs")?.GetGetMethod();
		_getBodyPrefab = Hook.Method(TBodyCatalog, "GetBodyPrefab");
		_findBodyPrefab = Hook.Method(TBodyCatalog, "FindBodyPrefab", typeof(string)) ?? Hook.Method(TBodyCatalog, "FindBodyPrefab");
		_findBodyIndex = Hook.Method(TBodyCatalog, "FindBodyIndex", typeof(string)) ?? Hook.Method(TBodyCatalog, "FindBodyIndex");
		_transformBody = FindMethod(TCharacterMaster, "TransformBody", 1) ?? Hook.Method(TCharacterMaster, "TransformBody");
		_getMasterPrefab = Hook.Method(TMasterCatalog, "GetMasterPrefab");
		_bodyCount = Hook.Prop(TBodyCatalog, "bodyCount")?.GetGetMethod();
		_masterCount = Hook.Prop(TMasterCatalog, "masterCount")?.GetGetMethod();
		_eliteCount = Hook.Prop(TEliteCatalog, "eliteCount")?.GetGetMethod();
		_getEliteDef = Hook.Method(TEliteCatalog, "GetEliteDef");
		_teleportBody = FindMethod(TTeleportHelper, "TeleportBody", 2);
		_spawnCardDoSpawn = FindMethod(TSpawnCard, "DoSpawn", 3);
		_networkServerSpawn = Hook.Method(TNetworkServer, "Spawn", typeof(GameObject));
		_networkServerActive = Hook.Prop(TNetworkServer, "active")?.GetGetMethod() ?? Hook.Method(TNetworkServer, "get_active");
		_serverKick = FindMethod(TNetworkManagerSystem, "ServerKickClient", 2) ?? FindMethod(TNetworkManagerSystem, "ServerKickClient", 1);
		_serverBan = FindMethod(TNetworkManagerSystem, "ServerBanClient", 1);
		_giveTeamMoney = FindMethod(TTeamManager, "GiveTeamMoney", 2);
		_giveTeamExp = FindMethod(TTeamManager, "GiveTeamExperience", 2) ?? FindMethod(TTeamManager, "GiveTeamExperience", 3);
		_getBodySkins = Hook.Method(TBodyCatalog, "GetBodySkins") ?? Hook.Method(Hook.Type("RoR2.SkinCatalog"), "GetBodySkins");
		_applySkin = FindMethod(TModelSkinController, "ApplySkin", 1) ?? Hook.Method(TModelSkinController, "ApplySkin");
		_applySkinAsync = FindMethod(TModelSkinController, "ApplySkinAsync", 1) ?? Hook.Method(TModelSkinController, "ApplySkinAsync");
		_skinDefApply = FindMethod(TSkinDef, "Apply", 1) ?? Hook.Method(TSkinDef, "Apply");
		_setLoadoutServer = Hook.Method(TCharacterMaster, "SetLoadoutServer");
		_catalogSkins = Hook.Field(TBodyCatalog, "skins");
		_masterGod = Hook.Member(TCharacterMaster, "godMode");
		_healthGod = Hook.Member(THealthComponent, "godMode");
		_masterMoney = Hook.Member(TCharacterMaster, "money");
		_voidCoins = Hook.Member(TCharacterMaster, "voidCoins", "voidCoin");
		_lunarCoins = Hook.Member(TNetworkUser, "lunarCoins");
		_bodyMaster = Hook.Member(TCharacterBody, "master", "_master");
		_bodyHealth = Hook.Member(TCharacterBody, "healthComponent", "_healthComponent");
		_bodyMotor = Hook.Member(TCharacterBody, "characterMotor", "_characterMotor");
		_bodyInventory = Hook.Member(TCharacterBody, "inventory", "_inventory");
		_bodyInput = Hook.Member(TCharacterBody, "inputBank", "_inputBank");
		_bodyTeam = Hook.Member(TCharacterBody, "teamComponent", "_teamComponent");
		_bodySkill = Hook.Member(TCharacterBody, "skillLocator", "_skillLocator");
		_bodyDirection = Hook.Member(TCharacterBody, "characterDirection", "_characterDirection");
		_bodySprinting = Hook.Member(TCharacterBody, "isSprinting", "sprinting");
		_masterInventory = Hook.Member(TCharacterMaster, "inventory", "_inventory");
		_masterBodyPrefab = Hook.Member(TCharacterMaster, "bodyPrefab", "_bodyPrefab");
		_masterPcmc = Hook.Member(TCharacterMaster, "playerCharacterMasterController");
		_pcmcMaster = Hook.Member(TPlayerCharacterMasterController, "master");
		_nuMaster = Hook.Member(TNetworkUser, "master");
		_nuUserName = Hook.Member(TNetworkUser, "userName");
		_motorGravity = Hook.Member(TCharacterMotor, "useGravity");
		_motorVelocity = Hook.Member(TCharacterMotor, "velocity", "Velocity", "BaseVelocity");
		_tpShop = Hook.Field(TTeleporterInteraction, "shouldAttemptToSpawnShopPortal");
		_tpGold = Hook.Field(TTeleporterInteraction, "shouldAttemptToSpawnGoldshoresPortal");
		_tpCelestial = Hook.Field(TTeleporterInteraction, "shouldAttemptToSpawnMSPortal");
		_tpHoldout = Hook.Field(TTeleporterInteraction, "holdoutZoneController");
		_tpShrineStacks = Hook.Field(TTeleporterInteraction, "shrineBonusStacks", "bossShrineBonus");
		_holdoutCharge = Hook.Field(THoldoutZoneController, "_charge", "charge");
		_kcmLayers = Hook.Member(TKinematicMotor, "CollidableLayers", "collidableLayers");
		_itemNameToken = Hook.Field(TItemDef, "nameToken");
		_itemHidden = Hook.Field(TItemDef, "hidden");
		_itemTier = Hook.Field(TItemDef, "tier");
		_itemPickupToken = Hook.Member(TItemDef, "pickupToken", "descriptionToken");
		_itemDescToken = Hook.Member(TItemDef, "descriptionToken", "pickupToken");
		_equipNameToken = Hook.Field(TEquipmentDef, "nameToken");
		_buffNameToken = Hook.Field(TBuffDef, "nameToken", "eliteNameToken");
		_survivorNameToken = Hook.Field(TSurvivorDef, "displayNameToken");
		_survivorBodyPrefab = Hook.Member(TSurvivorDef, "bodyPrefab", "_bodyPrefab");
		_sceneNameToken = Hook.Field(TSceneDef, "nameToken");
		_sceneCachedName = Hook.Field(TSceneDef, "cachedName", "baseSceneName");
		_eliteNameToken = Hook.Field(TEliteDef, "modifierToken", "eliteNameToken");
		_eliteEquipment = Hook.Field(TEliteDef, "eliteEquipmentDef");
		_bodyNameToken = Hook.Member(TCharacterBody, "baseNameToken");
		_allBodyPrefabs = Hook.Member(TBodyCatalog, "allBodyPrefabs", "bodyPrefabs");
		_bodyIndex = Hook.Member(TCharacterBody, "bodyIndex");
		_bodySkinIndex = Hook.Member(TCharacterBody, "skinIndex");
		_modelTransform = Hook.Field(TModelLocator, "modelTransform", "_modelTransform");
		_mscSkins = Hook.Field(TModelSkinController, "skins");
		_mscCurrentSkin = Hook.Member(TModelSkinController, "currentSkinIndex", "skinIndex");
		_skinNameToken = Hook.Field(TSkinDef, "nameToken");
		_masterLoadout = Hook.Member(TCharacterMaster, "loadout", "_loadout");
		Type type = Hook.Type("RoR2.Loadout");
		Type type2 = type?.GetNestedType("BodyLoadoutManager") ?? Hook.Type("RoR2.Loadout+BodyLoadoutManager");
		_loadoutBodyManager = Hook.Field(type, "bodyLoadoutManager");
		_setSkinIndex = Hook.Method(type2, "SetSkinIndex");
		_masterBodyPrefabField = Hook.Field(Hook.Type("RoR2.CharacterMaster"), "bodyPrefab");
		_inputMove = Hook.Prop(TInputBank, "moveVector");
		_inputAim = Hook.Prop(TInputBank, "aimDirection");
		_placementMode = Hook.Field(TDirectorPlacementRule, "placementMode");
		_placementPosition = Hook.Field(TDirectorPlacementRule, "position");
		_spawnRequestTeam = Hook.Field(TDirectorSpawnRequest, "teamIndexOverride");
		_spawnRequestIgnoreLimit = Hook.Field(TDirectorSpawnRequest, "ignoreTeamMemberLimit");
		if (TDirectorPlacementRule != null)
		{
			Type nestedType = TDirectorPlacementRule.GetNestedType("PlacementMode");
			if (nestedType != null && nestedType.IsEnum)
			{
				try
				{
					_directPlacementMode = Enum.Parse(nestedType, "Direct");
				}
				catch
				{
					_directPlacementMode = Enum.ToObject(nestedType, 0);
				}
			}
		}
		Ready = true;
		Log.Info("RoR2 bridge ready. GiveItem=" + ((_giveItem != null) ? _giveItem.ToString() : "missing") + " itemStacks=" + (_itemStacks != null) + " money=" + (_masterMoney != null) + " motor=" + (_bodyMotor != null) + " sprint=" + (_bodySprinting != null) + " team=" + (_bodyTeam != null) + " applySkinAsync=" + ((_applySkinAsync != null) ? _applySkinAsync.ToString() : "missing") + " findBodyPrefab=" + (_findBodyPrefab != null) + " transformBody=" + ((_transformBody != null) ? _transformBody.ToString() : "missing"));
	}

	private static MethodInfo FindMethod(Type type, string name, int argc)
	{
		if (type == null)
		{
			return null;
		}
		MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo.Name == name && methodInfo.GetParameters().Length == argc && !methodInfo.IsGenericMethod)
			{
				return methodInfo;
			}
		}
		return null;
	}

	public static string Localize(string token)
	{
		if (string.IsNullOrEmpty(token))
		{
			return token;
		}
		if (_languageGet == null)
		{
			return token;
		}
		try
		{
			string text = _languageGet.Invoke(null, new object[1] { token }) as string;
			return string.IsNullOrEmpty(text) ? token : text;
		}
		catch
		{
			return token;
		}
	}

	public static List<Actor> Players()
	{
		List<Actor> list = new List<Actor>();
		HashSet<int> hashSet = new HashSet<int>();
		object obj = LocalBody();
		IEnumerable enumerable = ((_playerInstances != null) ? (Hook.Get(_playerInstances, null) as IEnumerable) : null);
		if (enumerable != null)
		{
			foreach (object item in enumerable)
			{
				if (item != null)
				{
					Actor actor = FromMaster((_pcmcMaster != null) ? Hook.Get(_pcmcMaster, item) : null, obj);
					if (actor != null && hashSet.Add(actor.Id))
					{
						list.Add(actor);
					}
				}
			}
		}
		IEnumerable enumerable2 = ((_networkUsers != null) ? (Hook.Get(_networkUsers, null) as IEnumerable) : null);
		if (enumerable2 != null)
		{
			foreach (object item2 in enumerable2)
			{
				if (item2 != null)
				{
					Actor actor2 = FromMaster((_nuMaster != null) ? Hook.Get(_nuMaster, item2) : null, obj);
					if (actor2 != null && hashSet.Add(actor2.Id))
					{
						actor2.NetworkUser = item2;
						list.Add(actor2);
					}
				}
			}
		}
		if (list.Count == 0 && obj != null)
		{
			Actor actor3 = FromBody(obj, obj);
			if (actor3 != null)
			{
				list.Add(actor3);
			}
		}
		return list;
	}

	public static Actor FindPlayer(int id)
	{
		foreach (Actor item in Players())
		{
			if (item.Id == id)
			{
				return item;
			}
		}
		return null;
	}

	public static object LocalBody()
	{
		try
		{
			MethodInfo methodInfo = Hook.Method(TLocalUserManager, "GetFirstLocalUser");
			object obj = ((methodInfo != null) ? methodInfo.Invoke(null, null) : null);
			if (obj == null)
			{
				return null;
			}
			MemberInfo memberInfo = Hook.Member(obj.GetType(), "cachedBody");
			object obj2 = ((memberInfo != null) ? Hook.Get(memberInfo, obj) : null);
			if (obj2 != null)
			{
				return obj2;
			}
			MemberInfo memberInfo2 = Hook.Member(obj.GetType(), "cachedMaster", "cachedMasterController");
			object obj3 = ((memberInfo2 != null) ? Hook.Get(memberInfo2, obj) : null);
			if (obj3 != null && _getBody != null)
			{
				return _getBody.Invoke(obj3, null);
			}
		}
		catch
		{
		}
		return null;
	}

	public static Actor LocalActor()
	{
		object obj = LocalBody();
		if (obj != null)
		{
			return FromBody(obj, obj);
		}
		return null;
	}

	private static Actor FromMaster(object master, object localBody)
	{
		if (master == null)
		{
			return null;
		}
		object obj = null;
		try
		{
			obj = _getBody?.Invoke(master, null);
		}
		catch
		{
		}
		if (obj == null)
		{
			return FromMasterOnly(master, localBody);
		}
		return FromBody(obj, localBody);
	}

	private static Actor FromMasterOnly(object master, object localBody)
	{
		Actor obj = new Actor
		{
			Master = master,
			Name = "Player",
			Id = StableId(master, (Component)((master is Component) ? master : null))
		};
		obj.Inventory = InventoryOf(obj);
		FillNetworkUser(obj);
		return obj;
	}

	public static Actor FromBody(object body, object localBody)
	{
		if (body == null)
		{
			return null;
		}
		Component val = (Component)((body is Component) ? body : null);
		object obj = ((_bodyMaster != null) ? Hook.Get(_bodyMaster, body) : null);
		if (!UnityAlive(obj))
		{
			obj = ComponentOf(Bind(body, "masterObject", "_masterObject"), TCharacterMaster);
		}
		Actor actor = new Actor
		{
			Body = body,
			Master = obj,
			Health = ((_bodyHealth != null) ? Hook.Get(_bodyHealth, body) : null),
			Motor = ((_bodyMotor != null) ? Hook.Get(_bodyMotor, body) : null),
			InputBank = ((_bodyInput != null) ? Hook.Get(_bodyInput, body) : null),
			Team = ((_bodyTeam != null) ? Hook.Get(_bodyTeam, body) : null),
			Direction = ((_bodyDirection != null) ? Hook.Get(_bodyDirection, body) : null),
			Transform = (Object.op_Implicit((Object)(object)val) ? val.transform : null),
			Id = StableId(obj, val),
			IsLocal = (localBody != null && body == localBody)
		};
		if (!UnityAlive(actor.Health) && Object.op_Implicit((Object)(object)val) && THealthComponent != null)
		{
			actor.Health = val.GetComponent(THealthComponent);
		}
		if (!UnityAlive(actor.Motor) && Object.op_Implicit((Object)(object)val) && TCharacterMotor != null)
		{
			actor.Motor = val.GetComponent(TCharacterMotor);
		}
		if (!UnityAlive(actor.InputBank) && Object.op_Implicit((Object)(object)val) && TInputBank != null)
		{
			actor.InputBank = val.GetComponent(TInputBank);
		}
		if (!UnityAlive(actor.Team) && Object.op_Implicit((Object)(object)val) && TTeamComponent != null)
		{
			actor.Team = val.GetComponent(TTeamComponent);
		}
		actor.Inventory = InventoryOf(actor);
		FillNetworkUser(actor);
		if (string.IsNullOrEmpty(actor.Name))
		{
			actor.Name = (Object.op_Implicit((Object)(object)val) ? ((Object)val.gameObject).name : "Body");
		}
		return actor;
	}

	private static void FillNetworkUser(Actor actor)
	{
		object obj = ((actor.Master != null && _masterPcmc != null) ? Hook.Get(_masterPcmc, actor.Master) : null);
		if (!UnityAlive(obj))
		{
			obj = ComponentOf(actor.Master, TPlayerCharacterMasterController);
		}
		if (UnityAlive(obj))
		{
			MethodInfo methodInfo = Hook.Method(obj.GetType(), "GetDisplayName");
			if (methodInfo != null)
			{
				actor.Name = (methodInfo.Invoke(obj, null) as string) ?? actor.Name;
			}
			object obj2 = Bind(obj, "networkUser");
			if (UnityAlive(obj2))
			{
				actor.NetworkUser = obj2;
			}
		}
		if (actor.NetworkUser != null && string.IsNullOrEmpty(actor.Name) && _nuUserName != null)
		{
			actor.Name = Hook.Get(_nuUserName, actor.NetworkUser) as string;
		}
		if (string.IsNullOrEmpty(actor.Name))
		{
			actor.Name = "Player";
		}
	}

	private static object Bind(object target, params string[] names)
	{
		if (target == null || names == null || names.Length == 0)
		{
			return null;
		}
		MemberInfo memberInfo = Hook.Member(target.GetType(), names);
		if (!(memberInfo == null))
		{
			return Hook.Get(memberInfo, target);
		}
		return null;
	}

	private static object ComponentOf(object host, Type type)
	{
		if (host == null || type == null)
		{
			return null;
		}
		Component val = (Component)((host is Component) ? host : null);
		if (val != null && Object.op_Implicit((Object)(object)val))
		{
			return val.GetComponent(type);
		}
		GameObject val2 = (GameObject)((host is GameObject) ? host : null);
		if (val2 != null && Object.op_Implicit((Object)(object)val2))
		{
			return val2.GetComponent(type);
		}
		return null;
	}

	private static bool UnityAlive(object obj)
	{
		if (obj == null)
		{
			return false;
		}
		Object val = (Object)((obj is Object) ? obj : null);
		if (val != null)
		{
			return Object.op_Implicit(val);
		}
		return true;
	}

	private static int StableId(object master, Component fallback)
	{
		Component val = (Component)((master is Component) ? master : null);
		if (val != null && Object.op_Implicit((Object)(object)val))
		{
			return ((Object)val).GetInstanceID();
		}
		if (Object.op_Implicit((Object)(object)fallback))
		{
			return ((Object)fallback).GetInstanceID();
		}
		return master?.GetHashCode() ?? 0;
	}

	public static object FirstLocalNetworkUser()
	{
		try
		{
			MethodInfo methodInfo = Hook.Method(TLocalUserManager, "GetFirstLocalUser");
			object obj = ((methodInfo != null) ? methodInfo.Invoke(null, null) : null);
			if (obj == null)
			{
				return null;
			}
			return Hook.Get(Hook.Member(obj.GetType(), "currentNetworkUser", "networkUser"), obj);
		}
		catch
		{
			return null;
		}
	}

	public static uint NetId(Actor actor)
	{
		uint num = NetIdOf(actor?.Master);
		if (num != 0)
		{
			return num;
		}
		uint num2 = NetIdOf(actor?.NetworkUser);
		if (num2 != 0)
		{
			return num2;
		}
		return NetIdOf(actor?.Body);
	}

	public static uint NetIdOf(object component)
	{
		Component val = (Component)((component is Component) ? component : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return 0u;
		}
		Type type = Hook.Type("UnityEngine.Networking.NetworkIdentity");
		if (type == null)
		{
			return 0u;
		}
		Component val2 = val.GetComponent(type) ?? val.GetComponentInParent(type);
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return 0u;
		}
		object obj = Hook.Get(Hook.Member(((object)val2).GetType(), "netId"), val2);
		if (obj == null)
		{
			return 0u;
		}
		object obj2 = Hook.Get(Hook.Member(obj.GetType(), "Value", "value"), obj);
		try
		{
			return Convert.ToUInt32(obj2 ?? ((object)0));
		}
		catch
		{
			return 0u;
		}
	}

	public static Actor FindByNetId(uint netId)
	{
		if (netId == 0)
		{
			return null;
		}
		foreach (Actor item in Players())
		{
			if (NetIdOf(item.Master) == netId)
			{
				return item;
			}
			if (NetIdOf(item.NetworkUser) == netId)
			{
				return item;
			}
			if (NetIdOf(item.Body) == netId)
			{
				return item;
			}
		}
		return null;
	}

	public static IEnumerable Bodies()
	{
		IEnumerable enumerable = ((_bodyInstances != null) ? (Hook.Get(_bodyInstances, null) as IEnumerable) : null);
		return enumerable ?? Array.Empty<object>();
	}

	public static int TeamOf(object body)
	{
		if (body == null)
		{
			return 0;
		}
		object obj = ((_bodyTeam != null) ? Hook.Get(_bodyTeam, body) : null);
		if (!UnityAlive(obj))
		{
			Component val = (Component)((body is Component) ? body : null);
			if (val != null && TTeamComponent != null)
			{
				obj = val.GetComponent(TTeamComponent);
			}
		}
		if (!UnityAlive(obj))
		{
			return 0;
		}
		return IndexValue.ToInt(Hook.Get(Hook.Prop(obj.GetType(), "teamIndex") ?? Hook.Member(obj.GetType(), "teamIndex", "_teamIndex"), obj));
	}

	public static void SetTeam(Actor actor, int teamIndex)
	{
		if (actor != null)
		{
			if (actor.IsLocal)
			{
				Session.ForcedTeam = teamIndex;
			}
			if (!CoOp.AskHost("slipstream_team " + NetId(actor) + " " + teamIndex))
			{
				ApplyTeamLocal(actor, teamIndex);
			}
		}
	}

	public static void ApplyTeamLocal(Actor actor, int teamIndex)
	{
		if (actor == null)
		{
			return;
		}
		object teamEnum = ((TTeamIndex != null) ? IndexValue.FromInt(TTeamIndex, teamIndex) : ((object)teamIndex));
		object obj = actor.Team;
		if (!UnityAlive(obj))
		{
			object body = actor.Body;
			Component val = (Component)((body is Component) ? body : null);
			if (val != null && TTeamComponent != null)
			{
				obj = val.GetComponent(TTeamComponent) ?? val.GetComponentInChildren(TTeamComponent, true);
			}
		}
		actor.Team = obj;
		WriteTeamIndex(obj, teamEnum);
		WriteTeamIndex(actor.Master, teamEnum);
		WriteTeamIndex(actor.Body, teamEnum);
		WriteHurtBoxes(actor.Body, teamEnum);
		LastActionMessage = "Team: " + TeamName(teamIndex) + ". Allies on that team will not attack you.";
		Log.Info(LastActionMessage + " value=" + teamIndex + " on " + actor.Name);
	}

	public static void HoldForcedTeam(Actor actor)
	{
		if (actor != null && actor.Body != null && Session.ForcedTeam != int.MinValue && TeamOf(actor.Body) != Session.ForcedTeam)
		{
			ApplyTeamLocal(actor, Session.ForcedTeam);
		}
	}

	private static string TeamName(int teamIndex)
	{
		return teamIndex switch
		{
			0 => "Neutral", 
			1 => "Player", 
			2 => "Monster", 
			3 => "Lunar", 
			4 => "Void", 
			_ => "Team " + teamIndex, 
		};
	}

	private static void WriteTeamIndex(object target, object teamEnum)
	{
		if (target == null || teamEnum == null)
		{
			return;
		}
		Type type = target.GetType();
		string[] array = new string[4] { "set_teamIndex", "SetTeamIndex", "SwitchTeam", "ChangeTeam" };
		foreach (string name in array)
		{
			MethodInfo methodInfo = Hook.Method(type, name);
			if (!(methodInfo == null))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 1)
				{
					Hook.Call(methodInfo, target, Hook.Coerce(teamEnum, parameters[0].ParameterType));
					return;
				}
			}
		}
		PropertyInfo propertyInfo = Hook.Prop(type, "teamIndex");
		if (propertyInfo != null && propertyInfo.CanWrite)
		{
			Hook.Set(propertyInfo, target, teamEnum);
			return;
		}
		Hook.Set(Hook.Member(type, "teamIndex", "_teamIndex"), target, teamEnum);
	}

	private static void WriteHurtBoxes(object body, object teamEnum)
	{
		Component val = (Component)((body is Component) ? body : null);
		if (!Object.op_Implicit((Object)(object)val) || teamEnum == null)
		{
			return;
		}
		Type type = THurtBox ?? Hook.Type("RoR2.HurtBox");
		if (type != null)
		{
			Component[] componentsInChildren = val.GetComponentsInChildren(type, true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				WriteTeamIndex(componentsInChildren[i], teamEnum);
			}
		}
		Type type2 = Hook.Type("RoR2.TeamFilter");
		if (type2 != null)
		{
			WriteTeamIndex(val.GetComponent(type2) ?? val.GetComponentInChildren(type2, true), teamEnum);
		}
	}

	public static void PushLocalToggles(Actor self)
	{
		if (self != null)
		{
			SetGod(self, Session.LocalMods.God);
			if (!IsServer)
			{
				CoOp.Submit("slipstream_t " + NetId(self) + " " + PackToggles(Session.LocalMods));
			}
		}
	}

	public static int PackToggles(ActorMods mods)
	{
		if (mods == null)
		{
			return 0;
		}
		int num = 0;
		if (mods.God)
		{
			num |= 1;
		}
		if (mods.InfiniteSprint)
		{
			num |= 2;
		}
		if (mods.InfiniteSkills)
		{
			num |= 4;
		}
		if (mods.Noclip)
		{
			num |= 8;
		}
		return num;
	}

	public static void SetGod(Actor actor, bool enabled)
	{
		if (actor != null)
		{
			if (actor.Master != null && _masterGod != null)
			{
				Hook.Set(_masterGod, actor.Master, enabled);
			}
			if (actor.Health != null && _healthGod != null)
			{
				Hook.Set(_healthGod, actor.Health, enabled);
			}
		}
	}

	public static void SetSprinting(Actor actor, bool enabled)
	{
		if (actor != null && actor.Body != null && !(_bodySprinting == null))
		{
			Hook.Set(_bodySprinting, actor.Body, enabled);
		}
	}

	public static void SetMotorGravity(Actor actor, bool useGravity)
	{
		if (actor != null && actor.Motor != null && !(_motorGravity == null))
		{
			Hook.Set(_motorGravity, actor.Motor, useGravity);
		}
	}

	public static void SetMotorVelocity(Actor actor, Vector3 velocity)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if (actor != null && actor.Motor != null && !(_motorVelocity == null))
		{
			Hook.Set(_motorVelocity, actor.Motor, velocity);
		}
	}

	public static Vector3 MotorVelocity(Actor actor)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		if (actor == null || actor.Motor == null || _motorVelocity == null)
		{
			return Vector3.zero;
		}
		object obj = Hook.Get(_motorVelocity, actor.Motor);
		if (obj is Vector3)
		{
			return (Vector3)obj;
		}
		return Vector3.zero;
	}

	public static void SetCollidable(Actor actor, bool enabled)
	{
		object obj = actor?.Body;
		Component val = (Component)((obj is Component) ? obj : null);
		if (val != null && TKinematicMotor != null)
		{
			Component component = val.GetComponent(TKinematicMotor);
			if ((Object)(object)component != (Object)null && _kcmLayers != null)
			{
				Hook.Set(_kcmLayers, component, enabled ? (-1) : 0);
			}
		}
		if ((Object)(object)actor?.Transform != (Object)null)
		{
			Collider component2 = ((Component)actor.Transform).GetComponent<Collider>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.enabled = enabled;
			}
		}
	}

	public static Vector3 MoveVector(Actor actor)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		if (actor == null || actor.InputBank == null || _inputMove == null)
		{
			return Vector3.zero;
		}
		object value = _inputMove.GetValue(actor.InputBank, null);
		if (value is Vector3)
		{
			return (Vector3)value;
		}
		return Vector3.zero;
	}

	public static Vector3 AimDirection(Actor actor)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (actor == null || actor.InputBank == null || _inputAim == null)
		{
			if (!Object.op_Implicit((Object)(object)actor.Transform))
			{
				return Vector3.forward;
			}
			return actor.Transform.forward;
		}
		object value = _inputAim.GetValue(actor.InputBank, null);
		if (value is Vector3)
		{
			return (Vector3)value;
		}
		return Vector3.forward;
	}

	public static void SetAim(Actor actor, Vector3 direction)
	{
		//IL_0072: 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)
		if (actor != null && actor.InputBank != null && _inputAim != null && _inputAim.CanWrite)
		{
			_inputAim.SetValue(actor.InputBank, ((Vector3)(ref direction)).normalized, null);
		}
		if (actor != null && actor.Direction != null)
		{
			Hook.Set(Hook.Member(actor.Direction.GetType(), "forward"), actor.Direction, ((Vector3)(ref direction)).normalized);
		}
	}

	public static void RefillSkills(Actor actor)
	{
		if (actor == null || actor.Body == null || _bodySkill == null)
		{
			return;
		}
		object obj = Hook.Get(_bodySkill, actor.Body);
		if (obj == null)
		{
			return;
		}
		string[] array = new string[4] { "primary", "secondary", "utility", "special" };
		foreach (string text in array)
		{
			MemberInfo memberInfo = Hook.Member(obj.GetType(), text);
			object obj2 = ((memberInfo != null) ? Hook.Get(memberInfo, obj) : null);
			if (obj2 != null)
			{
				MemberInfo memberInfo2 = Hook.Member(obj2.GetType(), "maxStock");
				MemberInfo member = Hook.Member(obj2.GetType(), "stock");
				FieldInfo fieldInfo = Hook.Field(obj2.GetType(), "rechargeStopwatch", "finalRechargeStopwatch");
				object value = ((memberInfo2 != null) ? Hook.Get(memberInfo2, obj2) : ((object)1));
				Hook.Set(member, obj2, value);
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(obj2, 0f);
				}
			}
		}
	}

	public static uint GetMoney(Actor actor)
	{
		if (actor == null || actor.Master == null || _masterMoney == null)
		{
			return 0u;
		}
		try
		{
			return Convert.ToUInt32(Hook.Get(_masterMoney, actor.Master) ?? ((object)0));
		}
		catch
		{
			return 0u;
		}
	}

	public static void SetMoney(Actor actor, uint amount)
	{
		if (actor != null && actor.Master != null && !CoOp.AskHost("slipstream_money " + NetId(actor) + " " + amount))
		{
			if (_masterMoney == null)
			{
				LastActionMessage = "Could not find CharacterMaster.money.";
				Log.Warn(LastActionMessage);
				return;
			}
			Hook.Set(_masterMoney, actor.Master, amount);
			LastActionMessage = "Set money to " + amount + " for " + actor.Name + ".";
			Log.Info(LastActionMessage);
		}
	}

	public static uint GetVoidCoins(Actor actor)
	{
		if (actor == null || actor.Master == null || _voidCoins == null)
		{
			return 0u;
		}
		try
		{
			return Convert.ToUInt32(Hook.Get(_voidCoins, actor.Master) ?? ((object)0));
		}
		catch
		{
			return 0u;
		}
	}

	public static void SetVoidCoins(Actor actor, uint amount)
	{
		if (actor != null && actor.Master != null && !(_voidCoins == null) && !CoOp.AskHost("slipstream_void " + NetId(actor) + " " + amount))
		{
			Hook.Set(_voidCoins, actor.Master, amount);
			LastActionMessage = "Set Void coins to " + amount + " for " + actor.Name + ".";
		}
	}

	public static uint GetLunar(Actor actor)
	{
		if (actor == null || actor.NetworkUser == null || _lunarCoins == null)
		{
			return 0u;
		}
		try
		{
			return Convert.ToUInt32(Hook.Get(_lunarCoins, actor.NetworkUser) ?? ((object)0));
		}
		catch
		{
			return 0u;
		}
	}

	public static void AwardLunar(Actor actor, uint amount)
	{
		if (actor != null && actor.NetworkUser != null && !CoOp.AskHost("slipstream_lunar " + NetId(actor) + " " + amount))
		{
			if (_awardLunar != null)
			{
				Hook.Call(_awardLunar, actor.NetworkUser, amount);
			}
			else if (_lunarCoins != null)
			{
				uint lunar = GetLunar(actor);
				Hook.Set(_lunarCoins, actor.NetworkUser, lunar + amount);
			}
			LastActionMessage = "Awarded " + amount + " lunar coins to " + actor.Name + ".";
		}
	}

	public static void GiveExperience(uint amount)
	{
		object obj = ((_teamManagerInstance != null) ? Hook.Get(_teamManagerInstance, null) : null);
		if (obj == null || _giveTeamExp == null)
		{
			LastActionMessage = "Team XP could not be applied (TeamManager missing).";
			return;
		}
		if (_giveTeamExp.GetParameters().Length == 2)
		{
			Hook.Call(_giveTeamExp, obj, IndexValue.FromInt(TTeamIndex, 1), amount);
		}
		else
		{
			Hook.Call(_giveTeamExp, obj, IndexValue.FromInt(TTeamIndex, 1), (ulong)amount, true);
		}
		LastActionMessage = "Gave " + amount + " team XP.";
	}

	public static void QueuePlayer(Action action)
	{
		if (action != null)
		{
			_pendingPlayer.Add(action);
		}
	}

	public static void DrainPendingPlayer()
	{
		if (_pendingPlayer.Count == 0)
		{
			return;
		}
		Action[] array = _pendingPlayer.ToArray();
		_pendingPlayer.Clear();
		Action[] array2 = array;
		foreach (Action action in array2)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				LastActionMessage = "Player action failed: " + ex.Message;
				Log.Warn(LastActionMessage);
			}
		}
	}

	public static void QueueGive(Actor actor, int itemIndex, int count)
	{
		if (actor != null && count != 0)
		{
			_pendingGives.Add(new PendingGive
			{
				ActorId = actor.Id,
				NetId = NetId(actor),
				ItemIndex = itemIndex,
				Count = count
			});
		}
	}

	public static void DrainPendingGive()
	{
		if (_pendingGives.Count == 0)
		{
			return;
		}
		PendingGive[] array = _pendingGives.ToArray();
		_pendingGives.Clear();
		PendingGive[] array2 = array;
		for (int i = 0; i < array2.Length; i++)
		{
			PendingGive pendingGive = array2[i];
			Actor actor = FindPlayer(pendingGive.ActorId) ?? FindByNetId(pendingGive.NetId);
			if (actor == null && pendingGive.NetId == 0)
			{
				actor = LocalActor();
			}
			GiveItem(actor, pendingGive.ItemIndex, pendingGive.Count);
		}
	}

	public static void GiveItem(Actor actor, int itemIndex, int count)
	{
		if (actor == null || count == 0)
		{
			return;
		}
		if (!IsServer)
		{
			uint num = NetId(actor);
			if (num != 0)
			{
				CoOp.Submit("slipstream_item " + num + " " + itemIndex + " " + count);
				LastActionMessage = "Asked the host to grant ×" + count + ".";
				return;
			}
			if (!actor.IsLocal)
			{
				LastActionMessage = "Could not reach that player. Need a netId and the host running SlipStream.";
				return;
			}
		}
		GiveItemLocal(actor, itemIndex, count);
	}

	public static void GiveItemLocal(Actor actor, int itemIndex, int count)
	{
		object obj = InventoryOf(actor);
		if (obj == null)
		{
			LastActionMessage = "No inventory on " + (actor?.Name ?? "that player") + ".";
			Log.Warn(LastActionMessage + " master=" + UnityAlive(actor?.Master) + " body=" + UnityAlive(actor?.Body) + " TInventory=" + (TInventory != null));
		}
		else if (count != 0)
		{
			object index = IndexValue.FromInt(TItemIndex, itemIndex);
			bool flag = false;
			if (count > 0)
			{
				flag = InvokeInventory(obj, _giveItem, index, count);
			}
			else if (_removeItem != null)
			{
				flag = InvokeInventory(obj, _removeItem, index, -count);
			}
			if (!flag)
			{
				flag = TryWriteStacks(obj, itemIndex, count);
			}
			if (flag)
			{
				Hook.Call(_onInventoryChanged, obj);
				LastActionMessage = ((count > 0) ? "Gave ×" : "Removed ×") + Math.Abs(count) + " to " + actor.Name + ".";
				Log.Info(LastActionMessage + " itemIndex=" + itemIndex);
			}
			else
			{
				LastActionMessage = "Could not change inventory (GiveItem missing).";
				Log.Warn(LastActionMessage + " GiveItem=" + (_giveItem != null) + " stacks=" + (_itemStacks != null));
			}
		}
	}

	private static object InventoryOf(Actor actor)
	{
		if (actor == null)
		{
			return null;
		}
		if (UnityAlive(actor.Inventory))
		{
			return actor.Inventory;
		}
		object obj = null;
		if (UnityAlive(actor.Master))
		{
			if (_masterInventory != null)
			{
				obj = Hook.Get(_masterInventory, actor.Master);
			}
			if (!UnityAlive(obj))
			{
				obj = Bind(actor.Master, "inventory", "_inventory");
			}
			if (!UnityAlive(obj))
			{
				obj = ComponentOf(actor.Master, TInventory);
			}
		}
		if (!UnityAlive(obj) && UnityAlive(actor.Body))
		{
			if (_bodyInventory != null)
			{
				obj = Hook.Get(_bodyInventory, actor.Body);
			}
			if (!UnityAlive(obj))
			{
				obj = Bind(actor.Body, "inventory", "_inventory");
			}
			if (!UnityAlive(obj))
			{
				obj = ComponentOf(actor.Body, TInventory);
			}
		}
		if (!UnityAlive(obj) && UnityAlive(actor.Body) && !UnityAlive(actor.Master))
		{
			object obj2 = (actor.Master = Bind(actor.Body, "master", "_master") ?? ComponentOf(Bind(actor.Body, "masterObject", "_masterObject"), TCharacterMaster));
			if (UnityAlive(obj2))
			{
				obj = Bind(obj2, "inventory", "_inventory") ?? ComponentOf(obj2, TInventory);
			}
		}
		actor.Inventory = (UnityAlive(obj) ? obj : null);
		return actor.Inventory;
	}

	private static bool InvokeInventory(object inv, MethodInfo method, object index, int count)
	{
		if (inv == null || method == null)
		{
			return false;
		}
		try
		{
			ParameterInfo[] parameters = method.GetParameters();
			object obj = index;
			if (TItemDef != null && parameters.Length != 0 && parameters[0].ParameterType == TItemDef && _getItemDef != null)
			{
				obj = _getItemDef.Invoke(null, new object[1] { index });
			}
			else if (parameters.Length != 0)
			{
				obj = Hook.Coerce(index, parameters[0].ParameterType);
			}
			if (parameters.Length == 1)
			{
				method.Invoke(inv, new object[1] { obj });
			}
			else if (parameters.Length == 2)
			{
				method.Invoke(inv, new object[2]
				{
					obj,
					Hook.Coerce(count, parameters[1].ParameterType)
				});
			}
			else
			{
				if (parameters.Length < 3)
				{
					return false;
				}
				object obj2 = null;
				if (parameters[2].ParameterType == typeof(bool) || parameters[2].ParameterType == typeof(bool?))
				{
					obj2 = false;
				}
				else if (parameters[2].ParameterType.IsValueType)
				{
					obj2 = Activator.CreateInstance(parameters[2].ParameterType);
				}
				method.Invoke(inv, new object[3]
				{
					obj,
					Hook.Coerce(count, parameters[1].ParameterType),
					obj2
				});
			}
			return true;
		}
		catch (Exception ex)
		{
			Log.Warn(method.Name + " failed: " + (ex.InnerException ?? ex).Message);
			return false;
		}
	}

	private static bool TryWriteStacks(object inv, int itemIndex, int count)
	{
		if (inv == null || _itemStacks == null || itemIndex < 0)
		{
			return false;
		}
		object value = _itemStacks.GetValue(inv);
		if (value is int[] array)
		{
			if (itemIndex >= array.Length)
			{
				return false;
			}
			array[itemIndex] = Math.Max(0, array[itemIndex] + count);
			_itemStacks.SetValue(inv, array);
			return true;
		}
		if (value is Array array2 && itemIndex < array2.Length)
		{
			int num = Convert.ToInt32(array2.GetValue(itemIndex));
			array2.SetValue(Math.Max(0, num + count), itemIndex);
			return true;
		}
		return false;
	}

	public static int ItemCount(Actor actor, int itemIndex)
	{
		object obj = InventoryOf(actor);
		if (obj == null || _getItemCount == null)
		{
			return 0;
		}
		object obj2 = Hook.Call(_getItemCount, obj, IndexValue.FromInt(TItemIndex, itemIndex));
		if (obj2 != null)
		{
			return Convert.ToInt32(obj2);
		}
		return 0;
	}

	public static void ClearInventory(Actor actor)
	{
		if (actor != null && !CoOp.AskHost("slipstream_clear " + NetId(actor)))
		{
			ClearInventoryLocal(actor);
		}
	}

	public static void ClearInventoryLocal(Actor actor)
	{
		object obj = InventoryOf(actor);
		if (obj == null)
		{
			return;
		}
		foreach (CatalogItem item in Items())
		{
			int num = ItemCount(actor, item.Index);
			if (num > 0 && _removeItem != null)
			{
				Hook.Call(_removeItem, obj, IndexValue.FromInt(TItemIndex, item.Index), num);
			}
		}
		LastActionMessage = "Cleared inventory for " + actor.Name + ".";
	}

	public static void GiveAllItems(Actor actor, int stacks)
	{
		if (actor != null && !CoOp.AskHost("slipstream_giveall " + NetId(actor) + " " + stacks))
		{
			GiveAllItemsLocal(actor, stacks);
		}
	}

	public static void GiveAllItemsLocal(Actor actor, int stacks)
	{
		bool flag = default(bool);
		foreach (CatalogItem item in Items())
		{
			int num;
			if (item.Def != null && _itemHidden != null)
			{
				object value = _itemHidden.GetValue(item.Def);
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) == 0)
			{
				GiveItemLocal(actor, item.Index, stacks);
			}
		}
		LastActionMessage = "Gave all items ×" + stacks + " to " + actor.Name + ".";
	}

	public static void SetEquipment(Actor actor, int equipmentIndex)
	{
		if (actor != null && !CoOp.AskHost("slipstream_equip " + NetId(actor) + " " + equipmentIndex))
		{
			SetEquipmentLocal(actor, equipmentIndex);
		}
	}

	public static void SetEquipmentLocal(Actor actor, int equipmentIndex)
	{
		object obj = InventoryOf(actor);
		if (obj != null && !(_setEquipment == null))
		{
			object obj2 = IndexValue.FromInt(TEquipmentIndex, equipmentIndex);
			if (_setEquipment.GetParameters().Length == 1)
			{
				Hook.Call(_setEquipment, obj, obj2);
			}
			else
			{
				Hook.Call(_setEquipment, obj, obj2, false);
			}
		}
	}

	public static void SetBuff(Actor actor, int buffIndex, int count)
	{
		if (actor != null && !CoOp.AskHost("slipstream_buff " + NetId(actor) + " " + buffIndex + " " + count))
		{
			SetBuffLocal(actor, buffIndex, count);
		}
	}

	public static void SetBuffLocal(Actor actor, int buffIndex, int count)
	{
		if (actor == null || actor.Body == null)
		{
			return;
		}
		object obj = IndexValue.FromInt(TBuffIndex, buffIndex);
		if (_setBuffCount != null)
		{
			Hook.Call(_setBuffCount, actor.Body, obj, count);
		}
		else if (count > 0 && _addTimedBuff != null)
		{
			if (_addTimedBuff.GetParameters().Length == 2)
			{
				Hook.Call(_addTimedBuff, actor.Body, obj, 60f);
			}
			else
			{
				Hook.Call(_addTimedBuff, actor.Body, obj, count, 60f);
			}
		}
	}

	public static void Kill(object body)
	{
		if (body == null)
		{
			return;
		}
		object obj = ((_bodyHealth != null) ? Hook.Get(_bodyHealth, body) : null);
		if (obj == null)
		{
			Component val = (Component)((body is Component) ? body : null);
			if (val != null && THealthComponent != null)
			{
				obj = val.GetComponent(THealthComponent);
			}
		}
		if (obj != null && _suicide != null)
		{
			if (_suicide.GetParameters().Length == 0)
			{
				Hook.Call(_suicide, obj);
			}
			else
			{
				Hook.Call(_suicide, obj, null, null, null);
			}
		}
	}

	public static void KillAllMobs()
	{
		int num = 0;
		foreach (object item in Bodies())
		{
			if (TeamOf(item) != 1)
			{
				Kill(item);
				num++;
			}
		}
		LastActionMessage = "Killed " + num + " non-player bodies.";
		Log.Info(LastActionMessage);
	}

	public static void Revive(Actor actor)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		if (actor == null || actor.Master == null || CoOp.AskHost("slipstream_revive " + NetId(actor)))
		{
			return;
		}
		Vector3 val = (Object.op_Implicit((Object)(object)actor.Transform) ? actor.Transform.position : Vector3.zero);
		Quaternion val2 = (Object.op_Implicit((Object)(object)actor.Transform) ? actor.Transform.rotation : Quaternion.identity);
		if (_respawnAt != null)
		{
			if (_respawnAt.GetParameters().Length == 2)
			{
				Hook.Call(_respawnAt, actor.Master, val, val2);
			}
			else
			{
				Hook.Call(_respawnAt, actor.Master, val, val2, true);
			}
		}
		else if (_respawn != null)
		{
			Hook.Call(_respawn, actor.Master);
		}
		LastActionMessage = "Revived " + actor.Name + ".";
	}

	public static void Teleport(Actor actor, Vector3 position)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (actor != null && actor.Body != null)
		{
			if (_teleportBody != null)
			{
				Hook.Call(_teleportBody, actor.Body, position);
			}
			else if (Object.op_Implicit((Object)(object)actor.Transform))
			{
				actor.Transform.position = position;
			}
		}
	}

	public static void SpawnAs(Actor actor, GameObject bodyPrefab)
	{
		SpawnAsBody(actor, bodyPrefab);
	}

	public static void SpawnAsSurvivor(Actor actor, object survivorDef)
	{
		GameObject val = BodyPrefabOf(survivorDef);
		if (!Object.op_Implicit((Object)(object)val))
		{
			object obj = ((survivorDef is Object) ? survivorDef : null);
			LastActionMessage = "Could not resolve a body prefab for " + (((obj != null) ? ((Object)obj).name : null) ?? "that survivor") + ".";
			Log.Warn(LastActionMessage);
		}
		else
		{
			SpawnAsBody(actor, val);
		}
	}

	public static void SpawnAsNamed(Actor actor, string bodyName)
	{
		SpawnAsBody(actor, FindBodyPrefab(bodyName));
	}

	private static void SpawnAsBody(Actor actor, GameObject prefab)
	{
		if (actor == null || actor.Master == null)
		{
			LastActionMessage = "No player master to spawn as.";
			Log.Warn(LastActionMessage);
		}
		else if (!Object.op_Implicit((Object)(object)prefab))
		{
			LastActionMessage = "Body prefab was null.";
			Log.Warn(LastActionMessage);
		}
		else
		{
			if (CoOp.AskHost("slipstream_spawnas " + NetId(actor) + " " + ((Object)prefab).name))
			{
				return;
			}
			Log.Info("Spawn as " + ((Object)prefab).name + " on " + actor.Name + ".");
			bool flag = false;
			if (_transformBody != null)
			{
				try
				{
					ParameterInfo[] parameters = _transformBody.GetParameters();
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
					{
						Hook.Call(_transformBody, actor.Master, ((Object)prefab).name);
						flag = true;
					}
					else if (parameters.Length == 1)
					{
						Hook.Call(_transformBody, actor.Master, Hook.Coerce(prefab, parameters[0].ParameterType));
						flag = true;
					}
				}
				catch (Exception ex)
				{
					Log.Warn("TransformBody failed: " + (ex.InnerException ?? ex).Message);
				}
			}
			if (!flag)
			{
				if (_masterBodyPrefab != null)
				{
					Hook.Set(_masterBodyPrefab, actor.Master, prefab);
				}
				else if (_masterBodyPrefabField != null)
				{
					_masterBodyPrefabField.SetValue(actor.Master, prefab);
				}
				Revive(actor);
			}
			LastActionMessage = "Spawning as " + ((Object)prefab).name + ".";
			if (Session.ForcedTeam != int.MinValue)
			{
				ApplyTeamLocal(actor.IsLocal ? (LocalActor() ?? actor) : actor, Session.ForcedTeam);
			}
		}
	}

	public static string BodyDisplayName(Actor actor)
	{
		if (actor == null || actor.Body == null)
		{
			return null;
		}
		string text = ((_bodyNameToken != null) ? (Hook.Get(_bodyNameToken, actor.Body) as string) : null);
		string text2 = Localize(text);
		if (string.IsNullOrEmpty(text2) || text2 == text)
		{
			object body = actor.Body;
			object obj = ((body is Component) ? body : null);
			text2 = ((obj != null) ? ((Object)obj).name : null);
		}
		if (!string.IsNullOrEmpty(text2))
		{
			return text2;
		}
		return actor.Name;
	}

	public static int CurrentSkinIndex(Actor actor)
	{
		if (actor == null || actor.Body == null)
		{
			return -1;
		}
		Component val = ModelSkinOf(actor);
		if ((Object)(object)val != (Object)null && _mscCurrentSkin != null)
		{
			return IndexValue.ToInt(Hook.Get(_mscCurrentSkin, val));
		}
		if (_bodySkinIndex != null)
		{
			return IndexValue.ToInt(Hook.Get(_bodySkinIndex, actor.Body));
		}
		return -1;
	}

	public static List<CatalogItem> SkinsFor(Actor actor)
	{
		List<CatalogItem> list = new List<CatalogItem>();
		Array array = SkinArray(actor);
		if (array == null)
		{
			return list;
		}
		for (int i = 0; i < array.Length; i++)
		{
			object obj = null;
			try
			{
				obj = array.GetValue(i);
			}
			catch
			{
				continue;
			}
			if (obj != null)
			{
				list.Add(new CatalogItem
				{
					Index = i,
					Def = obj,
					Name = SkinDisplayName(obj, i)
				});
			}
		}
		return list;
	}

	public static void QueueSkin(Actor actor, int skinIndex)
	{
		if (actor != null && actor.Body != null && skinIndex >= 0)
		{
			Session.PendingSkinActorId = actor.Id;
			Session.PendingSkinIndex = skinIndex;
		}
	}

	public static void DrainPendingSkin()
	{
		if (Session.PendingSkinIndex >= 0 && !SkinBusy)
		{
			int pendingSkinActorId = Session.PendingSkinActorId;
			int pendingSkinIndex = Session.PendingSkinIndex;
			Session.PendingSkinIndex = -1;
			ApplySkin(FindPlayer(pendingSkinActorId) ?? LocalActor(), pendingSkinIndex);
		}
	}

	public static void ApplySkin(Actor actor, int skinIndex)
	{
		if (actor == null || actor.Body == null || skinIndex < 0 || SkinBusy)
		{
			return;
		}
		Array array = SkinArray(actor);
		if (array == null || skinIndex >= array.Length)
		{
			Log.Warn("No skins array for this body.");
			return;
		}
		Component val = ModelSkinOf(actor);
		if ((Object)(object)val == (Object)null)
		{
			Log.Warn("No ModelSkinController on this body.");
			return;
		}
		_skinBusy = true;
		_skinBusyUntil = Time.unscaledTime + 12f;
		Log.Info("Applying skin " + skinIndex + " on " + actor.Name + ".");
		SlipstreamPlugin.Run(ApplySkinRoutine(actor, skinIndex, val));
	}

	private static IEnumerator ApplySkinRoutine(Actor actor, int skinIndex, object msc)
	{
		yield return null;
		object started = null;
		try
		{
			started = InvokeApplySkinAsync(msc, skinIndex);
		}
		catch (Exception ex)
		{
			Log.Warn("ApplySkinAsync threw: " + (ex.InnerException ?? ex).Message);
		}
		if (started == null)
		{
			Log.Warn("ApplySkinAsync did not start. SkinDef.Apply was not used.");
			_skinBusy = false;
			yield break;
		}
		Log.Info("ApplySkinAsync started for skin " + skinIndex + " (" + started.GetType().Name + ").");
		if (started is IEnumerator routine)
		{
			float until = Time.unscaledTime + 12f;
			while (routine.MoveNext() && !(Time.unscaledTime > until))
			{
				yield return routine.Current;
			}
		}
		else
		{
			IEnumerator pump = UniTaskToCoroutine(started);
			float until = Time.unscaledTime + 10f;
			if (pump != null)
			{
				while (pump.MoveNext() && !(Time.unscaledTime > until))
				{
					yield return pump.Current;
				}
			}
			else
			{
				ForgetUniTask(started);
				while (Time.unscaledTime < until && !UniTaskCompleted(started))
				{
					yield return null;
				}
			}
		}
		WriteSkinLoadout(actor, skinIndex);
		if (IsServer)
		{
			PushLoadout(actor);
		}
		else
		{
			CoOp.Submit("slipstream_skin " + NetId(actor) + " " + skinIndex);
		}
		_skinBusy = false;
		Log.Info("Skin " + skinIndex + " apply finished.");
	}

	private static void PushLoadout(Actor actor)
	{
		if (actor == null || actor.Master == null || _setLoadoutServer == null)
		{
			return;
		}
		try
		{
			object obj = ((_masterLoadout != null) ? Hook.Get(_masterLoadout, actor.Master) : Bind(actor.Master, "loadout", "_loadout"));
			if (obj != null)
			{
				Hook.Call(_setLoadoutServer, actor.Master, obj);
			}
		}
		catch (Exception ex)
		{
			Log.Warn("SetLoadoutServer skipped: " + ex.Message);
		}
	}

	private static object InvokeApplySkinAsync(object msc, int skinIndex)
	{
		if (msc == null || TModelSkinController == null)
		{
			return null;
		}
		MethodInfo methodInfo = null;
		MethodInfo methodInfo2 = null;
		MethodInfo[] methods = TModelSkinController.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo3 in methods)
		{
			if (methodInfo3.Name != "ApplySkinAsync" || methodInfo3.IsGenericMethod)
			{
				continue;
			}
			ParameterInfo[] parameters = methodInfo3.GetParameters();
			if (parameters.Length >= 1 && parameters.Length <= 2)
			{
				if (typeof(IEnumerator).IsAssignableFrom(methodInfo3.ReturnType))
				{
					methodInfo = methodInfo3;
				}
				else
				{
					methodInfo2 = methodInfo3;
				}
			}
		}
		MethodInfo methodInfo4 = methodInfo ?? methodInfo2 ?? _applySkinAsync;
		if (methodInfo4 == null)
		{
			return null;
		}
		try
		{
			object[] array = ArgsForApplySkinAsync(methodInfo4, skinIndex);
			if (array == null)
			{
				return null;
			}
			Log.Info("Invoking " + methodInfo4);
			return methodInfo4.Invoke(msc, array);
		}
		catch (Exception ex)
		{
			Log.Warn("ApplySkinAsync failed: " + (ex.InnerException ?? ex).Message);
			return null;
		}
	}

	private static object[] ArgsForApplySkinAsync(MethodInfo method, int skinIndex)
	{
		ParameterInfo[] parameters = method.GetParameters();
		if (parameters.Length < 1 || parameters.Length > 2)
		{
			return null;
		}
		object[] array = new object[parameters.Length];
		for (int i = 0; i < parameters.Length; i++)
		{
			Type parameterType = parameters[i].ParameterType;
			if (parameterType == typeof(int) || parameterType == typeof(uint) || (parameterType.IsEnum && parameterType.Name.IndexOf("Unload", StringComparison.OrdinalIgnoreCase) < 0))
			{
				array[i] = Hook.Coerce(skinIndex, parameterType);
			}
			else if (parameterType.IsEnum)
			{
				array[i] = ParseNamedEnum(parameterType, "OnRunEnd", "AtWill", "OnSceneUnload");
			}
			else if (parameterType.IsValueType)
			{
				array[i] = Activator.CreateInstance(parameterType);
			}
			else
			{
				array[i] = null;
			}
		}
		return array;
	}

	private static object ParseNamedEnum(Type type, params string[] names)
	{
		if (type == null || !type.IsEnum)
		{
			return null;
		}
		foreach (string value in names)
		{
			try
			{
				return Enum.Parse(type, value);
			}
			catch
			{
			}
		}
		return Enum.ToObject(type, 0);
	}

	private static void ForgetUniTask(object task)
	{
		if (task == null)
		{
			return;
		}
		Type type = task.GetType();
		string[] array = new string[2] { "Cysharp.Threading.Tasks.UniTaskExtensions", "Cysharp.Threading.Tasks.UniTask" };
		for (int i = 0; i < array.Length; i++)
		{
			Type type2 = Hook.Type(array[i]);
			if (type2 == null)
			{
				continue;
			}
			MethodInfo[] methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "Forget")
				{
					continue;
				}
				try
				{
					MethodInfo methodInfo2 = (methodInfo.IsGenericMethod ? methodInfo.MakeGenericMethod(type) : methodInfo);
					if (methodInfo2.GetParameters().Length == 1)
					{
						methodInfo2.Invoke(null, new object[1] { task });
						return;
					}
				}
				catch
				{
				}
			}
		}
	}

	private static IEnumerator UniTaskToCoroutine(object task)
	{
		if (task == null)
		{
			yield break;
		}
		IEnumerator inner = null;
		Type type = task.GetType();
		Type type2 = Hook.Type("Cysharp.Threading.Tasks.UniTaskExtensions");
		if (type2 != null)
		{
			MethodInfo[] methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "ToCoroutine" || methodInfo.GetParameters().Length != 1)
				{
					continue;
				}
				try
				{
					MethodInfo methodInfo2 = methodInfo;
					if (!methodInfo.IsGenericMethod)
					{
						goto IL_00b6;
					}
					if (!type.IsGenericType)
					{
						continue;
					}
					methodInfo2 = methodInfo.MakeGenericMethod(type.GetGenericArguments());
					goto IL_00b6;
					IL_00b6:
					if (methodInfo2.Invoke(null, new object[1] { task }) is IEnumerator enumerator)
					{
						inner = enumerator;
						break;
					}
				}
				catch (Exception ex)
				{
					Log.Warn("ToCoroutine skipped: " + (ex.InnerException ?? ex).Message);
				}
			}
		}
		if (inner != null)
		{
			while (inner.MoveNext())
			{
				yield return inner.Current;
			}
			yield break;
		}
		ForgetUniTask(task);
		float until = Time.unscaledTime + 10f;
		while (Time.unscaledTime < until && !UniTaskCompleted(task))
		{
			yield return null;
		}
	}

	private static bool UniTaskCompleted(object task)
	{
		if (task == null)
		{
			return true;
		}
		object obj = Hook.Get(Hook.Member(task.GetType(), "Status", "status"), task);
		if (obj == null)
		{
			return false;
		}
		try
		{
			return Convert.ToInt32(obj) != 0;
		}
		catch
		{
			return false;
		}
	}

	private static string SkinDisplayName(object def, int index)
	{
		string text = ((_skinNameToken != null) ? (_skinNameToken.GetValue(def) as string) : null);
		string text2 = Localize(text);
		if (string.IsNullOrEmpty(text2) || text2 == text)
		{
			object obj = ((def is Object) ? def : null);
			text2 = ((obj != null) ? ((Object)obj).name : null);
		}
		if (!string.IsNullOrEmpty(text2))
		{
			return text2;
		}
		return "Skin " + index;
	}

	private static object BodyIndexOf(Actor actor)
	{
		if (actor == null || actor.Body == null || _bodyIndex == null)
		{
			return null;
		}
		return Hook.Get(_bodyIndex, actor.Body);
	}

	private static Component ModelSkinOf(Actor actor)
	{
		object obj = actor?.Body;
		Component val = (Component)((obj is Component) ? obj : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return null;
		}
		if (TModelLocator != null)
		{
			Component component = val.GetComponent(TModelLocator);
			if (Object.op_Implicit((Object)(object)component))
			{
				object obj2 = Bind(component, "modelTransform", "_modelTransform");
				Transform val2 = (Transform)((obj2 is Transform) ? obj2 : null);
				if (Object.op_Implicit((Object)(object)val2) && TModelSkinController != null)
				{
					Component component2 = ((Component)val2).GetComponent(TModelSkinController);
					if (Object.op_Implicit((Object)(object)component2))
					{
						return component2;
					}
				}
			}
		}
		if (TModelSkinController != null)
		{
			Component componentInChildren = val.GetComponentInChildren(TModelSkinController, true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				return componentInChildren;
			}
		}
		return null;
	}

	private static Array SkinArray(Actor actor)
	{
		Component val = ModelSkinOf(actor);
		if ((Object)(object)val != (Object)null && _mscSkins != null && _mscSkins.GetValue(val) is Array { Length: >0 } array)
		{
			return array;
		}
		object obj = BodyIndexOf(actor);
		if (obj == null)
		{
			return null;
		}
		if (_getBodySkins != null)
		{
			try
			{
				ParameterInfo[] parameters = _getBodySkins.GetParameters();
				object obj2 = obj;
				if (parameters.Length == 1)
				{
					obj2 = Hook.Coerce(obj, parameters[0].ParameterType);
				}
				if (_getBodySkins.Invoke(null, new object[1] { obj2 }) is Array { Length: >0 } array2)
				{
					return array2;
				}
			}
			catch
			{
			}
		}
		if (_catalogSkins?.GetValue(null) is Array array3)
		{
			try
			{
				int num = IndexValue.ToInt(obj);
				if (num >= 0 && num < array3.Length && array3.GetValue(num) is Array { Length: >0 } array4)
				{
					return array4;
				}
			}
			catch
			{
			}
		}
		return null;
	}

	private static void WriteSkinLoadout(Actor actor, int skinIndex)
	{
		if (actor.Master == null)
		{
			return;
		}
		try
		{
			object obj = ((_masterLoadout != null) ? Hook.Get(_masterLoadout, actor.Master) : Bind(actor.Master, "loadout", "_loadout"));
			object obj2 = ((obj != null && _loadoutBodyManager != null) ? _loadoutBodyManager.GetValue(obj) : null);
			object obj3 = BodyIndexOf(actor