Decompiled source of MegabonkMultiplayer v1.0.0

plugins\MegabonkMultiplayer.dll

Decompiled 11 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
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("MegabonkMultiplayer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Multiplayer mod for Megabonk")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ba547804f6d0d6662dd32230fb2a96b9f0759923")]
[assembly: AssemblyProduct("MegabonkMultiplayer")]
[assembly: AssemblyTitle("MegabonkMultiplayer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MegabonkMultiplayer
{
	public class ChestSyncManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <AnimateItemText>d__22 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public GameObject textObject;

			private Vector3 <startPos>5__2;

			private Vector3 <endPos>5__3;

			private float <duration>5__4;

			private float <t>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AnimateItemText>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				//IL_004f: 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_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<startPos>5__2 = textObject.transform.position;
					<endPos>5__3 = <startPos>5__2 + Vector3.up * 2f;
					<duration>5__4 = 2f;
					<t>5__5 = 0f;
					break;
				case 2:
					<>1__state = -1;
					<t>5__5 += Time.deltaTime;
					break;
				}
				if (<t>5__5 < <duration>5__4)
				{
					float num = <t>5__5 / <duration>5__4;
					textObject.transform.position = Vector3.Lerp(<startPos>5__2, <endPos>5__3, num);
					TextMesh component = textObject.GetComponent<TextMesh>();
					if ((Object)(object)component != (Object)null)
					{
						Color color = component.color;
						color.a = 1f - num;
						component.color = color;
					}
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				Object.Destroy((Object)(object)textObject);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <AnimateOpenedByText>d__23 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public GameObject textObject;

			private float <duration>5__2;

			private float <t>5__3;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AnimateOpenedByText>d__23(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<duration>5__2 = 3f;
					_ = textObject.transform.position;
					<t>5__3 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<t>5__3 += Time.deltaTime;
					break;
				}
				if (<t>5__3 < <duration>5__2)
				{
					float num = <t>5__3 / <duration>5__2;
					TextMesh component = textObject.GetComponent<TextMesh>();
					if ((Object)(object)component != (Object)null)
					{
						Color color = component.color;
						color.a = 1f - num;
						component.color = color;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				Object.Destroy((Object)(object)textObject);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static ChestSyncManager instance;

		private Dictionary<string, ChestData> chests = new Dictionary<string, ChestData>();

		private float lastChestSync;

		private const float CHEST_SYNC_INTERVAL = 5f;

		public static ChestSyncManager Instance => instance;

		private void Awake()
		{
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void Start()
		{
			if ((Object)(object)NetworkManager.Instance != (Object)null)
			{
				NetworkManager.Instance.OnMessageReceived += HandleNetworkMessage;
			}
		}

		private void Update()
		{
			if (NetworkManager.Instance.IsHost && Time.time - lastChestSync >= 5f)
			{
				ScanForNewChests();
				lastChestSync = Time.time;
			}
		}

		private void HandleNetworkMessage(NetworkMessage message)
		{
			string messageType = message.MessageType;
			if (!(messageType == "ChestSpawnMessage"))
			{
				if (messageType == "ChestOpenedMessage")
				{
					HandleChestOpenedMessage(message as ChestOpenedMessage);
				}
			}
			else
			{
				HandleChestSpawnMessage(message as ChestSpawnMessage);
			}
		}

		private void HandleChestSpawnMessage(ChestSpawnMessage message)
		{
			if (!NetworkManager.Instance.IsHost)
			{
				CreateRemoteChest(message);
			}
		}

		private void HandleChestOpenedMessage(ChestOpenedMessage message)
		{
			ProcessChestOpening(message);
		}

		public void RegisterChestSpawn(GameObject chest)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkManager.Instance.IsHost)
			{
				string text = Guid.NewGuid().ToString();
				Vector3 position = chest.transform.position;
				ChestType chestType = DetermineChestType(chest);
				int cost = CalculateChestCost(chestType);
				string[] items = GenerateChestItems(chestType);
				ChestData value = new ChestData
				{
					ChestId = text,
					GameObject = chest,
					Position = position,
					Type = chestType,
					Cost = cost,
					Items = items,
					IsOpened = false,
					OpenedByPlayerId = ""
				};
				chests[text] = value;
				ChestSpawnMessage message = new ChestSpawnMessage
				{
					ChestId = text,
					Position = position,
					ChestType = chestType.ToString(),
					Cost = cost,
					Items = items
				};
				NetworkManager.Instance.SendMessage(message);
			}
		}

		public bool TryOpenChest(GameObject chest, string playerId)
		{
			string text = FindChestId(chest);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			ChestData chestData = chests[text];
			if (chestData.IsOpened)
			{
				return false;
			}
			if (!CanPlayerAffordChest(playerId, chestData.Cost))
			{
				ShowInsufficientFundsMessage(playerId);
				return false;
			}
			chestData.IsOpened = true;
			chestData.OpenedByPlayerId = playerId;
			DeductCostFromPlayer(playerId, chestData.Cost);
			GiveItemsToPlayer(playerId, chestData.Items);
			ChestOpenedMessage message = new ChestOpenedMessage
			{
				ChestId = text,
				OpenedByPlayerId = playerId,
				ItemsReceived = chestData.Items
			};
			NetworkManager.Instance.SendMessage(message);
			UpdateChestVisual(chest, isOpened: true);
			return true;
		}

		private void CreateRemoteChest(ChestSpawnMessage message)
		{
			//IL_0022: 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)
			GameObject gameObject = CreateRemoteChestVisual(message);
			ChestData value = new ChestData
			{
				ChestId = message.ChestId,
				GameObject = gameObject,
				Position = message.Position,
				Type = (ChestType)Enum.Parse(typeof(ChestType), message.ChestType),
				Cost = message.Cost,
				Items = message.Items,
				IsOpened = false,
				OpenedByPlayerId = ""
			};
			chests[message.ChestId] = value;
		}

		private void ProcessChestOpening(ChestOpenedMessage message)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (chests.ContainsKey(message.ChestId))
			{
				ChestData chestData = chests[message.ChestId];
				chestData.IsOpened = true;
				chestData.OpenedByPlayerId = message.OpenedByPlayerId;
				if ((Object)(object)chestData.GameObject != (Object)null)
				{
					UpdateChestVisual(chestData.GameObject, isOpened: true);
				}
				ShowChestOpeningEffect(chestData.Position, message.ItemsReceived, message.OpenedByPlayerId);
				if (message.OpenedByPlayerId == GetLocalPlayerId())
				{
					GiveItemsToPlayer(message.OpenedByPlayerId, message.ItemsReceived);
				}
			}
		}

		private void ScanForNewChests()
		{
			GameObject[] array = GameObject.FindGameObjectsWithTag("Chest");
			foreach (GameObject chest in array)
			{
				if (string.IsNullOrEmpty(FindChestId(chest)))
				{
					RegisterChestSpawn(chest);
				}
			}
		}

		private GameObject CreateRemoteChestVisual(ChestSpawnMessage message)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = "RemoteChest_" + message.ChestId;
			val.transform.position = message.Position;
			val.transform.localScale = new Vector3(1f, 0.5f, 1f);
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				Material val2 = new Material(Shader.Find("Standard"));
				val2.color = GetChestTypeColor(message.ChestType);
				component.material = val2;
			}
			CreateChestCostDisplay(val, message.Cost);
			ChestInteraction chestInteraction = val.AddComponent<ChestInteraction>();
			chestInteraction.ChestId = message.ChestId;
			chestInteraction.Cost = message.Cost;
			chestInteraction.Items = message.Items;
			return val;
		}

		private void CreateChestCostDisplay(GameObject chest, int cost)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			GameObject val = new GameObject("CostDisplay");
			val.transform.SetParent(chest.transform);
			val.transform.localPosition = Vector3.up * 1.5f;
			TextMesh obj = val.AddComponent<TextMesh>();
			obj.text = $"{cost} Gold";
			obj.fontSize = 16;
			obj.color = Color.yellow;
			obj.anchor = (TextAnchor)4;
		}

		private void UpdateChestVisual(GameObject chest, bool isOpened)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)chest == (Object)null) && isOpened)
			{
				Renderer component = chest.GetComponent<Renderer>();
				if ((Object)(object)component != (Object)null)
				{
					component.material.color = Color.gray;
				}
				Transform val = chest.transform.Find("CostDisplay");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
				ChestInteraction component2 = chest.GetComponent<ChestInteraction>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Behaviour)component2).enabled = false;
				}
			}
		}

		private void ShowChestOpeningEffect(Vector3 position, string[] items, string playerId)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_003e: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ChestOpenEffect");
			val.transform.position = position + Vector3.up;
			for (int i = 0; i < items.Length; i++)
			{
				GameObject val2 = new GameObject($"ItemText_{i}");
				val2.transform.position = position + Vector3.up * (2f + (float)i * 0.5f);
				TextMesh obj = val2.AddComponent<TextMesh>();
				obj.text = items[i];
				obj.color = GetItemRarityColor(items[i]);
				obj.fontSize = 12;
				obj.anchor = (TextAnchor)4;
				((MonoBehaviour)this).StartCoroutine(AnimateItemText(val2, (float)i * 0.2f));
			}
			ShowChestOpenedByText(position, playerId);
			Object.Destroy((Object)(object)val, 3f);
		}

		private void ShowChestOpenedByText(Vector3 position, string playerId)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("OpenedByText");
			val.transform.position = position + Vector3.up * 3f;
			TextMesh obj = val.AddComponent<TextMesh>();
			obj.text = "Opened by Player " + playerId.Substring(0, 8);
			obj.color = Color.cyan;
			obj.fontSize = 10;
			obj.anchor = (TextAnchor)4;
			((MonoBehaviour)this).StartCoroutine(AnimateOpenedByText(val));
		}

		[IteratorStateMachine(typeof(<AnimateItemText>d__22))]
		private IEnumerator AnimateItemText(GameObject textObject, float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AnimateItemText>d__22(0)
			{
				textObject = textObject,
				delay = delay
			};
		}

		[IteratorStateMachine(typeof(<AnimateOpenedByText>d__23))]
		private IEnumerator AnimateOpenedByText(GameObject textObject)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AnimateOpenedByText>d__23(0)
			{
				textObject = textObject
			};
		}

		private ChestType DetermineChestType(GameObject chest)
		{
			string text = ((Object)chest).name.ToLower();
			if (text.Contains("legendary"))
			{
				return ChestType.Legendary;
			}
			if (text.Contains("epic"))
			{
				return ChestType.Epic;
			}
			if (text.Contains("rare"))
			{
				return ChestType.Rare;
			}
			return ChestType.Common;
		}

		private int CalculateChestCost(ChestType chestType)
		{
			int connectedPlayerCount = NetworkManager.Instance.ConnectedPlayerCount;
			return Mathf.RoundToInt((float)(chestType switch
			{
				ChestType.Common => 10, 
				ChestType.Rare => 25, 
				ChestType.Epic => 50, 
				ChestType.Legendary => 100, 
				_ => 10, 
			}) * (1f + (float)(connectedPlayerCount - 1) * 0.1f));
		}

		private string[] GenerateChestItems(ChestType chestType)
		{
			List<string> list = new List<string>();
			switch (chestType)
			{
			case ChestType.Common:
				list.Add("Health Potion");
				list.Add("10 Gold");
				break;
			case ChestType.Rare:
				list.Add("Mana Potion");
				list.Add("Iron Sword");
				list.Add("25 Gold");
				break;
			case ChestType.Epic:
				list.Add("Magic Ring");
				list.Add("Steel Armor");
				list.Add("50 Gold");
				break;
			case ChestType.Legendary:
				list.Add("Legendary Weapon");
				list.Add("Ancient Artifact");
				list.Add("100 Gold");
				break;
			}
			return list.ToArray();
		}

		private Color GetChestTypeColor(string chestType)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0059: 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_0061: 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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(chestType.ToLower() switch
			{
				"common" => new Color(0.6f, 0.3f, 0.1f), 
				"rare" => Color.blue, 
				"epic" => Color.magenta, 
				"legendary" => Color.yellow, 
				_ => Color.gray, 
			});
		}

		private Color GetItemRarityColor(string item)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			if (item.Contains("Legendary"))
			{
				return Color.yellow;
			}
			if (item.Contains("Epic") || item.Contains("Ancient"))
			{
				return Color.magenta;
			}
			if (item.Contains("Magic") || item.Contains("Steel"))
			{
				return Color.blue;
			}
			return Color.white;
		}

		private bool CanPlayerAffordChest(string playerId, int cost)
		{
			return GetPlayerGold(playerId) >= cost;
		}

		private void DeductCostFromPlayer(string playerId, int cost)
		{
			int playerGold = GetPlayerGold(playerId);
			SetPlayerGold(playerId, playerGold - cost);
		}

		private void GiveItemsToPlayer(string playerId, string[] items)
		{
			foreach (string text in items)
			{
				Debug.Log((object)("Giving " + text + " to player " + playerId));
			}
		}

		private void ShowInsufficientFundsMessage(string playerId)
		{
			if (playerId == GetLocalPlayerId())
			{
				Debug.Log((object)"Insufficient gold to open this chest!");
			}
		}

		private string FindChestId(GameObject chest)
		{
			return chests.FirstOrDefault((KeyValuePair<string, ChestData> kvp) => (Object)(object)kvp.Value.GameObject == (Object)(object)chest).Key;
		}

		private string GetLocalPlayerId()
		{
			return SystemInfo.deviceUniqueIdentifier;
		}

		private int GetPlayerGold(string playerId)
		{
			return 100;
		}

		private void SetPlayerGold(string playerId, int gold)
		{
		}

		public int GetTotalChestCount()
		{
			return chests.Count;
		}

		public int GetAvailableChestCount()
		{
			return chests.Values.Count((ChestData c) => !c.IsOpened);
		}

		public List<ChestData> GetAllChests()
		{
			return chests.Values.ToList();
		}

		public ChestData GetChestData(string chestId)
		{
			if (!chests.ContainsKey(chestId))
			{
				return null;
			}
			return chests[chestId];
		}
	}
	public enum ChestType
	{
		Common,
		Rare,
		Epic,
		Legendary
	}
	[Serializable]
	public class ChestData
	{
		public string ChestId;

		public GameObject GameObject;

		public Vector3 Position;

		public ChestType Type;

		public int Cost;

		public string[] Items;

		public bool IsOpened;

		public string OpenedByPlayerId;
	}
	public class ChestInteraction : MonoBehaviour
	{
		public string ChestId;

		public int Cost;

		public string[] Items;

		private void OnMouseDown()
		{
			if ((Object)(object)ChestSyncManager.Instance != (Object)null)
			{
				string deviceUniqueIdentifier = SystemInfo.deviceUniqueIdentifier;
				ChestSyncManager.Instance.TryOpenChest(((Component)this).gameObject, deviceUniqueIdentifier);
			}
		}

		private void OnTriggerEnter(Collider other)
		{
			if (((Component)other).CompareTag("Player"))
			{
				ShowInteractionPrompt(show: true);
			}
		}

		private void OnTriggerExit(Collider other)
		{
			if (((Component)other).CompareTag("Player"))
			{
				ShowInteractionPrompt(show: false);
			}
		}

		private void ShowInteractionPrompt(bool show)
		{
			Debug.Log((object)(show ? $"Press E to open chest (Cost: {Cost} Gold)" : ""));
		}
	}
	public class EnemyScalingManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <DeathAnimation>d__25 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public GameObject enemy;

			private float <duration>5__2;

			private Vector3 <originalScale>5__3;

			private float <t>5__4;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DeathAnimation>d__25(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: 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)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<duration>5__2 = 1f;
					<originalScale>5__3 = enemy.transform.localScale;
					<t>5__4 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<t>5__4 += Time.deltaTime;
					break;
				}
				if (<t>5__4 < <duration>5__2)
				{
					float num = <t>5__4 / <duration>5__2;
					enemy.transform.localScale = Vector3.Lerp(<originalScale>5__3, Vector3.zero, num);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				Object.Destroy((Object)(object)enemy);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <RemoveEnemyDelayed>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public EnemyScalingManager <>4__this;

			public string enemyId;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RemoveEnemyDelayed>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Expected O, but got Unknown
				int num = <>1__state;
				EnemyScalingManager enemyScalingManager = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					enemyScalingManager.RemoveEnemy(enemyId);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static EnemyScalingManager instance;

		private Dictionary<string, EnemyData> enemies = new Dictionary<string, EnemyData>();

		private float lastEnemySync;

		private const float ENEMY_SYNC_INTERVAL = 2f;

		public static EnemyScalingManager Instance => instance;

		private void Awake()
		{
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void Start()
		{
			if ((Object)(object)NetworkManager.Instance != (Object)null)
			{
				NetworkManager.Instance.OnMessageReceived += HandleNetworkMessage;
			}
		}

		private void Update()
		{
			if (NetworkManager.Instance.IsHost && Time.time - lastEnemySync >= 2f)
			{
				SyncAllEnemies();
				lastEnemySync = Time.time;
			}
		}

		private void HandleNetworkMessage(NetworkMessage message)
		{
			string messageType = message.MessageType;
			if (!(messageType == "EnemySpawnMessage"))
			{
				if (messageType == "EnemyUpdateMessage")
				{
					HandleEnemyUpdateMessage(message as EnemyUpdateMessage);
				}
			}
			else
			{
				HandleEnemySpawnMessage(message as EnemySpawnMessage);
			}
		}

		private void HandleEnemySpawnMessage(EnemySpawnMessage message)
		{
			if (!NetworkManager.Instance.IsHost)
			{
				SpawnRemoteEnemy(message);
			}
		}

		private void HandleEnemyUpdateMessage(EnemyUpdateMessage message)
		{
			UpdateRemoteEnemy(message);
		}

		public void RegisterEnemySpawn(GameObject enemy, string enemyType)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkManager.Instance.IsHost)
			{
				string text = Guid.NewGuid().ToString();
				int connectedPlayerCount = NetworkManager.Instance.ConnectedPlayerCount;
				float value = MegabonkMultiplayerPlugin.EnemyScalingFactor.Value;
				EnemyStats originalEnemyStats = GetOriginalEnemyStats(enemy, enemyType);
				EnemyStats enemyStats = ScaleEnemyStats(originalEnemyStats, connectedPlayerCount, value);
				ApplyStatsToEnemy(enemy, enemyStats);
				EnemyData value2 = new EnemyData
				{
					EnemyId = text,
					GameObject = enemy,
					EnemyType = enemyType,
					Stats = enemyStats,
					LastPosition = enemy.transform.position,
					LastHealth = enemyStats.Health,
					State = "spawned"
				};
				enemies[text] = value2;
				EnemySpawnMessage message = new EnemySpawnMessage
				{
					EnemyId = text,
					EnemyType = enemyType,
					SpawnPosition = enemy.transform.position,
					Health = enemyStats.Health,
					Damage = enemyStats.Damage,
					Level = enemyStats.Level
				};
				NetworkManager.Instance.SendMessage(message);
			}
		}

		public void UpdateEnemyState(GameObject enemy, string state, string targetPlayerId = "")
		{
			//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_0063: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkManager.Instance.IsHost)
			{
				string text = FindEnemyId(enemy);
				if (!string.IsNullOrEmpty(text))
				{
					EnemyData enemyData = enemies[text];
					enemyData.State = state;
					enemyData.LastPosition = enemy.transform.position;
					enemyData.LastHealth = GetEnemyCurrentHealth(enemy);
					EnemyUpdateMessage message = new EnemyUpdateMessage
					{
						EnemyId = text,
						Position = enemy.transform.position,
						Health = enemyData.LastHealth,
						State = state,
						TargetPlayerId = targetPlayerId
					};
					NetworkManager.Instance.SendMessage(message);
				}
			}
		}

		public void OnEnemyDeath(GameObject enemy)
		{
			if (NetworkManager.Instance.IsHost)
			{
				string text = FindEnemyId(enemy);
				if (!string.IsNullOrEmpty(text))
				{
					UpdateEnemyState(enemy, "dead");
					((MonoBehaviour)this).StartCoroutine(RemoveEnemyDelayed(text, 5f));
				}
			}
		}

		private void SpawnRemoteEnemy(EnemySpawnMessage message)
		{
			//IL_005d: 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)
			GameObject gameObject = CreateRemoteEnemyVisual(message);
			EnemyData value = new EnemyData
			{
				EnemyId = message.EnemyId,
				GameObject = gameObject,
				EnemyType = message.EnemyType,
				Stats = new EnemyStats
				{
					Health = message.Health,
					Damage = message.Damage,
					Level = message.Level
				},
				LastPosition = message.SpawnPosition,
				LastHealth = message.Health,
				State = "spawned"
			};
			enemies[message.EnemyId] = value;
		}

		private void UpdateRemoteEnemy(EnemyUpdateMessage message)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (enemies.ContainsKey(message.EnemyId))
			{
				EnemyData enemyData = enemies[message.EnemyId];
				enemyData.LastPosition = message.Position;
				enemyData.LastHealth = message.Health;
				enemyData.State = message.State;
				if ((Object)(object)enemyData.GameObject != (Object)null)
				{
					UpdateRemoteEnemyVisual(enemyData.GameObject, message);
				}
				if (message.State == "dead")
				{
					HandleRemoteEnemyDeath(enemyData);
				}
			}
		}

		private EnemyStats GetOriginalEnemyStats(GameObject enemy, string enemyType)
		{
			EnemyStats enemyStats = new EnemyStats
			{
				Health = 100f,
				Damage = 10f,
				Speed = 5f,
				Level = 1,
				XPReward = 50
			};
			Health component = enemy.GetComponent<Health>();
			if ((Object)(object)component != (Object)null)
			{
				enemyStats.Health = component.maxHealth;
			}
			Attack component2 = enemy.GetComponent<Attack>();
			if ((Object)(object)component2 != (Object)null)
			{
				enemyStats.Damage = component2.damage;
			}
			return enemyStats;
		}

		private EnemyStats ScaleEnemyStats(EnemyStats originalStats, int playerCount, float scalingFactor)
		{
			float num = 1f + (float)(playerCount - 1) * scalingFactor;
			return new EnemyStats
			{
				Health = originalStats.Health * num,
				Damage = originalStats.Damage * num,
				Speed = originalStats.Speed,
				Level = originalStats.Level + (playerCount - 1),
				XPReward = Mathf.RoundToInt((float)originalStats.XPReward * num)
			};
		}

		private void ApplyStatsToEnemy(GameObject enemy, EnemyStats stats)
		{
			Health component = enemy.GetComponent<Health>();
			if ((Object)(object)component != (Object)null)
			{
				component.maxHealth = stats.Health;
				component.currentHealth = stats.Health;
			}
			Attack component2 = enemy.GetComponent<Attack>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.damage = stats.Damage;
			}
			XPReward component3 = enemy.GetComponent<XPReward>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.xpAmount = stats.XPReward;
			}
		}

		private GameObject CreateRemoteEnemyVisual(EnemySpawnMessage message)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = "RemoteEnemy_" + message.EnemyId;
			val.transform.position = message.SpawnPosition;
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				Material val2 = new Material(Shader.Find("Standard"));
				val2.color = GetEnemyTypeColor(message.EnemyType);
				component.material = val2;
			}
			Collider component2 = val.GetComponent<Collider>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			CreateEnemyHealthBar(val, message.Health);
			return val;
		}

		private void UpdateRemoteEnemyVisual(GameObject remoteEnemy, EnemyUpdateMessage message)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)remoteEnemy == (Object)null))
			{
				remoteEnemy.transform.position = Vector3.Lerp(remoteEnemy.transform.position, message.Position, Time.deltaTime * 5f);
				UpdateEnemyHealthBar(remoteEnemy, message.Health);
				string state = message.State;
				if (!(state == "chasing") && !(state == "attacking"))
				{
					_ = state == "dead";
				}
			}
		}

		private void CreateEnemyHealthBar(GameObject enemy, float maxHealth)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("EnemyHealthBar");
			val.transform.SetParent(enemy.transform);
			val.transform.localPosition = Vector3.up * 2f;
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val2).name = "Background";
			val2.transform.SetParent(val.transform);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localScale = new Vector3(2f, 0.2f, 0.1f);
			Renderer component = val2.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.material.color = Color.red;
			}
			Object.Destroy((Object)(object)val2.GetComponent<Collider>());
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj).name = "Foreground";
			obj.transform.SetParent(val2.transform);
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localScale = Vector3.one;
			Renderer component2 = obj.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.material.color = Color.green;
			}
			Object.Destroy((Object)(object)obj.GetComponent<Collider>());
		}

		private void UpdateEnemyHealthBar(GameObject enemy, float currentHealth)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Transform val = enemy.transform.Find("EnemyHealthBar/Background/Foreground");
			if ((Object)(object)val != (Object)null)
			{
				string text = FindEnemyId(enemy);
				if (!string.IsNullOrEmpty(text) && enemies.ContainsKey(text))
				{
					float health = enemies[text].Stats.Health;
					float num = currentHealth / health;
					val.localScale = new Vector3(num, 1f, 1f);
				}
			}
		}

		private void HandleRemoteEnemyDeath(EnemyData enemyData)
		{
			if ((Object)(object)enemyData.GameObject != (Object)null)
			{
				((MonoBehaviour)this).StartCoroutine(DeathAnimation(enemyData.GameObject));
			}
		}

		[IteratorStateMachine(typeof(<DeathAnimation>d__25))]
		private IEnumerator DeathAnimation(GameObject enemy)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DeathAnimation>d__25(0)
			{
				enemy = enemy
			};
		}

		[IteratorStateMachine(typeof(<RemoveEnemyDelayed>d__26))]
		private IEnumerator RemoveEnemyDelayed(string enemyId, float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RemoveEnemyDelayed>d__26(0)
			{
				<>4__this = this,
				enemyId = enemyId,
				delay = delay
			};
		}

		private void SyncAllEnemies()
		{
			//IL_0034: 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)
			foreach (EnemyData value in enemies.Values)
			{
				if ((Object)(object)value.GameObject != (Object)null)
				{
					Vector3 position = value.GameObject.transform.position;
					float enemyCurrentHealth = GetEnemyCurrentHealth(value.GameObject);
					if (Vector3.Distance(position, value.LastPosition) > 1f || Mathf.Abs(enemyCurrentHealth - value.LastHealth) > 1f)
					{
						UpdateEnemyState(value.GameObject, value.State);
					}
				}
			}
		}

		private void RemoveEnemy(string enemyId)
		{
			if (enemies.ContainsKey(enemyId))
			{
				if ((Object)(object)enemies[enemyId].GameObject != (Object)null)
				{
					Object.Destroy((Object)(object)enemies[enemyId].GameObject);
				}
				enemies.Remove(enemyId);
			}
		}

		private string FindEnemyId(GameObject enemy)
		{
			return enemies.FirstOrDefault((KeyValuePair<string, EnemyData> kvp) => (Object)(object)kvp.Value.GameObject == (Object)(object)enemy).Key;
		}

		private float GetEnemyCurrentHealth(GameObject enemy)
		{
			Health component = enemy.GetComponent<Health>();
			if (!((Object)(object)component != (Object)null))
			{
				return 100f;
			}
			return component.currentHealth;
		}

		private Color GetEnemyTypeColor(string enemyType)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(enemyType.ToLower() switch
			{
				"goblin" => Color.green, 
				"orc" => Color.red, 
				"skeleton" => Color.white, 
				"boss" => Color.black, 
				_ => Color.gray, 
			});
		}

		public int GetTotalEnemyCount()
		{
			return enemies.Count;
		}

		public List<EnemyData> GetAllEnemies()
		{
			return enemies.Values.ToList();
		}

		public EnemyData GetEnemyData(string enemyId)
		{
			if (!enemies.ContainsKey(enemyId))
			{
				return null;
			}
			return enemies[enemyId];
		}
	}
	[Serializable]
	public class EnemyStats
	{
		public float Health;

		public float Damage;

		public float Speed;

		public int Level;

		public int XPReward;
	}
	[Serializable]
	public class EnemyData
	{
		public string EnemyId;

		public GameObject GameObject;

		public string EnemyType;

		public EnemyStats Stats;

		public Vector3 LastPosition;

		public float LastHealth;

		public string State;
	}
	public class Health : MonoBehaviour
	{
		public float maxHealth = 100f;

		public float currentHealth = 100f;
	}
	public class Attack : MonoBehaviour
	{
		public float damage = 10f;
	}
	public class XPReward : MonoBehaviour
	{
		public int xpAmount = 50;
	}
	[HarmonyPatch]
	public class GamePatches
	{
		[HarmonyPatch(typeof(PlayerController), "Update")]
		[HarmonyPostfix]
		public static void PlayerController_Update_Postfix(PlayerController __instance)
		{
			if ((Object)(object)PlayerSyncManager.Instance != (Object)null)
			{
				_ = NetworkManager.Instance.IsConnected;
			}
		}

		[HarmonyPatch(typeof(PlayerController), "Attack")]
		[HarmonyPostfix]
		public static void PlayerController_Attack_Postfix(PlayerController __instance, Vector3 targetPosition)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)PlayerSyncManager.Instance != (Object)null)
			{
				PlayerSyncManager.Instance.SendPlayerAction("attack", targetPosition);
			}
		}

		[HarmonyPatch(typeof(PlayerController), "UseSkill")]
		[HarmonyPostfix]
		public static void PlayerController_UseSkill_Postfix(PlayerController __instance, string skillId, Vector3 targetPosition)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)PlayerSyncManager.Instance != (Object)null)
			{
				PlayerSyncManager.Instance.SendPlayerAction("skill", targetPosition, skillId);
			}
		}

		[HarmonyPatch(typeof(ExperienceManager), "AddExperience")]
		[HarmonyPrefix]
		public static bool ExperienceManager_AddExperience_Prefix(ExperienceManager __instance, int amount, Vector3 source)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)XPManager.Instance != (Object)null && NetworkManager.Instance.IsConnected)
			{
				XPManager.Instance.AddXP(amount, "enemy", source);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(EnemySpawner), "SpawnEnemy")]
		[HarmonyPostfix]
		public static void EnemySpawner_SpawnEnemy_Postfix(EnemySpawner __instance, GameObject spawnedEnemy, string enemyType)
		{
			if ((Object)(object)EnemyScalingManager.Instance != (Object)null && NetworkManager.Instance.IsConnected)
			{
				EnemyScalingManager.Instance.RegisterEnemySpawn(spawnedEnemy, enemyType);
			}
		}

		[HarmonyPatch(typeof(Enemy), "Die")]
		[HarmonyPostfix]
		public static void Enemy_Die_Postfix(Enemy __instance)
		{
			if ((Object)(object)EnemyScalingManager.Instance != (Object)null && NetworkManager.Instance.IsConnected)
			{
				EnemyScalingManager.Instance.OnEnemyDeath(((Component)__instance).gameObject);
			}
		}

		[HarmonyPatch(typeof(ChestSpawner), "SpawnChest")]
		[HarmonyPostfix]
		public static void ChestSpawner_SpawnChest_Postfix(ChestSpawner __instance, GameObject spawnedChest)
		{
			if ((Object)(object)ChestSyncManager.Instance != (Object)null && NetworkManager.Instance.IsConnected)
			{
				ChestSyncManager.Instance.RegisterChestSpawn(spawnedChest);
			}
		}

		[HarmonyPatch(typeof(Chest), "Open")]
		[HarmonyPrefix]
		public static bool Chest_Open_Prefix(Chest __instance, Player player)
		{
			if ((Object)(object)ChestSyncManager.Instance != (Object)null && NetworkManager.Instance.IsConnected)
			{
				string playerNetworkId = GetPlayerNetworkId(player);
				ChestSyncManager.Instance.TryOpenChest(((Component)__instance).gameObject, playerNetworkId);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(GameManager), "StartWave")]
		[HarmonyPostfix]
		public static void GameManager_StartWave_Postfix(GameManager __instance, int waveNumber)
		{
			if (NetworkManager.Instance.IsHost)
			{
				GameStateMessage message = new GameStateMessage
				{
					GamePhase = "wave_started",
					Wave = waveNumber,
					GameTime = Time.time
				};
				NetworkManager.Instance.SendMessage(message);
			}
		}

		[HarmonyPatch(typeof(GameManager), "EndWave")]
		[HarmonyPostfix]
		public static void GameManager_EndWave_Postfix(GameManager __instance, int waveNumber)
		{
			if (NetworkManager.Instance.IsHost)
			{
				GameStateMessage message = new GameStateMessage
				{
					GamePhase = "wave_ended",
					Wave = waveNumber,
					GameTime = Time.time
				};
				NetworkManager.Instance.SendMessage(message);
			}
		}

		[HarmonyPatch(typeof(MainMenu), "Start")]
		[HarmonyPostfix]
		public static void MainMenu_Start_Postfix(MainMenu __instance)
		{
			MultiplayerUISimple.Instance?.CreateMainMenuUI(__instance);
		}

		private static string GetPlayerNetworkId(Player player)
		{
			return SystemInfo.deviceUniqueIdentifier;
		}
	}
	[HarmonyPatch]
	public class ConditionalPatches
	{
		[HarmonyPatch("PlayerMovement", "Move")]
		[HarmonyPostfix]
		public static void PlayerMovement_Move_Postfix()
		{
		}

		[HarmonyPatch("ItemManager", "GiveItem")]
		[HarmonyPostfix]
		public static void ItemManager_GiveItem_Postfix(string itemId, int quantity)
		{
		}
	}
	public class PlayerController : MonoBehaviour
	{
		public virtual void Update()
		{
		}

		public virtual void Attack(Vector3 targetPosition)
		{
		}

		public virtual void UseSkill(string skillId, Vector3 targetPosition)
		{
		}
	}
	public class ExperienceManager : MonoBehaviour
	{
		public virtual void AddExperience(int amount, Vector3 source)
		{
		}
	}
	public class EnemySpawner : MonoBehaviour
	{
		public virtual GameObject SpawnEnemy(string enemyType)
		{
			return null;
		}
	}
	public class Enemy : MonoBehaviour
	{
		public virtual void Die()
		{
		}
	}
	public class ChestSpawner : MonoBehaviour
	{
		public virtual GameObject SpawnChest()
		{
			return null;
		}
	}
	public class Chest : MonoBehaviour
	{
		public virtual void Open(Player player)
		{
		}
	}
	public class Player : MonoBehaviour
	{
		public string playerId;

		public int gold;

		public int experience;

		public int level;
	}
	public class GameManager : MonoBehaviour
	{
		public virtual void StartWave(int waveNumber)
		{
		}

		public virtual void EndWave(int waveNumber)
		{
		}
	}
	public class MainMenu : MonoBehaviour
	{
		public virtual void Start()
		{
		}
	}
	[BepInPlugin("com.multibonk.multiplayer", "Megabonk Multiplayer", "1.0.0")]
	public class MegabonkMultiplayerPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.multibonk.multiplayer";

		public const string PluginName = "Megabonk Multiplayer";

		public const string PluginVersion = "1.0.0";

		public static ConfigEntry<int> MaxPlayers;

		public static ConfigEntry<float> XPShareRate;

		public static ConfigEntry<float> EnemyScalingFactor;

		public static ConfigEntry<float> ProximityRange;

		public static ConfigEntry<int> NetworkPort;

		public static NetworkManager NetworkManager;

		public static PlayerSyncManager PlayerSyncManager;

		public static XPManager XPManager;

		public static EnemyScalingManager EnemyScalingManager;

		public static ChestSyncManager ChestSyncManager;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Megabonk Multiplayer 1.0.0 is loading...");
			InitializeConfig();
			InitializeSystems();
			harmony = new Harmony("com.multibonk.multiplayer");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Megabonk Multiplayer 1.0.0 loaded successfully!");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			NetworkManager?.Shutdown();
		}

		private void InitializeConfig()
		{
			MaxPlayers = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPlayers", 4, "Maximum number of players (1-4)");
			XPShareRate = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "XPShareRate", 1f, "Rate of XP sharing (0.0 = no sharing, 1.0 = full sharing)");
			EnemyScalingFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "EnemyScalingFactor", 0.75f, "Enemy scaling factor per additional player");
			ProximityRange = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "ProximityRange", 50f, "Distance for player visibility on map");
			NetworkPort = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "Port", 25565, "Network port for hosting games");
		}

		private void InitializeSystems()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_001f: 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_002a: Expected O, but got Unknown
			//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_0044: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0087: 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_0092: Expected O, but got Unknown
			GameObject val = new GameObject("NetworkManager");
			Object.DontDestroyOnLoad((Object)val);
			NetworkManager = val.AddComponent<NetworkManager>();
			GameObject val2 = new GameObject("PlayerSyncManager");
			Object.DontDestroyOnLoad((Object)val2);
			PlayerSyncManager = val2.AddComponent<PlayerSyncManager>();
			GameObject val3 = new GameObject("XPManager");
			Object.DontDestroyOnLoad((Object)val3);
			XPManager = val3.AddComponent<XPManager>();
			GameObject val4 = new GameObject("EnemyScalingManager");
			Object.DontDestroyOnLoad((Object)val4);
			EnemyScalingManager = val4.AddComponent<EnemyScalingManager>();
			GameObject val5 = new GameObject("ChestSyncManager");
			Object.DontDestroyOnLoad((Object)val5);
			ChestSyncManager = val5.AddComponent<ChestSyncManager>();
			GameObject val6 = new GameObject("MultiplayerUI");
			Object.DontDestroyOnLoad((Object)val6);
			val6.AddComponent<MultiplayerUISimple>();
		}
	}
	public class MultiplayerUISimple : MonoBehaviour
	{
		private static MultiplayerUISimple instance;

		private bool showMultiplayerMenu;

		private bool showHostPanel;

		private bool showJoinPanel;

		private bool showLobbyPanel;

		private bool showSettings;

		private int maxPlayers = 4;

		private float xpShareRate = 1f;

		private float enemyScalingFactor = 0.75f;

		private float proximityRange = 50f;

		private string playerName = "Player";

		private string roomCode = "";

		private string chatMessage = "";

		private Rect windowRect = new Rect((float)(Screen.width / 2 - 200), (float)(Screen.height / 2 - 150), 400f, 300f);

		private Vector2 scrollPosition = Vector2.zero;

		public static MultiplayerUISimple Instance => instance;

		private void Awake()
		{
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void Start()
		{
			if ((Object)(object)NetworkManager.Instance != (Object)null)
			{
				NetworkManager.Instance.OnMessageReceived += HandleNetworkMessage;
				NetworkManager.Instance.OnPlayerConnected += OnPlayerConnected;
				NetworkManager.Instance.OnPlayerDisconnected += OnPlayerDisconnected;
			}
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)109))
			{
				showMultiplayerMenu = !showMultiplayerMenu;
			}
			if (Input.GetKeyDown((KeyCode)116))
			{
				_ = NetworkManager.Instance.IsConnected;
			}
		}

		private void OnGUI()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00bd: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			GUI.skin.label.fontSize = 14;
			GUI.skin.button.fontSize = 12;
			GUI.skin.textField.fontSize = 12;
			if (showMultiplayerMenu && !NetworkManager.Instance.IsConnected)
			{
				windowRect = GUI.Window(0, windowRect, new WindowFunction(MultiplayerMenuWindow), "Multiplayer");
			}
			else if (showHostPanel)
			{
				windowRect = GUI.Window(1, windowRect, new WindowFunction(HostPanelWindow), "Host Game");
			}
			else if (showJoinPanel)
			{
				windowRect = GUI.Window(2, windowRect, new WindowFunction(JoinPanelWindow), "Join Game");
			}
			else if (showLobbyPanel)
			{
				windowRect = GUI.Window(3, windowRect, new WindowFunction(LobbyPanelWindow), "Multiplayer Lobby");
			}
			if (NetworkManager.Instance.IsConnected)
			{
				string arg = (NetworkManager.Instance.IsHost ? "Hosting" : "Connected");
				int connectedPlayerCount = NetworkManager.Instance.ConnectedPlayerCount;
				GUI.Label(new Rect(10f, 10f, 200f, 20f), $"{arg} - Players: {connectedPlayerCount}/{maxPlayers}");
				DrawSimpleChat();
			}
			GUI.Label(new Rect(10f, (float)(Screen.height - 30), 300f, 20f), "Press M to open Multiplayer menu");
		}

		private void MultiplayerMenuWindow(int windowID)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Megabonk Multiplayer", GUI.skin.label, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (GUILayout.Button("Host Game", Array.Empty<GUILayoutOption>()))
			{
				showMultiplayerMenu = false;
				showHostPanel = true;
			}
			if (GUILayout.Button("Join Game", Array.Empty<GUILayoutOption>()))
			{
				showMultiplayerMenu = false;
				showJoinPanel = true;
			}
			GUILayout.Space(10f);
			if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>()))
			{
				showMultiplayerMenu = false;
			}
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void HostPanelWindow(int windowID)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Host Game Settings", GUI.skin.label, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label("Player Name:", Array.Empty<GUILayoutOption>());
			playerName = GUILayout.TextField(playerName, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Max Players: {maxPlayers}", Array.Empty<GUILayoutOption>());
			maxPlayers = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)maxPlayers, 2f, 4f, Array.Empty<GUILayoutOption>()));
			GUILayout.Label($"XP Share Rate: {xpShareRate * 100f:F0}%", Array.Empty<GUILayoutOption>());
			xpShareRate = GUILayout.HorizontalSlider(xpShareRate, 0f, 1f, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Enemy Scaling: {enemyScalingFactor * 100f:F0}%", Array.Empty<GUILayoutOption>());
			enemyScalingFactor = GUILayout.HorizontalSlider(enemyScalingFactor, 0f, 1f, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (GUILayout.Button("Start Hosting", Array.Empty<GUILayoutOption>()))
			{
				StartHosting();
			}
			if (GUILayout.Button("Back", Array.Empty<GUILayoutOption>()))
			{
				showHostPanel = false;
				showMultiplayerMenu = true;
			}
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void JoinPanelWindow(int windowID)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Join Game", GUI.skin.label, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label("Player Name:", Array.Empty<GUILayoutOption>());
			playerName = GUILayout.TextField(playerName, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Host IP Address:", Array.Empty<GUILayoutOption>());
			roomCode = GUILayout.TextField(roomCode, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (GUILayout.Button("Join Game", Array.Empty<GUILayoutOption>()))
			{
				JoinGame();
			}
			if (GUILayout.Button("Back", Array.Empty<GUILayoutOption>()))
			{
				showJoinPanel = false;
				showMultiplayerMenu = true;
			}
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void LobbyPanelWindow(int windowID)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Multiplayer Lobby", GUI.skin.label, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			string text = (NetworkManager.Instance.IsHost ? "Hosting Game" : "Connected to Host");
			GUILayout.Label("Status: " + text, Array.Empty<GUILayoutOption>());
			int connectedPlayerCount = NetworkManager.Instance.ConnectedPlayerCount;
			GUILayout.Label($"Players: {connectedPlayerCount}/{maxPlayers}", Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (NetworkManager.Instance.IsHost)
			{
				if (GUILayout.Button(showSettings ? "Hide Settings" : "Game Settings", Array.Empty<GUILayoutOption>()))
				{
					showSettings = !showSettings;
				}
				if (showSettings)
				{
					GUILayout.Label("--- Game Settings ---", Array.Empty<GUILayoutOption>());
					GUILayout.Label($"Max Players: {maxPlayers}", Array.Empty<GUILayoutOption>());
					int num = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)maxPlayers, 2f, 4f, Array.Empty<GUILayoutOption>()));
					GUILayout.Label($"XP Share Rate: {xpShareRate * 100f:F0}%", Array.Empty<GUILayoutOption>());
					float num2 = GUILayout.HorizontalSlider(xpShareRate, 0f, 1f, Array.Empty<GUILayoutOption>());
					GUILayout.Label($"Enemy Scaling: {enemyScalingFactor * 100f:F0}%", Array.Empty<GUILayoutOption>());
					float num3 = GUILayout.HorizontalSlider(enemyScalingFactor, 0f, 1f, Array.Empty<GUILayoutOption>());
					if (num != maxPlayers || num2 != xpShareRate || num3 != enemyScalingFactor)
					{
						maxPlayers = num;
						xpShareRate = num2;
						enemyScalingFactor = num3;
						ApplySettings();
					}
				}
				GUILayout.Space(10f);
				if (GUILayout.Button("Start Game", Array.Empty<GUILayoutOption>()))
				{
					StartGame();
				}
			}
			GUILayout.Space(10f);
			if (GUILayout.Button("Leave Game", Array.Empty<GUILayoutOption>()))
			{
				LeaveGame();
			}
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void DrawSimpleChat()
		{
			//IL_0018: 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)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			GUI.Box(new Rect(10f, (float)(Screen.height - 120), 300f, 80f), "");
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(15f, (float)(Screen.height - 35), 200f, 20f);
			chatMessage = GUI.TextField(val, chatMessage);
			if (GUI.Button(new Rect(220f, (float)(Screen.height - 35), 50f, 20f), "Send") || ((int)Event.current.type == 4 && (int)Event.current.keyCode == 13 && GUI.GetNameOfFocusedControl() == "ChatInput"))
			{
				SendChatMessage();
			}
			GUI.SetNextControlName("ChatInput");
		}

		private void StartHosting()
		{
			MegabonkMultiplayerPlugin.MaxPlayers.Value = maxPlayers;
			MegabonkMultiplayerPlugin.XPShareRate.Value = xpShareRate;
			MegabonkMultiplayerPlugin.EnemyScalingFactor.Value = enemyScalingFactor;
			if (NetworkManager.Instance.StartHost())
			{
				showHostPanel = false;
				showLobbyPanel = true;
				Debug.Log((object)"Started hosting multiplayer game");
			}
		}

		private void JoinGame()
		{
			if (!string.IsNullOrEmpty(roomCode) && NetworkManager.Instance.ConnectToHost(roomCode))
			{
				showJoinPanel = false;
				showLobbyPanel = true;
				Debug.Log((object)("Connecting to host: " + roomCode));
			}
		}

		private void StartGame()
		{
			if (NetworkManager.Instance.IsHost)
			{
				GameStateMessage message = new GameStateMessage
				{
					GamePhase = "starting",
					GameTime = Time.time
				};
				NetworkManager.Instance.SendMessage(message);
				showLobbyPanel = false;
				Debug.Log((object)"Starting multiplayer game");
			}
		}

		private void LeaveGame()
		{
			NetworkManager.Instance.Shutdown();
			showLobbyPanel = false;
			showMultiplayerMenu = true;
			Debug.Log((object)"Left multiplayer game");
		}

		private void ApplySettings()
		{
			if (NetworkManager.Instance.IsHost)
			{
				MegabonkMultiplayerPlugin.MaxPlayers.Value = maxPlayers;
				MegabonkMultiplayerPlugin.XPShareRate.Value = xpShareRate;
				MegabonkMultiplayerPlugin.EnemyScalingFactor.Value = enemyScalingFactor;
				SettingsUpdateMessage message = new SettingsUpdateMessage
				{
					MaxPlayers = maxPlayers,
					XPShareRate = xpShareRate,
					EnemyScalingFactor = enemyScalingFactor,
					ProximityRange = proximityRange
				};
				NetworkManager.Instance.SendMessage(message);
				Debug.Log((object)"Settings updated and synced to all players");
			}
		}

		private void SendChatMessage()
		{
			if (!string.IsNullOrEmpty(chatMessage))
			{
				ChatMessage message = new ChatMessage
				{
					PlayerName = playerName,
					Message = chatMessage,
					ChatType = "all"
				};
				NetworkManager.Instance.SendMessage(message);
				chatMessage = "";
			}
		}

		private void HandleNetworkMessage(NetworkMessage message)
		{
			switch (message.MessageType)
			{
			case "ChatMessage":
				HandleChatMessage(message as ChatMessage);
				break;
			case "GameStateMessage":
				HandleGameStateMessage(message as GameStateMessage);
				break;
			case "SettingsUpdateMessage":
				HandleSettingsUpdateMessage(message as SettingsUpdateMessage);
				break;
			}
		}

		private void HandleChatMessage(ChatMessage message)
		{
			Debug.Log((object)("[CHAT] " + message.PlayerName + ": " + message.Message));
		}

		private void HandleGameStateMessage(GameStateMessage message)
		{
			if (message.GamePhase == "starting")
			{
				showLobbyPanel = false;
				Debug.Log((object)"Game starting!");
			}
		}

		private void HandleSettingsUpdateMessage(SettingsUpdateMessage message)
		{
			if (!NetworkManager.Instance.IsHost)
			{
				maxPlayers = message.MaxPlayers;
				xpShareRate = message.XPShareRate;
				enemyScalingFactor = message.EnemyScalingFactor;
				proximityRange = message.ProximityRange;
				MegabonkMultiplayerPlugin.MaxPlayers.Value = maxPlayers;
				MegabonkMultiplayerPlugin.XPShareRate.Value = xpShareRate;
				MegabonkMultiplayerPlugin.EnemyScalingFactor.Value = enemyScalingFactor;
				MegabonkMultiplayerPlugin.ProximityRange.Value = proximityRange;
				Debug.Log((object)"Settings updated by host");
			}
		}

		private void OnPlayerConnected(string playerId)
		{
			Debug.Log((object)("Player " + playerId.Substring(0, 8) + " connected"));
		}

		private void OnPlayerDisconnected(string playerId)
		{
			Debug.Log((object)("Player " + playerId.Substring(0, 8) + " disconnected"));
		}

		public void CreateMainMenuUI(object mainMenu)
		{
			Debug.Log((object)"Multiplayer UI initialized - Press M to open menu");
		}
	}
	public class NetworkManager : MonoBehaviour
	{
		public enum NetworkRole
		{
			None,
			Host,
			Client
		}

		private NetworkRole currentRole;

		private TcpListener server;

		private TcpClient client;

		private List<ClientConnection> connectedClients = new List<ClientConnection>();

		private Thread serverThread;

		private bool isRunning;

		private Queue<NetworkMessage> incomingMessages = new Queue<NetworkMessage>();

		private Queue<NetworkMessage> outgoingMessages = new Queue<NetworkMessage>();

		public static NetworkManager Instance { get; private set; }

		public bool IsHost => currentRole == NetworkRole.Host;

		public bool IsClient => currentRole == NetworkRole.Client;

		public bool IsConnected
		{
			get
			{
				if (isRunning)
				{
					if (!IsHost)
					{
						if (IsClient)
						{
							return client?.Connected ?? false;
						}
						return false;
					}
					return true;
				}
				return false;
			}
		}

		public int ConnectedPlayerCount
		{
			get
			{
				if (!IsHost)
				{
					if (!IsConnected)
					{
						return 1;
					}
					return 2;
				}
				return connectedClients.Count + 1;
			}
		}

		public event Action<NetworkMessage> OnMessageReceived;

		public event Action<string> OnPlayerConnected;

		public event Action<string> OnPlayerDisconnected;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void Update()
		{
			ProcessIncomingMessages();
			ProcessOutgoingMessages();
		}

		public bool StartHost(int port = 25565)
		{
			try
			{
				currentRole = NetworkRole.Host;
				server = new TcpListener(IPAddress.Any, port);
				server.Start();
				isRunning = true;
				serverThread = new Thread(ServerLoop);
				serverThread.Start();
				Debug.Log((object)$"Server started on port {port}");
				return true;
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to start server: " + ex.Message));
				return false;
			}
		}

		public bool ConnectToHost(string ipAddress, int port = 25565)
		{
			try
			{
				currentRole = NetworkRole.Client;
				client = new TcpClient();
				client.Connect(ipAddress, port);
				isRunning = true;
				new Thread(ClientLoop).Start();
				Debug.Log((object)$"Connected to server at {ipAddress}:{port}");
				return true;
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to connect to server: " + ex.Message));
				return false;
			}
		}

		private void ServerLoop()
		{
			while (isRunning)
			{
				try
				{
					if (server.Pending())
					{
						TcpClient tcpClient = server.AcceptTcpClient();
						if (connectedClients.Count < MegabonkMultiplayerPlugin.MaxPlayers.Value - 1)
						{
							string text = Guid.NewGuid().ToString();
							ClientConnection connection = new ClientConnection(text, tcpClient);
							connectedClients.Add(connection);
							new Thread((ThreadStart)delegate
							{
								HandleClient(connection);
							}).Start();
							this.OnPlayerConnected?.Invoke(text);
							BroadcastMessage(new PlayerConnectedMessage
							{
								PlayerId = text
							});
						}
						else
						{
							tcpClient.Close();
						}
					}
					Thread.Sleep(10);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Server loop error: " + ex.Message));
				}
			}
		}

		private void ClientLoop()
		{
			NetworkStream stream = client.GetStream();
			byte[] array = new byte[4096];
			while (isRunning && client.Connected)
			{
				try
				{
					if (stream.DataAvailable)
					{
						int count = stream.Read(array, 0, array.Length);
						NetworkMessage item = JsonConvert.DeserializeObject<NetworkMessage>(Encoding.UTF8.GetString(array, 0, count));
						lock (incomingMessages)
						{
							incomingMessages.Enqueue(item);
						}
					}
					Thread.Sleep(10);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Client loop error: " + ex.Message));
					break;
				}
			}
		}

		private void HandleClient(ClientConnection connection)
		{
			NetworkStream stream = connection.TcpClient.GetStream();
			byte[] array = new byte[4096];
			while (isRunning && connection.TcpClient.Connected)
			{
				try
				{
					if (stream.DataAvailable)
					{
						int count = stream.Read(array, 0, array.Length);
						NetworkMessage networkMessage = JsonConvert.DeserializeObject<NetworkMessage>(Encoding.UTF8.GetString(array, 0, count));
						networkMessage.SenderId = connection.ClientId;
						lock (incomingMessages)
						{
							incomingMessages.Enqueue(networkMessage);
						}
						BroadcastMessage(networkMessage, connection.ClientId);
					}
					Thread.Sleep(10);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Client handler error: " + ex.Message));
					break;
				}
			}
			connectedClients.Remove(connection);
			this.OnPlayerDisconnected?.Invoke(connection.ClientId);
			BroadcastMessage(new PlayerDisconnectedMessage
			{
				PlayerId = connection.ClientId
			});
		}

		public void SendMessage(NetworkMessage message)
		{
			lock (outgoingMessages)
			{
				outgoingMessages.Enqueue(message);
			}
		}

		private void BroadcastMessage(NetworkMessage message, string excludeClientId = null)
		{
			string s = JsonConvert.SerializeObject((object)message);
			byte[] bytes = Encoding.UTF8.GetBytes(s);
			foreach (ClientConnection connectedClient in connectedClients)
			{
				if (connectedClient.ClientId != excludeClientId)
				{
					try
					{
						connectedClient.TcpClient.GetStream().Write(bytes, 0, bytes.Length);
					}
					catch (Exception ex)
					{
						Debug.LogError((object)("Failed to send message to client " + connectedClient.ClientId + ": " + ex.Message));
					}
				}
			}
		}

		private void ProcessIncomingMessages()
		{
			lock (incomingMessages)
			{
				while (incomingMessages.Count > 0)
				{
					NetworkMessage obj = incomingMessages.Dequeue();
					this.OnMessageReceived?.Invoke(obj);
				}
			}
		}

		private void ProcessOutgoingMessages()
		{
			lock (outgoingMessages)
			{
				while (outgoingMessages.Count > 0)
				{
					NetworkMessage networkMessage = outgoingMessages.Dequeue();
					if (currentRole == NetworkRole.Host)
					{
						BroadcastMessage(networkMessage);
					}
					else if (currentRole == NetworkRole.Client && client != null && client.Connected)
					{
						try
						{
							string s = JsonConvert.SerializeObject((object)networkMessage);
							byte[] bytes = Encoding.UTF8.GetBytes(s);
							client.GetStream().Write(bytes, 0, bytes.Length);
						}
						catch (Exception ex)
						{
							Debug.LogError((object)("Failed to send message to server: " + ex.Message));
						}
					}
				}
			}
		}

		public void Shutdown()
		{
			isRunning = false;
			if (server != null)
			{
				server.Stop();
			}
			if (client != null)
			{
				client.Close();
			}
			foreach (ClientConnection connectedClient in connectedClients)
			{
				connectedClient.TcpClient.Close();
			}
			connectedClients.Clear();
			currentRole = NetworkRole.None;
		}
	}
	public class ClientConnection
	{
		public string ClientId { get; }

		public TcpClient TcpClient { get; }

		public ClientConnection(string clientId, TcpClient tcpClient)
		{
			ClientId = clientId;
			TcpClient = tcpClient;
		}
	}
	[Serializable]
	public abstract class NetworkMessage
	{
		public string MessageType { get; set; }

		public string SenderId { get; set; }

		public float Timestamp { get; set; }

		protected NetworkMessage()
		{
			MessageType = GetType().Name;
			Timestamp = Time.time;
		}
	}
	[Serializable]
	public class PlayerPositionMessage : NetworkMessage
	{
		public Vector3 Position { get; set; }

		public Vector3 Velocity { get; set; }

		public float Rotation { get; set; }

		public string AnimationState { get; set; }
	}
	[Serializable]
	public class PlayerActionMessage : NetworkMessage
	{
		public string ActionType { get; set; }

		public Vector3 TargetPosition { get; set; }

		public string SkillId { get; set; }

		public float ActionData { get; set; }
	}
	[Serializable]
	public class XPGainedMessage : NetworkMessage
	{
		public int XPAmount { get; set; }

		public string Source { get; set; }

		public Vector3 SourcePosition { get; set; }
	}
	[Serializable]
	public class EnemySpawnMessage : NetworkMessage
	{
		public string EnemyId { get; set; }

		public string EnemyType { get; set; }

		public Vector3 SpawnPosition { get; set; }

		public float Health { get; set; }

		public float Damage { get; set; }

		public int Level { get; set; }
	}
	[Serializable]
	public class EnemyUpdateMessage : NetworkMessage
	{
		public string EnemyId { get; set; }

		public Vector3 Position { get; set; }

		public float Health { get; set; }

		public string State { get; set; }

		public string TargetPlayerId { get; set; }
	}
	[Serializable]
	public class ChestSpawnMessage : NetworkMessage
	{
		public string ChestId { get; set; }

		public Vector3 Position { get; set; }

		public string ChestType { get; set; }

		public int Cost { get; set; }

		public string[] Items { get; set; }
	}
	[Serializable]
	public class ChestOpenedMessage : NetworkMessage
	{
		public string ChestId { get; set; }

		public string OpenedByPlayerId { get; set; }

		public string[] ItemsReceived { get; set; }
	}
	[Serializable]
	public class PlayerConnectedMessage : NetworkMessage
	{
		public string PlayerId { get; set; }

		public string PlayerName { get; set; }

		public int PlayerLevel { get; set; }

		public Vector3 SpawnPosition { get; set; }
	}
	[Serializable]
	public class PlayerDisconnectedMessage : NetworkMessage
	{
		public string PlayerId { get; set; }
	}
	[Serializable]
	public class GameStateMessage : NetworkMessage
	{
		public string GamePhase { get; set; }

		public float GameTime { get; set; }

		public int Wave { get; set; }

		public int TotalPlayersAlive { get; set; }
	}
	[Serializable]
	public class PlayerStatsMessage : NetworkMessage
	{
		public int Level { get; set; }

		public int CurrentXP { get; set; }

		public int XPToNextLevel { get; set; }

		public float Health { get; set; }

		public float MaxHealth { get; set; }

		public float Mana { get; set; }

		public float MaxMana { get; set; }

		public int Gold { get; set; }
	}
	[Serializable]
	public class ChatMessage : NetworkMessage
	{
		public string PlayerName { get; set; }

		public string Message { get; set; }

		public string ChatType { get; set; }
	}
	[Serializable]
	public class PingMessage : NetworkMessage
	{
		public float ClientTime { get; set; }
	}
	[Serializable]
	public class PongMessage : NetworkMessage
	{
		public float ClientTime { get; set; }

		public float ServerTime { get; set; }
	}
	[Serializable]
	public class SettingsUpdateMessage : NetworkMessage
	{
		public int MaxPlayers { get; set; }

		public float XPShareRate { get; set; }

		public float EnemyScalingFactor { get; set; }

		public float ProximityRange { get; set; }
	}
	public class PlayerSyncManager : MonoBehaviour
	{
		private Dictionary<string, RemotePlayer> remotePlayers = new Dictionary<string, RemotePlayer>();

		private float lastSyncTime;

		private const float SYNC_INTERVAL = 0.1f;

		private const float INTERPOLATION_RATE = 10f;

		public static PlayerSyncManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		private void Start()
		{
			if ((Object)(object)NetworkManager.Instance != (Object)null)
			{
				NetworkManager.Instance.OnMessageReceived += HandleNetworkMessage;
				NetworkManager.Instance.OnPlayerConnected += OnPlayerConnected;
				NetworkManager.Instance.OnPlayerDisconnected += OnPlayerDisconnected;
			}
		}

		private void Update()
		{
			if (Time.time - lastSyncTime >= 0.1f && NetworkManager.Instance.IsConnected)
			{
				SendPlayerPosition();
				lastSyncTime = Time.time;
			}
			InterpolateRemotePlayers();
		}

		private void SendPlayerPosition()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			GameObject localPlayer = GetLocalPlayer();
			if (!((Object)(object)localPlayer == (Object)null))
			{
				PlayerPositionMessage obj = new PlayerPositionMessage
				{
					Position = localPlayer.transform.position,
					Velocity = GetPlayerVelocity(localPlayer)
				};
				Quaternion rotation = localPlayer.transform.rotation;
				obj.Rotation = ((Quaternion)(ref rotation)).eulerAngles.y;
				obj.AnimationState = GetPlayerAnimationState(localPlayer);
				PlayerPositionMessage message = obj;
				NetworkManager.Instance.SendMessage(message);
			}
		}

		private void HandleNetworkMessage(NetworkMessage message)
		{
			switch (message.MessageType)
			{
			case "PlayerPositionMessage":
				HandlePlayerPositionMessage(message as PlayerPositionMessage);
				break;
			case "PlayerActionMessage":
				HandlePlayerActionMessage(message as PlayerActionMessage);
				break;
			case "PlayerStatsMessage":
				HandlePlayerStatsMessage(message as PlayerStatsMessage);
				break;
			}
		}

		private void HandlePlayerPositionMessage(PlayerPositionMessage message)
		{
			//IL_0046: 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)
			if (!(message.SenderId == GetLocalPlayerId()))
			{
				if (!remotePlayers.ContainsKey(message.SenderId))
				{
					CreateRemotePlayer(message.SenderId);
				}
				RemotePlayer remotePlayer = remotePlayers[message.SenderId];
				remotePlayer.UpdatePosition(message.Position, message.Velocity, message.Rotation);
				remotePlayer.SetAnimationState(message.AnimationState);
			}
		}

		private void HandlePlayerActionMessage(PlayerActionMessage message)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!(message.SenderId == GetLocalPlayerId()) && remotePlayers.ContainsKey(message.SenderId))
			{
				remotePlayers[message.SenderId].PerformAction(message.ActionType, message.TargetPosition, message.SkillId, message.ActionData);
			}
		}

		private void HandlePlayerStatsMessage(PlayerStatsMessage message)
		{
			if (!(message.SenderId == GetLocalPlayerId()) && remotePlayers.ContainsKey(message.SenderId))
			{
				remotePlayers[message.SenderId].UpdateStats(message);
			}
		}

		private void OnPlayerConnected(string playerId)
		{
			Debug.Log((object)("Player connected: " + playerId));
			CreateRemotePlayer(playerId);
		}

		private void OnPlayerDisconnected(string playerId)
		{
			Debug.Log((object)("Player disconnected: " + playerId));
			if (remotePlayers.ContainsKey(playerId))
			{
				Object.Destroy((Object)(object)((Component)remotePlayers[playerId]).gameObject);
				remotePlayers.Remove(playerId);
			}
		}

		private void CreateRemotePlayer(string playerId)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!remotePlayers.ContainsKey(playerId))
			{
				RemotePlayer remotePlayer = new GameObject("RemotePlayer_" + playerId).AddComponent<RemotePlayer>();
				remotePlayer.Initialize(playerId);
				remotePlayers[playerId] = remotePlayer;
			}
		}

		private void InterpolateRemotePlayers()
		{
			foreach (RemotePlayer value in remotePlayers.Values)
			{
				value.InterpolatePosition(10f);
			}
		}

		public void SendPlayerAction(string actionType, Vector3 targetPosition, string skillId = "", float actionData = 0f)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			PlayerActionMessage message = new PlayerActionMessage
			{
				ActionType = actionType,
				TargetPosition = targetPosition,
				SkillId = skillId,
				ActionData = actionData
			};
			NetworkManager.Instance.SendMessage(message);
		}

		public void SendPlayerStats()
		{
			GameObject localPlayer = GetLocalPlayer();
			if (!((Object)(object)localPlayer == (Object)null))
			{
				PlayerStatsMessage message = new PlayerStatsMessage
				{
					Level = GetPlayerLevel(localPlayer),
					CurrentXP = GetPlayerCurrentXP(localPlayer),
					XPToNextLevel = GetPlayerXPToNextLevel(localPlayer),
					Health = GetPlayerHealth(localPlayer),
					MaxHealth = GetPlayerMaxHealth(localPlayer),
					Mana = GetPlayerMana(localPlayer),
					MaxMana = GetPlayerMaxMana(localPlayer),
					Gold = GetPlayerGold(localPlayer)
				};
				NetworkManager.Instance.SendMessage(message);
			}
		}

		public List<RemotePlayer> GetRemotePlayersInRange(Vector3 position, float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return remotePlayers.Values.Where((RemotePlayer player) => Vector3.Distance(((Component)player).transform.position, position) <= range).ToList();
		}

		public int GetTotalPlayerCount()
		{
			return remotePlayers.Count + 1;
		}

		private GameObject GetLocalPlayer()
		{
			return GameObject.FindWithTag("Player");
		}

		private string GetLocalPlayerId()
		{
			return SystemInfo.deviceUniqueIdentifier;
		}

		private Vector3 GetPlayerVelocity(GameObject player)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody component = player.GetComponent<Rigidbody>();
			if (!((Object)(object)component != (Object)null))
			{
				return Vector3.zero;
			}
			return component.velocity;
		}

		private string GetPlayerAnimationState(GameObject player)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Animator component = player.GetComponent<Animator>();
			if ((Object)(object)component != (Object)null)
			{
				AnimatorStateInfo currentAnimatorStateInfo = component.GetCurrentAnimatorStateInfo(0);
				if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Walk"))
				{
					currentAnimatorStateInfo = component.GetCurrentAnimatorStateInfo(0);
					if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Attack"))
					{
						return "idle";
					}
					return "attacking";
				}
				return "walking";
			}
			return "idle";
		}

		private int GetPlayerLevel(GameObject player)
		{
			return 1;
		}

		private int GetPlayerCurrentXP(GameObject player)
		{
			return 0;
		}

		private int GetPlayerXPToNextLevel(GameObject player)
		{
			return 100;
		}

		private float GetPlayerHealth(GameObject player)
		{
			return 100f;
		}

		private float GetPlayerMaxHealth(GameObject player)
		{
			return 100f;
		}

		private float GetPlayerMana(GameObject player)
		{
			return 50f;
		}

		private float GetPlayerMaxMana(GameObject player)
		{
			return 50f;
		}

		private int GetPlayerGold(GameObject player)
		{
			return 0;
		}
	}
	public class RemotePlayer : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <PlayAttackEffect>d__30 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RemotePlayer <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlayAttackEffect>d__30(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Expected O, but got Unknown
				int num = <>1__state;
				RemotePlayer remotePlayer = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					remotePlayer.SetAnimationState("attacking");
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					remotePlayer.SetAnimationState("idle");
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <PlayJumpEffect>d__32 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RemotePlayer <>4__this;

			private Vector3 <originalPos>5__2;

			private float <jumpHeight>5__3;

			private float <jumpDuration>5__4;

			private float <t>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlayJumpEffect>d__32(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				RemotePlayer remotePlayer = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<originalPos>5__2 = ((Component)remotePlayer).transform.position;
					<jumpHeight>5__3 = 2f;
					<jumpDuration>5__4 = 0.5f;
					<t>5__5 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<t>5__5 += Time.deltaTime;
					break;
				}
				if (<t>5__5 < <jumpDuration>5__4)
				{
					float num2 = Mathf.Sin(<t>5__5 / <jumpDuration>5__4 * MathF.PI) * <jumpHeight>5__3;
					((Component)remotePlayer).transform.position = <originalPos>5__2 + Vector3.up * num2;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				((Component)remotePlayer).transform.position = <originalPos>5__2;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <PlaySkillEffect>d__31 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlaySkillEffect>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private Vector3 targetPosition;

		private Vector3 targetVelocity;

		private float targetRotation;

		private string currentAnimationState;

		private GameObject playerModel;

		private Animator animator;

		private int level = 1;

		private float health = 100f;

		private float maxHealth = 100f;

		private float mana = 50f;

		private float maxMana = 50f;

		private int gold;

		private bool isVisible = true;

		private float lastVisibilityCheck;

		private const float VISIBILITY_CHECK_INTERVAL = 0.5f;

		public string PlayerId { get; private set; }

		public void Initialize(string playerId)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			PlayerId = playerId;
			targetPosition = ((Component)this).transform.position;
			CreatePlayerModel();
			CreateNameplate();
			SetupComponents();
		}

		private void Update()
		{
			CheckVisibility();
			UpdateNameplate();
		}

		private void CreatePlayerModel()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			playerModel = GameObject.CreatePrimitive((PrimitiveType)1);
			playerModel.transform.SetParent(((Component)this).transform);
			playerModel.transform.localPosition = Vector3.zero;
			Renderer component = playerModel.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				Material val = new Material(Shader.Find("Standard"));
				val.color = GetPlayerColor(PlayerId);
				component.material = val;
			}
			Collider component2 = playerModel.GetComponent<Collider>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			animator = playerModel.AddComponent<Animator>();
		}

		private void CreateNameplate()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Nameplate");
			val.transform.SetParent(((Component)this).transform);
			val.transform.localPosition = Vector3.up * 2.5f;
			TextMesh obj = val.AddComponent<TextMesh>();
			obj.text = "Player " + PlayerId.Substring(0, 8);
			obj.fontSize = 20;
			obj.color = Color.white;
			obj.anchor = (TextAnchor)4;
			val.transform.rotation = Quaternion.LookRotation(Vector3.forward);
			CreateSimpleHealthBar(val);
		}

		private void CreateSimpleHealthBar(GameObject parent)
		{
			//IL_0038: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = "HealthBarBG";
			val.transform.SetParent(parent.transform);
			val.transform.localPosition = new Vector3(0f, -0.5f, 0f);
			val.transform.localScale = new Vector3(2f, 0.2f, 0.1f);
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.material.color = Color.red;
			}
			Object.Destroy((Object)(object)val.GetComponent<Collider>());
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj).name = "HealthBarFG";
			obj.transform.SetParent(val.transform);
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localScale = Vector3.one;
			Renderer component2 = obj.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.material.color = Color.green;
			}
			Object.Destroy((Object)(object)obj.GetComponent<Collider>());
		}

		private void SetupComponents()
		{
			((Component)this).gameObject.layer = LayerMask.NameToLayer("UI");
		}

		public void UpdatePosition(Vector3 position, Vector3 velocity, float rotation)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			targetPosition = position;
			targetVelocity = velocity;
			targetRotation = rotation;
		}

		public void InterpolatePosition(float interpolationRate)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, targetPosition, Time.deltaTime * interpolationRate);
			Quaternion rotation = ((Component)this).transform.rotation;
			float num = Mathf.LerpAngle(((Quaternion)(ref rotation)).eulerAngles.y, targetRotation, Time.deltaTime * interpolationRate);
			((Component)this).transform.rotation = Quaternion.Euler(0f, num, 0f);
		}

		public void SetAnimationState(string animationState)
		{
			if (currentAnimationState != animationState)
			{
				currentAnimationState = animationState;
				UpdateAnimation();
			}
		}

		private void UpdateAnimation()
		{
			if ((Object)(object)animator == (Object)null)
			{
				return;
			}
			string text = currentAnimationState;
			if (!(text == "walking"))
			{
				if (text == "attacking")
				{
					animator.SetBool("IsWalking", false);
					animator.SetBool("IsAttacking", true);
				}
				else
				{
					animator.SetBool("IsWalking", false);
					animator.SetBool("IsAttacking", false);
				}
			}
			else
			{
				animator.SetBool("IsWalking", true);
				animator.SetBool("IsAttacking", false);
			}
		}

		public void PerformAction(string actionType, Vector3 targetPos, string skillId, float actionData)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			switch (actionType)
			{
			case "attack":
				((MonoBehaviour)this).StartCoroutine(PlayAttackEffect(targetPos));
				break;
			case "skill":
				((MonoBehaviour)this).StartCoroutine(PlaySkillEffect(skillId, targetPos));
				break;
			case "jump":
				((MonoBehaviour)this).StartCoroutine(PlayJumpEffect());
				break;
			}
		}

		[IteratorStateMachine(typeof(<PlayAttackEffect>d__30))]
		private IEnumerator PlayAttackEffect(Vector3 targetPos)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlayAttackEffect>d__30(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<PlaySkillEffect>d__31))]
		private IEnumerator PlaySkillEffect(string skillId, Vector3 targetPos)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlaySkillEffect>d__31(0);
		}

		[IteratorStateMachine(typeof(<PlayJumpEffect>d__32))]
		private IEnumerator PlayJumpEffect()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlayJumpEffect>d__32(0)
			{
				<>4__this = this
			};
		}

		public void UpdateStats(PlayerStatsMessage stats)
		{
			level = stats.Level;
			health = stats.Health;
			maxHealth = stats.MaxHealth;
			mana = stats.Mana;
			maxMana = stats.MaxMana;
			gold = stats.Gold;
			UpdateHealthBar();
		}

		private void UpdateHealthBar()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find("Nameplate/HealthBarBG/HealthBarFG");
			if ((Object)(object)val != (Object)null)
			{
				float num = health / maxHealth;
				val.localScale = new Vector3(num, 1f, 1f);
			}
		}

		private void CheckVisibility()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time - lastVisibilityCheck < 0.5f)
			{
				return;
			}
			lastVisibilityCheck = Time.time;
			GameObject val = GameObject.FindWithTag("Player");
			if (!((Object)(object)val == (Object)null))
			{
				bool flag = Vector3.Distance(((Component)this).transform.position, val.transform.position) <= MegabonkMultiplayerPlugi