Decompiled source of LCBridge v1.1.2

BepInEx/plugins/LCBridge.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LCBridge.Patches;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LCBridge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("LCBridge")]
[assembly: AssemblyTitle("LCBridge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LCBridge
{
	public static class BridgeServer
	{
		private static TcpListener _listener;

		private static Thread _acceptThread;

		private static volatile bool _running;

		private static readonly List<TcpClient> _clients = new List<TcpClient>();

		private static readonly object _lock = new object();

		public static void Start(int port)
		{
			if (!_running)
			{
				_running = true;
				_listener = new TcpListener(IPAddress.Loopback, port);
				_listener.Start();
				_acceptThread = new Thread(AcceptLoop)
				{
					IsBackground = true,
					Name = "LCBridge-Accept"
				};
				_acceptThread.Start();
			}
		}

		public static void Stop()
		{
			_running = false;
			try
			{
				_listener?.Stop();
			}
			catch
			{
			}
			lock (_lock)
			{
				foreach (TcpClient client in _clients)
				{
					try
					{
						client.Close();
					}
					catch
					{
					}
				}
				_clients.Clear();
			}
		}

		private static void AcceptLoop()
		{
			while (_running)
			{
				try
				{
					TcpClient tcpClient = _listener.AcceptTcpClient();
					if (Handshake(tcpClient))
					{
						lock (_lock)
						{
							_clients.Add(tcpClient);
						}
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogInfo((object)"Оверлей подключился к мосту.");
						}
					}
					else
					{
						try
						{
							tcpClient.Close();
						}
						catch
						{
						}
					}
				}
				catch
				{
					if (!_running)
					{
						break;
					}
				}
			}
		}

		private static bool Handshake(TcpClient client)
		{
			try
			{
				NetworkStream stream = client.GetStream();
				byte[] array = new byte[4096];
				int num = stream.Read(array, 0, array.Length);
				if (num <= 0)
				{
					return false;
				}
				string text = Encoding.UTF8.GetString(array, 0, num);
				string text2 = null;
				string[] array2 = text.Split(new string[1] { "\r\n" }, StringSplitOptions.None);
				foreach (string text3 in array2)
				{
					if (text3.StartsWith("Sec-WebSocket-Key:", StringComparison.OrdinalIgnoreCase))
					{
						text2 = text3.Substring("Sec-WebSocket-Key:".Length).Trim();
						break;
					}
				}
				if (text2 == null)
				{
					return false;
				}
				string text4;
				using (SHA1 sHA = SHA1.Create())
				{
					text4 = Convert.ToBase64String(sHA.ComputeHash(Encoding.UTF8.GetBytes(text2 + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")));
				}
				string s = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + text4 + "\r\n\r\n";
				byte[] bytes = Encoding.UTF8.GetBytes(s);
				stream.Write(bytes, 0, bytes.Length);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static void Broadcast(string text)
		{
			byte[] array = EncodeTextFrame(text);
			List<TcpClient> list = null;
			lock (_lock)
			{
				foreach (TcpClient client in _clients)
				{
					try
					{
						if (!client.Connected)
						{
							(list ?? (list = new List<TcpClient>())).Add(client);
						}
						else
						{
							client.GetStream().Write(array, 0, array.Length);
						}
					}
					catch
					{
						(list ?? (list = new List<TcpClient>())).Add(client);
					}
				}
				if (list == null)
				{
					return;
				}
				foreach (TcpClient item in list)
				{
					_clients.Remove(item);
					try
					{
						item.Close();
					}
					catch
					{
					}
				}
			}
		}

		private static byte[] EncodeTextFrame(string text)
		{
			byte[] bytes = Encoding.UTF8.GetBytes(text);
			int num = bytes.Length;
			byte[] array;
			if (num <= 125)
			{
				array = new byte[2]
				{
					0,
					(byte)num
				};
			}
			else if (num <= 65535)
			{
				array = new byte[4]
				{
					0,
					126,
					(byte)((num >> 8) & 0xFF),
					(byte)(num & 0xFF)
				};
			}
			else
			{
				array = new byte[10] { 0, 127, 0, 0, 0, 0, 0, 0, 0, 0 };
				for (int i = 0; i < 8; i++)
				{
					array[9 - i] = (byte)((num >> 8 * i) & 0xFF);
				}
			}
			array[0] = 129;
			byte[] array2 = new byte[array.Length + bytes.Length];
			Buffer.BlockCopy(array, 0, array2, 0, array.Length);
			Buffer.BlockCopy(bytes, 0, array2, array.Length, bytes.Length);
			return array2;
		}
	}
	public class BridgeTicker : MonoBehaviour
	{
		private float _timer;

		private const float Interval = 1f;

		private string _lastPayload;

		private int _lastMobCount = -1;

		private void Update()
		{
			_timer += Time.deltaTime;
			if (!(_timer < 1f))
			{
				_timer = 0f;
				GameState.TickStats();
				RunStats.Tick();
				string text = BuildJson();
				if (text != _lastPayload)
				{
					_lastPayload = text;
					BridgeServer.Broadcast(text);
				}
			}
		}

		private string BuildJson()
		{
			(int alive, int total) crew = GameState.GetCrew();
			int item = crew.alive;
			int item2 = crew.total;
			int deaths = GameState.GetDeaths();
			int localHealth = GameState.GetLocalHealth();
			string moonName = GameState.GetMoonName();
			string weatherTweaksWeather = GameState.GetWeatherTweaksWeather();
			string s = ((!string.IsNullOrEmpty(weatherTweaksWeather)) ? weatherTweaksWeather : GameState.GetVanillaWeather());
			string brutalEvent = GameState.GetBrutalEvent();
			(List<string> outside, List<string> inside) monsters = GameState.GetMonsters();
			List<string> item3 = monsters.outside;
			List<string> item4 = monsters.inside;
			List<string> traps = GameState.GetTraps();
			bool onMoon = GameState.GetOnMoon();
			bool loading = GameState.GetLoading();
			bool inGame = GameState.GetInGame();
			int resetToken = GameState.GetResetToken();
			int levelScrap = GameState.GetLevelScrap();
			string topKiller = GameState.GetTopKiller();
			string topMonster = GameState.GetTopMonster();
			string deadliestEvent = GameState.GetDeadliestEvent();
			int num = item3.Count + item4.Count;
			if (num != _lastMobCount)
			{
				_lastMobCount = num;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("[monsters] улица={0} ({1}) | комплекс={2} ({3})", item3.Count, string.Join(",", item3), item4.Count, string.Join(",", item4)));
				}
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('{');
			stringBuilder.Append("\"type\":\"bridge\",");
			stringBuilder.Append("\"deaths\":").Append(deaths).Append(',');
			stringBuilder.Append("\"alive\":").Append(item).Append(',');
			stringBuilder.Append("\"total\":").Append(item2).Append(',');
			stringBuilder.Append("\"health\":").Append(localHealth).Append(',');
			stringBuilder.Append("\"moonName\":").Append(JsonStr(moonName)).Append(',');
			stringBuilder.Append("\"weatherFull\":").Append(JsonStr(s)).Append(',');
			stringBuilder.Append("\"brutalEvent\":").Append(JsonStr(brutalEvent ?? "")).Append(',');
			stringBuilder.Append("\"onMoon\":").Append(onMoon ? "true" : "false").Append(',');
			stringBuilder.Append("\"loading\":").Append(loading ? "true" : "false").Append(',');
			stringBuilder.Append("\"inGame\":").Append(inGame ? "true" : "false").Append(',');
			stringBuilder.Append("\"resetToken\":").Append(resetToken).Append(',');
			stringBuilder.Append("\"levelScrap\":").Append(levelScrap).Append(',');
			stringBuilder.Append("\"topKiller\":").Append(JsonStr(topKiller ?? "")).Append(',');
			stringBuilder.Append("\"topMonster\":").Append(JsonStr(topMonster ?? "")).Append(',');
			stringBuilder.Append("\"deadliestEvent\":").Append(JsonStr(deadliestEvent ?? "")).Append(',');
			stringBuilder.Append("\"monstersOutside\":").Append(JsonArr(item3)).Append(',');
			stringBuilder.Append("\"monstersInside\":").Append(JsonArr(item4)).Append(',');
			stringBuilder.Append("\"traps\":").Append(JsonArr(traps)).Append(',');
			stringBuilder.Append("\"run\":").Append(RunStats.ToJson());
			stringBuilder.Append('}');
			return stringBuilder.ToString();
		}

		private static string JsonArr(List<string> items)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('[');
			for (int i = 0; i < items.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append(JsonStr(items[i]));
			}
			stringBuilder.Append(']');
			return stringBuilder.ToString();
		}

		private static string JsonStr(string s)
		{
			if (s == null)
			{
				return "\"\"";
			}
			StringBuilder stringBuilder = new StringBuilder(s.Length + 2);
			stringBuilder.Append('"');
			foreach (char c in s)
			{
				switch (c)
				{
				case '"':
					stringBuilder.Append("\\\"");
					continue;
				case '\\':
					stringBuilder.Append("\\\\");
					continue;
				case '\n':
					stringBuilder.Append("\\n");
					continue;
				case '\r':
					stringBuilder.Append("\\r");
					continue;
				case '\t':
					stringBuilder.Append("\\t");
					continue;
				}
				if (c < ' ')
				{
					StringBuilder stringBuilder2 = stringBuilder.Append("\\u");
					int num = c;
					stringBuilder2.Append(num.ToString("x4", CultureInfo.InvariantCulture));
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			stringBuilder.Append('"');
			return stringBuilder.ToString();
		}
	}
	internal static class EnemyResolver
	{
		private static readonly string[] _turretMarkers = new string[3] { "ToilHeadController", "MantiToilController", "TurretHeadController" };

		private static readonly string[] _slayerMarkers = new string[3] { "ToilSlayerController", "MantiSlayerController", "SlayerController" };

		public static string Resolve(object enemyAiObj)
		{
			string baseName = GetBaseName(enemyAiObj);
			if (string.IsNullOrEmpty(baseName))
			{
				return null;
			}
			try
			{
				switch (TurretKind(enemyAiObj))
				{
				case 2:
					return baseName + "+Turret+Slayer";
				case 1:
					return baseName + "+Turret";
				}
			}
			catch
			{
			}
			return baseName;
		}

		private static string GetBaseName(object enemyAiObj)
		{
			try
			{
				EnemyAI val = (EnemyAI)((enemyAiObj is EnemyAI) ? enemyAiObj : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.enemyType != (Object)null && !string.IsNullOrEmpty(val.enemyType.enemyName))
				{
					return val.enemyType.enemyName;
				}
			}
			catch
			{
			}
			return null;
		}

		private static int TurretKind(object enemyAiObj)
		{
			MonoBehaviour val = (MonoBehaviour)((enemyAiObj is MonoBehaviour) ? enemyAiObj : null);
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			Component[] componentsInChildren = ((Component)val).GetComponentsInChildren<Component>(true);
			if (componentsInChildren == null)
			{
				return 0;
			}
			int num = 0;
			Component[] array = componentsInChildren;
			foreach (Component val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				string name = ((object)val2).GetType().Name;
				if (string.IsNullOrEmpty(name))
				{
					continue;
				}
				string[] slayerMarkers = _slayerMarkers;
				foreach (string value in slayerMarkers)
				{
					if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 2;
					}
				}
				if (num != 0)
				{
					continue;
				}
				slayerMarkers = _turretMarkers;
				foreach (string value2 in slayerMarkers)
				{
					if (name.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						num = 1;
						break;
					}
				}
			}
			return num;
		}
	}
	public static class GameState
	{
		private static int _deaths = 0;

		private static readonly HashSet<int> _deadThisRound = new HashSet<int>();

		private static int _resetToken = 0;

		private static readonly Dictionary<string, int> _killerCounts = new Dictionary<string, int>();

		private static readonly Dictionary<string, int> _eventDeaths = new Dictionary<string, int>();

		private static readonly Dictionary<string, int> _monsterSeen = new Dictionary<string, int>();

		private static int _landedScrap;

		private static bool _wasLanded;

		private static bool _scrapLocked;

		private static Type _emType;

		private static FieldInfo _curEventsField;

		private static bool _bcSearched;

		private static readonly Dictionary<Type, MethodInfo> _nameMethodCache = new Dictionary<Type, MethodInfo>();

		private static Type _wtVarsType;

		private static MethodInfo _wtGetCurrent;

		private static bool _wtSearched;

		public static int GetResetToken()
		{
			return _resetToken;
		}

		public static void RegisterDeath(PlayerControllerB p, string killer = null)
		{
			bool flag = false;
			try
			{
				int item = (int)p.playerClientId;
				if (_deadThisRound.Add(item))
				{
					_deaths++;
					flag = true;
				}
			}
			catch
			{
				_deaths++;
				flag = true;
			}
			if (!flag)
			{
				return;
			}
			try
			{
				if (!string.IsNullOrEmpty(killer))
				{
					_killerCounts.TryGetValue(killer, out var value);
					_killerCounts[killer] = value + 1;
				}
				string brutalEvent = GetBrutalEvent();
				if (!string.IsNullOrEmpty(brutalEvent) && brutalEvent != "—")
				{
					_eventDeaths.TryGetValue(brutalEvent, out var value2);
					_eventDeaths[brutalEvent] = value2 + 1;
				}
				RunStats.OnDeath(killer);
			}
			catch
			{
			}
		}

		public static void OnNewRound()
		{
			_deadThisRound.Clear();
		}

		public static void ResetDeaths()
		{
			_deaths = 0;
			_deadThisRound.Clear();
			_resetToken++;
			_killerCounts.Clear();
			_eventDeaths.Clear();
			_monsterSeen.Clear();
			RunStats.ResetRun();
		}

		public static int GetDeaths()
		{
			return _deaths;
		}

		public static void TickStats()
		{
			try
			{
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null)
				{
					return;
				}
				HashSet<string> hashSet = new HashSet<string>();
				foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies)
				{
					if (!((Object)(object)spawnedEnemy == (Object)null) && !spawnedEnemy.isEnemyDead)
					{
						string text = EnemyResolver.Resolve(spawnedEnemy);
						if (text != null)
						{
							hashSet.Add(text);
						}
					}
				}
				foreach (string item in hashSet)
				{
					_monsterSeen.TryGetValue(item, out var value);
					_monsterSeen[item] = value + 1;
				}
			}
			catch
			{
			}
		}

		private static string TopOf(Dictionary<string, int> dict)
		{
			string result = null;
			int num = 0;
			foreach (KeyValuePair<string, int> item in dict)
			{
				if (item.Value > num)
				{
					num = item.Value;
					result = item.Key;
				}
			}
			return result;
		}

		public static string GetTopKiller()
		{
			return TopOf(_killerCounts);
		}

		public static string GetTopMonster()
		{
			return TopOf(_monsterSeen);
		}

		public static string GetDeadliestEvent()
		{
			return TopOf(_eventDeaths);
		}

		public static (int alive, int total) GetCrew()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return (alive: 0, total: 0);
				}
				int num = 0;
				int num2 = 0;
				PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					if (!((Object)(object)val == (Object)null) && (val.isPlayerControlled || val.isPlayerDead))
					{
						num++;
						if (!val.isPlayerDead)
						{
							num2++;
						}
					}
				}
				if (num == 0)
				{
					num = 1;
				}
				return (alive: num2, total: num);
			}
			catch
			{
				return (alive: 0, total: 0);
			}
		}

		public static int GetLocalHealth()
		{
			try
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val == (Object)null)
				{
					return 0;
				}
				return val.health;
			}
			catch
			{
				return 0;
			}
		}

		public static (List<string> outside, List<string> inside) GetMonsters()
		{
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			try
			{
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null)
				{
					return (outside: list, inside: list2);
				}
				Dictionary<string, int> dictionary = new Dictionary<string, int>();
				Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
				foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies)
				{
					if ((Object)(object)spawnedEnemy == (Object)null || spawnedEnemy.isEnemyDead)
					{
						continue;
					}
					string key = "Unknown";
					try
					{
						string text = EnemyResolver.Resolve(spawnedEnemy);
						if (!string.IsNullOrEmpty(text))
						{
							key = text;
						}
					}
					catch
					{
					}
					Dictionary<string, int> obj2 = (spawnedEnemy.isOutside ? dictionary : dictionary2);
					obj2.TryGetValue(key, out var value);
					obj2[key] = value + 1;
				}
				foreach (KeyValuePair<string, int> item in dictionary)
				{
					list.Add((item.Value > 1) ? $"{item.Key} x{item.Value}" : item.Key);
				}
				foreach (KeyValuePair<string, int> item2 in dictionary2)
				{
					list2.Add((item2.Value > 1) ? $"{item2.Key} x{item2.Value}" : item2.Key);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("GetMonsters fail: " + ex.Message));
				}
			}
			return (outside: list, inside: list2);
		}

		public static List<string> GetTraps()
		{
			List<string> list = new List<string>();
			try
			{
				Dictionary<string, int> counts = new Dictionary<string, int>();
				CountType<Turret>("Turret");
				CountType<Landmine>("Landmine");
				CountType<SpikeRoofTrap>("Spike Trap");
				foreach (KeyValuePair<string, int> item in counts)
				{
					list.Add((item.Value > 1) ? $"{item.Key} x{item.Value}" : item.Key);
				}
				void CountType<T>(string label) where T : Object
				{
					try
					{
						T[] array = Object.FindObjectsOfType<T>();
						if (array != null && array.Length != 0)
						{
							counts.TryGetValue(label, out var value);
							counts[label] = value + array.Length;
						}
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("GetTraps fail: " + ex.Message));
				}
			}
			return list;
		}

		public static int GetLevelScrap()
		{
			try
			{
				RoundManager instance = RoundManager.Instance;
				if (GetOnMoon())
				{
					if (!_wasLanded)
					{
						_wasLanded = true;
						_scrapLocked = false;
						_landedScrap = 0;
					}
					if (!_scrapLocked && (Object)(object)instance != (Object)null)
					{
						int num = (int)instance.totalScrapValueInLevel;
						if (num > 0)
						{
							_landedScrap = num;
							_scrapLocked = true;
						}
					}
				}
				else
				{
					_wasLanded = false;
					_scrapLocked = false;
					_landedScrap = 0;
				}
				return _landedScrap;
			}
			catch
			{
				return _landedScrap;
			}
		}

		private static string GetEventName(object ev)
		{
			Type type = ev.GetType();
			if (!_nameMethodCache.TryGetValue(type, out var value))
			{
				value = type.GetMethod("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				_nameMethodCache[type] = value;
			}
			if (value != null)
			{
				try
				{
					return value.Invoke(ev, null) as string;
				}
				catch
				{
				}
			}
			return ExtractName(ev);
		}

		public static string GetBrutalEvent()
		{
			try
			{
				if (!_bcSearched)
				{
					_bcSearched = true;
					_emType = FindTypeByFullName("BrutalCompanyMinus.Minus.EventManager") ?? FindTypeFuzzy("BrutalCompany", new string[1] { "EventManager" });
					if (_emType != null)
					{
						_curEventsField = _emType.GetField("currentEvents", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogInfo((object)("[reflection] BCMER EventManager=" + _emType.FullName + ", currentEvents field=" + ((_curEventsField != null) ? "OK" : "НЕ НАЙДЕНО")));
						}
					}
					else
					{
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogInfo((object)"[reflection] BCMER EventManager не найден (мод выключен?)");
						}
					}
				}
				if (_curEventsField == null)
				{
					return null;
				}
				if (!(_curEventsField.GetValue(null) is IEnumerable enumerable))
				{
					return null;
				}
				List<string> list = new List<string>();
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						string eventName = GetEventName(item);
						if (!string.IsNullOrEmpty(eventName))
						{
							list.Add(eventName);
						}
					}
				}
				if (list.Count == 0)
				{
					return null;
				}
				return string.Join(", ", list);
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogDebug((object)("GetBrutalEvent fail: " + ex.Message));
				}
				return null;
			}
		}

		public static string GetWeatherTweaksWeather()
		{
			try
			{
				if (!_wtSearched)
				{
					_wtSearched = true;
					_wtVarsType = FindTypeByFullName("WeatherTweaks.Variables") ?? FindTypeFuzzy("WeatherTweaks", new string[1] { "Variables" });
					if (_wtVarsType != null)
					{
						_wtGetCurrent = _wtVarsType.GetMethod("GetCurrentWeather", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogInfo((object)("[reflection] WeatherTweaks Variables=" + _wtVarsType.FullName + ", GetCurrentWeather=" + ((_wtGetCurrent != null) ? "OK" : "НЕ НАЙДЕНО")));
						}
					}
					else
					{
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogInfo((object)"[reflection] WeatherTweaks Variables не найден (мод выключен?)");
						}
					}
				}
				if (_wtGetCurrent == null)
				{
					return null;
				}
				object obj = _wtGetCurrent.Invoke(null, null);
				if (obj == null)
				{
					return null;
				}
				string text = ExtractName(obj);
				return string.IsNullOrEmpty(text) ? null : text;
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogDebug((object)("GetWeatherTweaks fail: " + ex.Message));
				}
				return null;
			}
		}

		public static string GetVanillaWeather()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.currentLevel == (Object)null)
				{
					return "None";
				}
				return ((object)Unsafe.As<LevelWeatherType, LevelWeatherType>(ref instance.currentLevel.currentWeather)/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return "None";
			}
		}

		public static string GetMoonName()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.currentLevel == (Object)null)
				{
					return "—";
				}
				return instance.currentLevel.PlanetName;
			}
			catch
			{
				return "—";
			}
		}

		public static bool GetOnMoon()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.currentLevel == (Object)null)
				{
					return false;
				}
				if (!instance.shipHasLanded)
				{
					return false;
				}
				string text = (instance.currentLevel.PlanetName ?? "").ToLowerInvariant();
				if (text.Contains("gordion") || text.Contains("company"))
				{
					return false;
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static bool GetLoading()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				return instance.travellingToNewLevel;
			}
			catch
			{
				return false;
			}
		}

		public static bool GetInGame()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				return instance.shipHasLanded || instance.travellingToNewLevel;
			}
			catch
			{
				return false;
			}
		}

		public static int GetDayCount()
		{
			try
			{
				TimeOfDay instance = TimeOfDay.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return 1;
				}
				return (instance.daysUntilDeadline < 0) ? 1 : (3 - instance.daysUntilDeadline);
			}
			catch
			{
				return 1;
			}
		}

		public static int GetQuotaIndexSafe()
		{
			try
			{
				TimeOfDay instance = TimeOfDay.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return 1;
				}
				return instance.timesFulfilledQuota + 1;
			}
			catch
			{
				return 1;
			}
		}

		public static int GetShipScrapSafe()
		{
			try
			{
				int num = 0;
				GameObject[] array = GameObject.FindGameObjectsWithTag("PhysicsProp");
				for (int i = 0; i < array.Length; i++)
				{
					GrabbableObject component = array[i].GetComponent<GrabbableObject>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.itemProperties == (Object)null) && component.itemProperties.isScrap && (component.isInShipRoom || component.isInElevator))
					{
						num += component.scrapValue;
					}
				}
				return num;
			}
			catch
			{
				return 0;
			}
		}

		public static List<KeyValuePair<int, int>> GetShipScrapItems()
		{
			List<KeyValuePair<int, int>> list = new List<KeyValuePair<int, int>>();
			try
			{
				GameObject[] array = GameObject.FindGameObjectsWithTag("PhysicsProp");
				for (int i = 0; i < array.Length; i++)
				{
					GrabbableObject component = array[i].GetComponent<GrabbableObject>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.itemProperties == (Object)null) && component.itemProperties.isScrap && (component.isInShipRoom || component.isInElevator))
					{
						list.Add(new KeyValuePair<int, int>(((Object)component).GetInstanceID(), component.scrapValue));
					}
				}
			}
			catch
			{
			}
			return list;
		}

		public static List<KeyValuePair<int, string>> GetMonsterInstances()
		{
			List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
			try
			{
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null)
				{
					return list;
				}
				foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies)
				{
					if (!((Object)(object)spawnedEnemy == (Object)null) && !spawnedEnemy.isEnemyDead)
					{
						string text = EnemyResolver.Resolve(spawnedEnemy);
						if (text != null)
						{
							list.Add(new KeyValuePair<int, string>(((Object)spawnedEnemy).GetInstanceID(), text));
						}
					}
				}
			}
			catch
			{
			}
			return list;
		}

		public static (List<string> outside, List<string> inside) GetMonstersRaw()
		{
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			try
			{
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null)
				{
					return (outside: list, inside: list2);
				}
				foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies)
				{
					if (!((Object)(object)spawnedEnemy == (Object)null) && !spawnedEnemy.isEnemyDead)
					{
						string text = EnemyResolver.Resolve(spawnedEnemy);
						if (text != null)
						{
							(spawnedEnemy.isOutside ? list : list2).Add(text);
						}
					}
				}
			}
			catch
			{
			}
			return (outside: list, inside: list2);
		}

		public static bool GetInsideFactorySafe()
		{
			try
			{
				PlayerControllerB val = StartOfRound.Instance?.localPlayerController;
				return (Object)(object)val != (Object)null && val.isInsideFactory;
			}
			catch
			{
				return false;
			}
		}

		private static Type FindTypeByFullName(string fullName)
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					Type type = null;
					try
					{
						type = assembly.GetType(fullName, throwOnError: false);
					}
					catch
					{
					}
					if (type != null)
					{
						return type;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static Type FindTypeFuzzy(string asmNameContains, string[] typeNameCandidates)
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					string text = assembly.GetName().Name ?? "";
					if (text.IndexOf(asmNameContains, StringComparison.OrdinalIgnoreCase) < 0)
					{
						continue;
					}
					Type[] source;
					try
					{
						source = assembly.GetTypes();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = ex.Types.Where((Type t) => t != null).ToArray();
					}
					foreach (string cand in typeNameCandidates)
					{
						Type type = source.FirstOrDefault((Type t) => string.Equals(t.Name, cand, StringComparison.OrdinalIgnoreCase));
						if (type != null)
						{
							ManualLogSource log = Plugin.Log;
							if (log != null)
							{
								log.LogInfo((object)("[reflection] нашёл тип " + type.FullName + " в " + text));
							}
							return type;
						}
					}
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("FindTypeFuzzy fail: " + ex2.Message));
				}
			}
			return null;
		}

		private static object ReadStaticMember(Type t, string name)
		{
			try
			{
				FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					if (field.IsStatic)
					{
						return field.GetValue(null);
					}
					object singletonInstance = GetSingletonInstance(t);
					if (singletonInstance != null)
					{
						return field.GetValue(singletonInstance);
					}
				}
				PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					MethodInfo? getMethod = property.GetGetMethod(nonPublic: true);
					if ((object)getMethod != null && getMethod.IsStatic)
					{
						return property.GetValue(null);
					}
					object singletonInstance2 = GetSingletonInstance(t);
					if (singletonInstance2 != null)
					{
						return property.GetValue(singletonInstance2);
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static object GetSingletonInstance(Type t)
		{
			try
			{
				PropertyInfo propertyInfo = t.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public) ?? t.GetProperty("instance", BindingFlags.Static | BindingFlags.Public);
				if (propertyInfo != null)
				{
					return propertyInfo.GetValue(null);
				}
				FieldInfo fieldInfo = t.GetField("Instance", BindingFlags.Static | BindingFlags.Public) ?? t.GetField("instance", BindingFlags.Static | BindingFlags.Public);
				if (fieldInfo != null)
				{
					return fieldInfo.GetValue(null);
				}
			}
			catch
			{
			}
			return null;
		}

		private static string ExtractName(object val)
		{
			if (val == null)
			{
				return null;
			}
			try
			{
				if (val is string result)
				{
					return result;
				}
				if (val.GetType().IsEnum)
				{
					return val.ToString();
				}
				Type type = val.GetType();
				PropertyInfo propertyInfo = type.GetProperty("Name") ?? type.GetProperty("name");
				if (propertyInfo != null)
				{
					string text = propertyInfo.GetValue(val) as string;
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
				FieldInfo fieldInfo = type.GetField("Name") ?? type.GetField("name");
				if (fieldInfo != null)
				{
					string text2 = fieldInfo.GetValue(val) as string;
					if (!string.IsNullOrEmpty(text2))
					{
						return text2;
					}
				}
				string text3 = val.ToString();
				if (!string.IsNullOrEmpty(text3) && text3 != type.FullName && text3 != type.Name)
				{
					return text3;
				}
			}
			catch
			{
			}
			return null;
		}
	}
	[BepInPlugin("gdlp.lcbridge", "LCBridge", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "gdlp.lcbridge";

		public const string NAME = "LCBridge";

		public const string VERSION = "1.1.0";

		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			int value = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "WebSocketPort", 8181, "Порт WebSocket-сервера моста. Оверлей должен слушать этот же порт.").Value;
			Log.LogInfo((object)"LCBridge v1.1.0 запускается...");
			_harmony = new Harmony("gdlp.lcbridge");
			_harmony.PatchAll(typeof(PlayerControllerB_Patches));
			_harmony.PatchAll(typeof(StartOfRound_Patches));
			Log.LogInfo((object)"Harmony-патчи применены.");
			try
			{
				BridgeServer.Start(value);
				Log.LogInfo((object)$"WebSocket-сервер моста запущен на ws://localhost:{value}");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Не удалось запустить сервер: {arg}");
			}
			((Component)this).gameObject.AddComponent<BridgeTicker>();
			Log.LogInfo((object)"LCBridge готов.");
		}

		private void OnDestroy()
		{
			try
			{
				BridgeServer.Stop();
			}
			catch
			{
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class RunStats
	{
		public class QuotaSlice
		{
			public int index;

			public int scrapStart;

			public int scrapEnd;

			public int seconds;

			public int deaths;
		}

		private class MoonStat
		{
			public int visits;

			public int profit;

			public int seconds;
		}

		private static readonly List<QuotaSlice> _quotas = new List<QuotaSlice>();

		private static QuotaSlice _curQuota;

		private static int _lastQuotaIndex = -1;

		private static readonly Dictionary<string, MoonStat> _moons = new Dictionary<string, MoonStat>();

		private static string _curMoon;

		private static int _moonScrapStart;

		private static readonly Dictionary<string, int> _monsterTime = new Dictionary<string, int>();

		private static readonly Dictionary<string, int> _monsterCount = new Dictionary<string, int>();

		private static readonly HashSet<int> _seenMonsterIds = new HashSet<int>();

		private static int _peakMonsters;

		private static readonly Dictionary<int, int> _collectedScrap = new Dictionary<int, int>();

		private static int _secInside;

		private static int _secOutside;

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

		private static int _lastDayLogged = -1;

		private static string _lastEventLogged;

		private static int _runSeconds;

		public static void ResetRun()
		{
			_quotas.Clear();
			_curQuota = null;
			_lastQuotaIndex = -1;
			_moons.Clear();
			_curMoon = null;
			_moonScrapStart = 0;
			_monsterTime.Clear();
			_peakMonsters = 0;
			_monsterCount.Clear();
			_seenMonsterIds.Clear();
			_collectedScrap.Clear();
			_secInside = 0;
			_secOutside = 0;
			_timeline.Clear();
			_lastDayLogged = -1;
			_lastEventLogged = null;
			_runSeconds = 0;
		}

		public static void OnDeath(string killer)
		{
			try
			{
				int dayCount = GameState.GetDayCount();
				string moonName = GameState.GetMoonName();
				string arg = (string.IsNullOrEmpty(killer) ? "?" : killer);
				_timeline.Add($"{dayCount}|death|{arg}@{moonName}");
				if (_curQuota != null)
				{
					_curQuota.deaths++;
				}
			}
			catch
			{
			}
		}

		public static void Tick()
		{
			try
			{
				if (!GameState.GetInGame())
				{
					return;
				}
				_runSeconds++;
				int dayCount = GameState.GetDayCount();
				int quotaIndexSafe = GameState.GetQuotaIndexSafe();
				bool onMoon = GameState.GetOnMoon();
				string moonName = GameState.GetMoonName();
				string brutalEvent = GameState.GetBrutalEvent();
				foreach (KeyValuePair<int, int> shipScrapItem in GameState.GetShipScrapItems())
				{
					if (!_collectedScrap.ContainsKey(shipScrapItem.Key))
					{
						_collectedScrap[shipScrapItem.Key] = shipScrapItem.Value;
					}
				}
				int num = 0;
				foreach (int value in _collectedScrap.Values)
				{
					num += value;
				}
				if (quotaIndexSafe != _lastQuotaIndex)
				{
					if (_curQuota != null)
					{
						_curQuota.scrapEnd = num;
						_quotas.Add(_curQuota);
					}
					_curQuota = new QuotaSlice
					{
						index = quotaIndexSafe,
						scrapStart = num,
						scrapEnd = num,
						seconds = 0,
						deaths = 0
					};
					_lastQuotaIndex = quotaIndexSafe;
				}
				if (_curQuota != null)
				{
					_curQuota.seconds++;
					_curQuota.scrapEnd = num;
				}
				if (onMoon && !string.IsNullOrEmpty(moonName))
				{
					if (_curMoon != moonName)
					{
						_curMoon = moonName;
						_moonScrapStart = num;
						if (!_moons.ContainsKey(moonName))
						{
							_moons[moonName] = new MoonStat();
						}
						_moons[moonName].visits++;
					}
					MoonStat moonStat = _moons[moonName];
					moonStat.seconds++;
					int num2 = num - _moonScrapStart;
					if (num2 > 0)
					{
						moonStat.profit += num2;
						_moonScrapStart = num;
					}
				}
				else
				{
					_curMoon = null;
				}
				List<KeyValuePair<int, string>> monsterInstances = GameState.GetMonsterInstances();
				foreach (KeyValuePair<int, string> item in monsterInstances)
				{
					Add(_monsterTime, item.Value);
					if (_seenMonsterIds.Add(item.Key))
					{
						Add(_monsterCount, item.Value);
					}
				}
				int count = monsterInstances.Count;
				if (count > _peakMonsters)
				{
					_peakMonsters = count;
				}
				if (onMoon)
				{
					if (GameState.GetInsideFactorySafe())
					{
						_secInside++;
					}
					else
					{
						_secOutside++;
					}
				}
				if (dayCount != _lastDayLogged && dayCount > 0)
				{
					_lastDayLogged = dayCount;
					_timeline.Add($"{dayCount}|day|{moonName}");
				}
				if (!string.IsNullOrEmpty(brutalEvent) && brutalEvent != "—" && brutalEvent != _lastEventLogged)
				{
					_lastEventLogged = brutalEvent;
					_timeline.Add($"{dayCount}|event|{brutalEvent}");
				}
			}
			catch
			{
			}
		}

		private static void Add(Dictionary<string, int> d, string k)
		{
			if (!string.IsNullOrEmpty(k))
			{
				d.TryGetValue(k, out var value);
				d[k] = value + 1;
			}
		}

		public static string ToJson()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append('{');
				stringBuilder.Append("\"quotas\":[");
				List<QuotaSlice> list = new List<QuotaSlice>(_quotas);
				if (_curQuota != null)
				{
					list.Add(_curQuota);
				}
				for (int i = 0; i < list.Count; i++)
				{
					QuotaSlice quotaSlice = list[i];
					if (i > 0)
					{
						stringBuilder.Append(',');
					}
					int value = Math.Max(0, quotaSlice.scrapEnd - quotaSlice.scrapStart);
					stringBuilder.Append('{').Append("\"i\":").Append(quotaSlice.index)
						.Append(',')
						.Append("\"money\":")
						.Append(value)
						.Append(',')
						.Append("\"sec\":")
						.Append(quotaSlice.seconds)
						.Append(',')
						.Append("\"deaths\":")
						.Append(quotaSlice.deaths)
						.Append('}');
				}
				stringBuilder.Append("],");
				stringBuilder.Append("\"moons\":[");
				int num = 0;
				foreach (KeyValuePair<string, MoonStat> item in _moons.OrderByDescending((KeyValuePair<string, MoonStat> x) => x.Value.profit))
				{
					if (num++ > 0)
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append('{').Append("\"name\":").Append(JsonStr(item.Key))
						.Append(',')
						.Append("\"visits\":")
						.Append(item.Value.visits)
						.Append(',')
						.Append("\"profit\":")
						.Append(item.Value.profit)
						.Append(',')
						.Append("\"sec\":")
						.Append(item.Value.seconds)
						.Append('}');
				}
				stringBuilder.Append("],");
				stringBuilder.Append("\"monsters\":[");
				int num2 = 0;
				foreach (KeyValuePair<string, int> item2 in _monsterCount.OrderByDescending((KeyValuePair<string, int> x) => x.Value).Take(20))
				{
					if (num2++ > 0)
					{
						stringBuilder.Append(',');
					}
					_monsterTime.TryGetValue(item2.Key, out var value2);
					stringBuilder.Append('{').Append("\"name\":").Append(JsonStr(item2.Key))
						.Append(',')
						.Append("\"count\":")
						.Append(item2.Value)
						.Append(',')
						.Append("\"sec\":")
						.Append(value2)
						.Append('}');
				}
				stringBuilder.Append("],");
				stringBuilder.Append("\"peak\":").Append(_peakMonsters).Append(',');
				stringBuilder.Append("\"inside\":").Append(_secInside).Append(',');
				stringBuilder.Append("\"outside\":").Append(_secOutside).Append(',');
				stringBuilder.Append("\"runSec\":").Append(_runSeconds).Append(',');
				stringBuilder.Append("\"timeline\":[");
				for (int num3 = 0; num3 < _timeline.Count && num3 < 60; num3++)
				{
					if (num3 > 0)
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append(JsonStr(_timeline[num3]));
				}
				stringBuilder.Append(']');
				stringBuilder.Append('}');
				return stringBuilder.ToString();
			}
			catch
			{
				return "{}";
			}
		}

		private static string JsonStr(string s)
		{
			if (s == null)
			{
				return "\"\"";
			}
			StringBuilder stringBuilder = new StringBuilder("\"");
			foreach (char c in s)
			{
				switch (c)
				{
				case '"':
				case '\\':
					stringBuilder.Append('\\').Append(c);
					break;
				case '\n':
				case '\r':
					stringBuilder.Append(' ');
					break;
				default:
					stringBuilder.Append(c);
					break;
				}
			}
			stringBuilder.Append('"');
			return stringBuilder.ToString();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "LCBridge";

		public const string PLUGIN_NAME = "LCBridge";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace LCBridge.Patches
{
	[HarmonyPatch(typeof(PlayerControllerB))]
	public static class PlayerControllerB_Patches
	{
		[HarmonyPatch("KillPlayer")]
		[HarmonyPostfix]
		public static void OnKillPlayer(PlayerControllerB __instance, CauseOfDeath causeOfDeath)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)null && __instance.isPlayerDead)
			{
				string killer = ResolveKiller(__instance, causeOfDeath);
				GameState.RegisterDeath(__instance, killer);
			}
		}

		private static string ResolveKiller(PlayerControllerB player, CauseOfDeath cause)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected I4, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((int)cause != 2)
				{
					switch (cause - 5)
					{
					case 4:
						return "Утопление";
					case 0:
						return "Удушье";
					case 8:
						return "Огонь";
					case 6:
						return "Ток";
					case 3:
						return "Раздавлен";
					default:
					{
						RoundManager instance = RoundManager.Instance;
						if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null)
						{
							return "Неизвестно";
						}
						Vector3 position = ((Component)player).transform.position;
						float num = 25f;
						string text = null;
						foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies)
						{
							if (!((Object)(object)spawnedEnemy == (Object)null) && !spawnedEnemy.isEnemyDead)
							{
								float num2 = Vector3.Distance(position, ((Component)spawnedEnemy).transform.position);
								if (num2 < num)
								{
									num = num2;
									text = EnemyResolver.Resolve(spawnedEnemy);
								}
							}
						}
						return string.IsNullOrEmpty(text) ? "Неизвестно" : text;
					}
					}
				}
				return "Падение";
			}
			catch
			{
				return "Неизвестно";
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public static class StartOfRound_Patches
	{
		[HarmonyPatch("ResetShip")]
		[HarmonyPostfix]
		public static void OnResetShip()
		{
			GameState.ResetDeaths();
		}

		[HarmonyPatch("SetTimeAndPlanetToSavedSettings")]
		[HarmonyPostfix]
		public static void OnLoadSavedSettings()
		{
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if (!((Object)(object)instance == (Object)null) && ((instance.gameStats != null && instance.gameStats.daysSpent <= 0) || ((Object)(object)TimeOfDay.Instance != (Object)null && TimeOfDay.Instance.timesFulfilledQuota <= 0 && TimeOfDay.Instance.daysUntilDeadline >= 3)))
				{
					GameState.ResetDeaths();
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch("StartGame")]
		[HarmonyPostfix]
		public static void OnStartGame()
		{
			GameState.OnNewRound();
		}
	}
}