Decompiled source of CarlosMMONPCTrader v1.0.6

plugins/CarlosMMONPCTrader.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("CarlosMMONPCTrader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CarlosMMONPCTrader")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("86d60cf2-0118-4c54-a3c4-e0d4cf0f1341")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CarlosMMO;

[BepInPlugin("carlos.mmo.npctrader", "Carlos MMO NPC Trader", "1.0.5")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CarlosMMONPCTrader : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PlayerController), "TakeInput")]
	private static class PlayerController_TakeInput_Patch
	{
		private static bool Prefix(ref bool __result)
		{
			try
			{
				if (IsBlockingGameplayInput())
				{
					__result = false;
					return false;
				}
			}
			catch
			{
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "OnDeath")]
	private static class PlayerOnDeathPatch
	{
		private static void Prefix()
		{
			CloseUI();
		}
	}

	[HarmonyPatch(typeof(ZInput), "GetButton", new Type[] { typeof(string) })]
	private static class ZInputGetButtonPatch
	{
		private static bool Prefix(string name, ref bool __result)
		{
			if (!IsBlockingGameplayInput())
			{
				return true;
			}
			if (ShouldBlockInput(name))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(ZInput), "GetButtonDown", new Type[] { typeof(string) })]
	private static class ZInputGetButtonDownPatch
	{
		private static bool Prefix(string name, ref bool __result)
		{
			if (!IsBlockingGameplayInput())
			{
				return true;
			}
			if (ShouldBlockInput(name))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(ZInput), "GetButtonUp", new Type[] { typeof(string) })]
	private static class ZInputGetButtonUpPatch
	{
		private static bool Prefix(string name, ref bool __result)
		{
			if (!IsBlockingGameplayInput())
			{
				return true;
			}
			if (ShouldBlockInput(name))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}

	internal class TradeEntry
	{
		public readonly string ItemPrefabName;

		public readonly int Stack;

		public readonly int Price;

		public TradeEntry(string itemPrefabName, int stack, int price)
		{
			ItemPrefabName = itemPrefabName;
			Stack = stack;
			Price = price;
		}
	}

	public const string ModGuid = "carlos.mmo.npctrader";

	public const string ModName = "Carlos MMO NPC Trader";

	public const string ModVersion = "1.0.5";

	internal static CarlosMMONPCTrader Instance;

	internal static Harmony HarmonyInstance;

	private static ConfigEntry<string> _currencyItemName;

	private static ConfigEntry<string> _currencyDisplayNameOverride;

	private static ConfigEntry<int> _pieceStoneCost;

	private static ConfigEntry<int> _pieceWoodCost;

	private static ConfigEntry<int> _pieceFineWoodCost;

	private static ConfigEntry<string> _npcDisplayName;

	private static ConfigEntry<float> _interactDistance;

	private static ConfigEntry<float> _uiDistance;

	private static ConfigEntry<bool> _showOptionalPackStatus;

	private static ConfigEntry<bool> _preferPackCurrencyName;

	internal static bool UIVisible;

	internal static TraderNpcComponent CurrentTrader;

	private Rect _windowRect = new Rect(160f, 90f, 950f, 620f);

	private Vector2 _buyScroll = Vector2.zero;

	private Vector2 _sellScroll = Vector2.zero;

	private GUIStyle _windowStyle;

	private GUIStyle _titleStyle;

	private GUIStyle _sectionStyle;

	private GUIStyle _buttonStyle;

	private GUIStyle _closeButtonStyle;

	private GUIStyle _labelStyle;

	private GUIStyle _smallStyle;

	private GUIStyle _boxStyle;

	private GUIStyle _statusStyle;

	private bool _stylesInitialized;

	private bool _cursorWasVisible;

	private CursorLockMode _cursorPreviousLockMode = (CursorLockMode)1;

	private static readonly List<TradeEntry> BuyEntries = new List<TradeEntry>
	{
		new TradeEntry("Wood", 20, 15),
		new TradeEntry("Stone", 20, 15),
		new TradeEntry("Resin", 10, 18),
		new TradeEntry("Flint", 10, 20),
		new TradeEntry("LeatherScraps", 5, 25),
		new TradeEntry("DeerHide", 5, 30),
		new TradeEntry("Coal", 10, 22),
		new TradeEntry("CookedMeat", 5, 35),
		new TradeEntry("NeckTailGrilled", 5, 35),
		new TradeEntry("QueensJam", 2, 60),
		new TradeEntry("CarrotSoup", 2, 70),
		new TradeEntry("TurnipStew", 2, 80),
		new TradeEntry("Sausages", 2, 95),
		new TradeEntry("Bread", 2, 110),
		new TradeEntry("FishWraps", 2, 135),
		new TradeEntry("Iron", 5, 140),
		new TradeEntry("Silver", 5, 170),
		new TradeEntry("BlackMetal", 5, 190)
	};

	private static readonly List<TradeEntry> SellEntries = new List<TradeEntry>
	{
		new TradeEntry("CookedMeat", 5, 15),
		new TradeEntry("NeckTailGrilled", 5, 15),
		new TradeEntry("QueensJam", 2, 28),
		new TradeEntry("CarrotSoup", 2, 35),
		new TradeEntry("TurnipStew", 2, 40),
		new TradeEntry("Sausages", 2, 50),
		new TradeEntry("Bread", 2, 55),
		new TradeEntry("FishWraps", 2, 70),
		new TradeEntry("Iron", 5, 65),
		new TradeEntry("Silver", 5, 80),
		new TradeEntry("BlackMetal", 5, 90),
		new TradeEntry("Ruby", 1, 25),
		new TradeEntry("Amber", 1, 15),
		new TradeEntry("AmberPearl", 1, 20)
	};

	public static bool IsBlockingGameplayInput()
	{
		return UIVisible && (Object)(object)CurrentTrader != (Object)null;
	}

	private void Awake()
	{
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Expected O, but got Unknown
		Instance = this;
		_currencyItemName = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "CurrencyItem", "Coins", "Nome interno do item usado como moeda. Ex.: Coins ou CarlosCoin");
		_currencyDisplayNameOverride = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "CurrencyDisplayNameOverride", "", "Nome visível da moeda. Deixe vazio para usar o nome real do item. Ex.: CriptoVikings");
		_pieceStoneCost = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "PieceStoneCost", 20, "Custo em pedra para construir o Marco do Comerciante.");
		_pieceWoodCost = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "PieceWoodCost", 10, "Custo em madeira para construir o Marco do Comerciante.");
		_pieceFineWoodCost = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "PieceFineWoodCost", 5, "Custo em madeira fina para construir o Marco do Comerciante.");
		_npcDisplayName = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "NpcDisplayName", "Jamil o Comerciante", "Nome visível do NPC.");
		_interactDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "InteractDistance", 4f, "Distância de interação do NPC.");
		_uiDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "UIDistance", 6f, "Distância máxima para manter a interface aberta.");
		_showOptionalPackStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Optional Integration", "ShowPackStatusInUI", true, "Mostra na interface se mods do pack Carlos MMO foram detectados. Não cria dependência obrigatória.");
		_preferPackCurrencyName = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Optional Integration", "PreferCriptoVikingsWhenPackDetected", true, "Se nenhum nome visível de moeda for configurado manualmente, usa CriptoVikings quando detectar mods do pack.");
		HarmonyInstance = new Harmony("carlos.mmo.npctrader");
		HarmonyInstance.PatchAll();
		PrefabManager.OnVanillaPrefabsAvailable += RegisterTraderPiece;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Carlos MMO NPC Trader 1.0.5 carregado.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Nome configurado do NPC: " + GetConfiguredNpcDisplayName()));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Distância de interação configurada: " + GetConfiguredInteractDistance()));
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterTraderPiece;
		RestoreMouseState();
		if (HarmonyInstance != null)
		{
			HarmonyInstance.UnpatchSelf();
		}
	}

	private void Update()
	{
		//IL_004a: 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)
		if (!UIVisible)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || (Object)(object)CurrentTrader == (Object)null)
		{
			CloseUI();
			return;
		}
		ApplyMouseStateForMenu();
		if (Vector3.Distance(((Component)localPlayer).transform.position, ((Component)CurrentTrader).transform.position) > _uiDistance.Value)
		{
			((Character)localPlayer).Message((MessageType)2, "Você se afastou do comerciante.", 0, (Sprite)null);
			CloseUI();
		}
		else if (Input.GetKeyDown((KeyCode)27))
		{
			CloseUI();
		}
	}

	private void OnGUI()
	{
		//IL_0055: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		if (UIVisible && !((Object)(object)CurrentTrader == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
		{
			EnsureStyles();
			ApplyMouseStateForMenu();
			GUI.depth = 0;
			GUI.Box(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), GUIContent.none);
			_windowRect = GUI.Window(830177, _windowRect, new WindowFunction(DrawTraderWindow), "", _windowStyle);
		}
	}

	private void EnsureStyles()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Expected O, but got Unknown
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Expected O, but got Unknown
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Expected O, but got Unknown
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Expected O, but got Unknown
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Expected O, but got Unknown
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Expected O, but got Unknown
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Expected O, but got Unknown
		if (!_stylesInitialized)
		{
			_windowStyle = new GUIStyle(GUI.skin.window);
			_windowStyle.fontSize = 16;
			_windowStyle.padding = new RectOffset(16, 16, 16, 16);
			_titleStyle = new GUIStyle(GUI.skin.label);
			_titleStyle.fontSize = 22;
			_titleStyle.fontStyle = (FontStyle)1;
			_titleStyle.alignment = (TextAnchor)4;
			_sectionStyle = new GUIStyle(GUI.skin.label);
			_sectionStyle.fontSize = 17;
			_sectionStyle.fontStyle = (FontStyle)1;
			_buttonStyle = new GUIStyle(GUI.skin.button);
			_buttonStyle.fontSize = 14;
			_buttonStyle.fontStyle = (FontStyle)1;
			_buttonStyle.fixedHeight = 32f;
			_closeButtonStyle = new GUIStyle(GUI.skin.button);
			_closeButtonStyle.fontSize = 16;
			_closeButtonStyle.fontStyle = (FontStyle)1;
			_closeButtonStyle.alignment = (TextAnchor)4;
			_labelStyle = new GUIStyle(GUI.skin.label);
			_labelStyle.fontSize = 14;
			_labelStyle.wordWrap = false;
			_smallStyle = new GUIStyle(GUI.skin.label);
			_smallStyle.fontSize = 12;
			_smallStyle.wordWrap = true;
			_statusStyle = new GUIStyle(GUI.skin.label);
			_statusStyle.fontSize = 12;
			_statusStyle.fontStyle = (FontStyle)2;
			_statusStyle.wordWrap = true;
			_statusStyle.alignment = (TextAnchor)3;
			_boxStyle = new GUIStyle(GUI.skin.box);
			_boxStyle.padding = new RectOffset(10, 10, 10, 10);
			_stylesInitialized = true;
		}
	}

	private void DrawTraderWindow(int windowId)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			CloseUI();
			return;
		}
		if (GUI.Button(new Rect(((Rect)(ref _windowRect)).width - 42f, 8f, 28f, 24f), "X", _closeButtonStyle))
		{
			CloseUI();
			return;
		}
		string currencyDisplayName = GetCurrencyDisplayName();
		int balance = GetBalance(localPlayer);
		GUILayout.Space(4f);
		GUILayout.Label(_npcDisplayName.Value, _titleStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(4f);
		GUILayout.Label("Moeda atual: " + balance + " " + currencyDisplayName, _sectionStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label("Esquerda: comprar do NPC | Direita: vender para o NPC", _smallStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label("Feche com ESC ou pelo botão Fechar.", _smallStyle, Array.Empty<GUILayoutOption>());
		if (_showOptionalPackStatus.Value)
		{
			GUILayout.Space(2f);
			GUILayout.Label(GetPackStatusText(), _statusStyle, Array.Empty<GUILayoutOption>());
		}
		GUILayout.Space(10f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		DrawBuyPanel(localPlayer);
		GUILayout.Space(12f);
		DrawSellPanel(localPlayer);
		GUILayout.EndHorizontal();
		GUILayout.Space(8f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("Fechar", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }))
		{
			CloseUI();
		}
		GUILayout.FlexibleSpace();
		GUILayout.Label("Carlos MMO NPC Trader 1.0.5", _smallStyle, Array.Empty<GUILayoutOption>());
		GUILayout.EndHorizontal();
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 28f));
	}

	private void DrawBuyPanel(Player player)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginVertical(_boxStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(445f),
			GUILayout.Height(500f)
		});
		GUILayout.Label("COMPRAR DO NPC", _sectionStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(4f);
		_buyScroll = GUILayout.BeginScrollView(_buyScroll, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(425f),
			GUILayout.Height(450f)
		});
		for (int i = 0; i < BuyEntries.Count; i++)
		{
			TradeEntry tradeEntry = BuyEntries[i];
			ItemDrop itemDrop = GetItemDrop(tradeEntry.ItemPrefabName);
			if (!((Object)(object)itemDrop == (Object)null))
			{
				string text = itemDrop.m_itemData.m_shared.m_name;
				if (string.IsNullOrEmpty(text))
				{
					text = tradeEntry.ItemPrefabName;
				}
				GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
				string text2 = text;
				int stack = tradeEntry.Stack;
				GUILayout.Label(text2 + "  x" + stack, _labelStyle, Array.Empty<GUILayoutOption>());
				stack = tradeEntry.Price;
				GUILayout.Label("Preço: " + stack + " " + GetCurrencyDisplayName(), _smallStyle, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Comprar", _buttonStyle, Array.Empty<GUILayoutOption>()))
				{
					TryBuy(player, tradeEntry);
				}
				GUILayout.EndVertical();
			}
		}
		GUILayout.EndScrollView();
		GUILayout.EndVertical();
	}

	private void DrawSellPanel(Player player)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginVertical(_boxStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(445f),
			GUILayout.Height(500f)
		});
		GUILayout.Label("VENDER PARA O NPC", _sectionStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(4f);
		_sellScroll = GUILayout.BeginScrollView(_sellScroll, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(425f),
			GUILayout.Height(450f)
		});
		for (int i = 0; i < SellEntries.Count; i++)
		{
			TradeEntry tradeEntry = SellEntries[i];
			ItemDrop itemDrop = GetItemDrop(tradeEntry.ItemPrefabName);
			if (!((Object)(object)itemDrop == (Object)null))
			{
				string text = itemDrop.m_itemData.m_shared.m_name;
				if (string.IsNullOrEmpty(text))
				{
					text = tradeEntry.ItemPrefabName;
				}
				int num = CountItemByPrefabName(player, tradeEntry.ItemPrefabName);
				GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
				string text2 = text;
				int stack = tradeEntry.Stack;
				GUILayout.Label(text2 + "  x" + stack, _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Você tem: " + num, _smallStyle, Array.Empty<GUILayoutOption>());
				stack = tradeEntry.Price;
				GUILayout.Label("Pagamento: " + stack + " " + GetCurrencyDisplayName(), _smallStyle, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Vender", _buttonStyle, Array.Empty<GUILayoutOption>()))
				{
					TrySell(player, tradeEntry);
				}
				GUILayout.EndVertical();
			}
		}
		GUILayout.EndScrollView();
		GUILayout.EndVertical();
	}

	private void TryBuy(Player player, TradeEntry entry)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		ItemDrop itemDrop = GetItemDrop(entry.ItemPrefabName);
		if ((Object)(object)itemDrop == (Object)null)
		{
			((Character)player).Message((MessageType)2, "Item de venda não encontrado: " + entry.ItemPrefabName, 0, (Sprite)null);
			return;
		}
		int balance = GetBalance(player);
		if (balance < entry.Price)
		{
			((Character)player).Message((MessageType)2, "Moeda insuficiente.", 0, (Sprite)null);
		}
		else if (!SpendCoinsFromEconomy(player, entry.Price))
		{
			((Character)player).Message((MessageType)2, "Falha ao descontar moeda.", 0, (Sprite)null);
		}
		else if (!GiveItemByPrefabName(player, entry.ItemPrefabName, entry.Stack))
		{
			AddCoinsToEconomy(player, entry.Price);
			((Character)player).Message((MessageType)2, "Sem espaço no inventário.", 0, (Sprite)null);
		}
		else
		{
			((Character)player).Message((MessageType)2, "Compra concluída.", 0, (Sprite)null);
		}
	}

	private void TrySell(Player player, TradeEntry entry)
	{
		if (!((Object)(object)player == (Object)null))
		{
			int num = CountItemByPrefabName(player, entry.ItemPrefabName);
			if (num < entry.Stack)
			{
				((Character)player).Message((MessageType)2, "Você não tem itens suficientes para vender.", 0, (Sprite)null);
			}
			else if (!RemoveItemByPrefabName(player, entry.ItemPrefabName, entry.Stack))
			{
				((Character)player).Message((MessageType)2, "Falha ao remover item do inventário.", 0, (Sprite)null);
			}
			else if (!AddCoinsToEconomy(player, entry.Price))
			{
				GiveItemByPrefabName(player, entry.ItemPrefabName, entry.Stack);
				((Character)player).Message((MessageType)2, "Falha ao receber a moeda.", 0, (Sprite)null);
			}
			else
			{
				((Character)player).Message((MessageType)2, "Venda concluída.", 0, (Sprite)null);
			}
		}
	}

	private void RegisterTraderPiece()
	{
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Expected O, but got Unknown
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Expected O, but got Unknown
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Expected O, but got Unknown
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Expected O, but got Unknown
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Expected O, but got Unknown
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterTraderPiece;
		try
		{
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("piece_cmmo_trader_marker", "piece_banner01");
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Falha ao clonar piece_banner01 para o Marco do Comerciante.");
				return;
			}
			((Object)val).name = "piece_cmmo_trader_marker";
			HideOriginalVisuals(val);
			RemovePieceSideComponents(val);
			BuildTraderVisual(val);
			EnsurePieceCollider(val);
			if ((Object)(object)val.GetComponent<TraderNpcComponent>() == (Object)null)
			{
				val.AddComponent<TraderNpcComponent>();
			}
			Piece component = val.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "Marco do Comerciante";
				component.m_description = "Invoca o comerciante do Carlos MMO.";
				component.m_category = (PieceCategory)0;
				component.m_clipEverything = false;
				component.m_groundOnly = true;
				Sprite hammerIcon = GetHammerIcon();
				if ((Object)(object)hammerIcon != (Object)null)
				{
					component.m_icon = hammerIcon;
				}
			}
			PieceConfig val2 = new PieceConfig();
			val2.Name = "Marco do Comerciante";
			val2.Description = "Invoca o comerciante do Carlos MMO.";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "Misc";
			val2.CraftingStation = "piece_workbench";
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig("Stone", _pieceStoneCost.Value, 0, true),
				new RequirementConfig("Wood", _pieceWoodCost.Value, 0, true),
				new RequirementConfig("FineWood", _pieceFineWoodCost.Value, 0, true)
			};
			PieceConfig val3 = val2;
			PieceManager.Instance.AddPiece(new CustomPiece(val, false, val3));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Marco do Comerciante registrado com sucesso.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Erro ao registrar Marco do Comerciante: " + ex));
		}
	}

	private Sprite GetHammerIcon()
	{
		if ((Object)(object)ObjectDB.instance == (Object)null)
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer");
		if ((Object)(object)itemPrefab == (Object)null)
		{
			return null;
		}
		ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		return (component.m_itemData.m_shared.m_icons != null && component.m_itemData.m_shared.m_icons.Length != 0) ? component.m_itemData.m_shared.m_icons[0] : null;
	}

	private void HideOriginalVisuals(GameObject root)
	{
		MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			((Renderer)componentsInChildren[i]).enabled = false;
		}
		SkinnedMeshRenderer[] componentsInChildren2 = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			((Renderer)componentsInChildren2[j]).enabled = false;
		}
	}

	private void RemovePieceSideComponents(GameObject root)
	{
		CraftingStation component = root.GetComponent<CraftingStation>();
		if ((Object)(object)component != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component);
		}
		StationExtension component2 = root.GetComponent<StationExtension>();
		if ((Object)(object)component2 != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component2);
		}
		Container component3 = root.GetComponent<Container>();
		if ((Object)(object)component3 != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component3);
		}
		WearNTear component4 = root.GetComponent<WearNTear>();
		if ((Object)(object)component4 != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component4);
		}
		PrivateArea component5 = root.GetComponent<PrivateArea>();
		if ((Object)(object)component5 != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component5);
		}
	}

	private void BuildTraderVisual(GameObject root)
	{
		//IL_0061: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		GameObject prefab = PrefabManager.Instance.GetPrefab("Haldor");
		if ((Object)(object)prefab == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Prefab Haldor não encontrado. O trader ficará sem modelo visual.");
			return;
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, root.transform);
		((Object)val).name = "CMMO_TraderVisual";
		val.transform.localPosition = new Vector3(0f, 0f, 0f);
		val.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
		val.transform.localScale = Vector3.one;
		StripToVisualsOnly(val);
		Animator componentInChildren = val.GetComponentInChildren<Animator>(true);
		if ((Object)(object)componentInChildren != (Object)null)
		{
			((Behaviour)componentInChildren).enabled = true;
		}
	}

	private void StripToVisualsOnly(GameObject root)
	{
		Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
		foreach (Component val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer) && !(val is MeshFilter) && !(val is Animator) && !(val is ParticleSystem) && !(val is ParticleSystemRenderer) && !(val is Light))
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}
	}

	private void EnsurePieceCollider(GameObject root)
	{
		//IL_002c: 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)
		BoxCollider val = root.GetComponent<BoxCollider>();
		if ((Object)(object)val == (Object)null)
		{
			val = root.AddComponent<BoxCollider>();
		}
		val.center = new Vector3(0f, 1f, 0f);
		val.size = new Vector3(1.8f, 2.2f, 1.8f);
		((Collider)val).isTrigger = false;
	}

	private void ApplyMouseStateForMenu()
	{
		Cursor.visible = true;
		Cursor.lockState = (CursorLockMode)0;
	}

	private void RestoreMouseState()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		Cursor.visible = _cursorWasVisible;
		Cursor.lockState = _cursorPreviousLockMode;
	}

	private string GetPackStatusText()
	{
		bool flag = IsPluginLoadedByName("Carlos MMO Core");
		bool flag2 = IsPluginLoadedByName("Carlos MMO Economy");
		bool flag3 = IsPluginLoadedByName("Carlos MMO Loader");
		bool flag4 = IsPluginLoadedByName("Carlos MMO World HUD");
		if (!flag && !flag2 && !flag3 && !flag4)
		{
			return "Modo independente: funcionando sem outros mods do pack.";
		}
		List<string> list = new List<string>();
		if (flag3)
		{
			list.Add("Loader");
		}
		if (flag)
		{
			list.Add("Core");
		}
		if (flag2)
		{
			list.Add("Economy");
		}
		if (flag4)
		{
			list.Add("WorldHUD");
		}
		return "Integração opcional detectada: " + string.Join(", ", list.ToArray()) + ".";
	}

	private bool IsPackDetected()
	{
		return IsPluginLoadedByName("Carlos MMO Loader") || IsPluginLoadedByName("Carlos MMO Core") || IsPluginLoadedByName("Carlos MMO Economy") || IsPluginLoadedByName("Carlos MMO World HUD");
	}

	private bool IsPluginLoadedByName(string pluginName)
	{
		if (string.IsNullOrEmpty(pluginName))
		{
			return false;
		}
		foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
		{
			PluginInfo value = pluginInfo.Value;
			if (value == null || value.Metadata == null || !string.Equals(value.Metadata.Name, pluginName, StringComparison.OrdinalIgnoreCase))
			{
				continue;
			}
			return true;
		}
		return false;
	}

	internal static void OpenUI(TraderNpcComponent trader)
	{
		//IL_0040: 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 (!((Object)(object)trader == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)Instance == (Object)null))
		{
			Instance._cursorWasVisible = Cursor.visible;
			Instance._cursorPreviousLockMode = Cursor.lockState;
			CurrentTrader = trader;
			UIVisible = true;
			Instance.ApplyMouseStateForMenu();
		}
	}

	internal static void CloseUI()
	{
		UIVisible = false;
		CurrentTrader = null;
		if ((Object)(object)Instance != (Object)null)
		{
			Instance.RestoreMouseState();
		}
	}

	internal static string GetCurrencyDisplayName()
	{
		if (_currencyDisplayNameOverride != null && !string.IsNullOrWhiteSpace(_currencyDisplayNameOverride.Value))
		{
			return _currencyDisplayNameOverride.Value.Trim();
		}
		if ((Object)(object)Instance != (Object)null && _preferPackCurrencyName != null && _preferPackCurrencyName.Value && Instance.IsPackDetected())
		{
			return "CriptoVikings";
		}
		ItemDrop itemDrop = GetItemDrop(_currencyItemName.Value);
		if ((Object)(object)itemDrop != (Object)null && !string.IsNullOrEmpty(itemDrop.m_itemData.m_shared.m_name))
		{
			return itemDrop.m_itemData.m_shared.m_name;
		}
		return _currencyItemName.Value;
	}

	internal static string GetConfiguredNpcDisplayName()
	{
		if (_npcDisplayName != null && !string.IsNullOrWhiteSpace(_npcDisplayName.Value))
		{
			return _npcDisplayName.Value.Trim();
		}
		return "Jamil o Comerciante";
	}

	internal static float GetConfiguredInteractDistance()
	{
		if (_interactDistance == null)
		{
			return 4f;
		}
		return Mathf.Max(1.5f, _interactDistance.Value);
	}

	internal static ItemDrop GetItemDrop(string prefabName)
	{
		if ((Object)(object)ObjectDB.instance == (Object)null || string.IsNullOrEmpty(prefabName))
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
		if ((Object)(object)itemPrefab == (Object)null)
		{
			return null;
		}
		return itemPrefab.GetComponent<ItemDrop>();
	}

	internal static int CountItemByPrefabName(Player player, string prefabName)
	{
		if ((Object)(object)player == (Object)null || ((Humanoid)player).GetInventory() == null || string.IsNullOrEmpty(prefabName))
		{
			return 0;
		}
		int num = 0;
		List<ItemData> allItems = ((Humanoid)player).GetInventory().GetAllItems();
		for (int i = 0; i < allItems.Count; i++)
		{
			ItemData val = allItems[i];
			if (val != null && !((Object)(object)val.m_dropPrefab == (Object)null) && ((Object)val.m_dropPrefab).name == prefabName)
			{
				num += val.m_stack;
			}
		}
		return num;
	}

	internal static bool RemoveItemByPrefabName(Player player, string prefabName, int amount)
	{
		if ((Object)(object)player == (Object)null || ((Humanoid)player).GetInventory() == null || amount <= 0)
		{
			return false;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		List<ItemData> allItems = inventory.GetAllItems();
		int num = amount;
		for (int num2 = allItems.Count - 1; num2 >= 0; num2--)
		{
			ItemData val = allItems[num2];
			if (val != null && !((Object)(object)val.m_dropPrefab == (Object)null) && !(((Object)val.m_dropPrefab).name != prefabName))
			{
				int num3 = Math.Min(val.m_stack, num);
				val.m_stack -= num3;
				num -= num3;
				if (val.m_stack <= 0)
				{
					inventory.RemoveItem(val);
				}
				if (num <= 0)
				{
					return true;
				}
			}
		}
		return false;
	}

	internal static bool GiveItemByPrefabName(Player player, string prefabName, int amount)
	{
		if ((Object)(object)player == (Object)null || ((Humanoid)player).GetInventory() == null || amount <= 0)
		{
			return false;
		}
		ItemDrop itemDrop = GetItemDrop(prefabName);
		if ((Object)(object)itemDrop == (Object)null)
		{
			return false;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		bool result = true;
		for (int i = 0; i < amount; i++)
		{
			if (!inventory.AddItem(((Component)itemDrop).gameObject, 1))
			{
				result = false;
				break;
			}
		}
		return result;
	}

	internal static int GetBalance(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return 0;
		}
		if ((Object)(object)Instance == (Object)null || !Instance.IsPluginLoadedByName("Carlos MMO Economy"))
		{
			return CountItemByPrefabName(player, _currencyItemName.Value);
		}
		string text = ResolveEconomyWalletKey(player);
		if (string.IsNullOrEmpty(text))
		{
			return CountItemByPrefabName(player, _currencyItemName.Value);
		}
		return Mathf.Max(0, PlayerPrefs.GetInt(text, 0));
	}

	internal static bool SetBalance(Player player, int newBalance)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if ((Object)(object)Instance == (Object)null || !Instance.IsPluginLoadedByName("Carlos MMO Economy"))
		{
			return true;
		}
		string text = ResolveEconomyWalletKey(player);
		if (string.IsNullOrEmpty(text))
		{
			return false;
		}
		PlayerPrefs.SetInt(text, Mathf.Max(0, newBalance));
		PlayerPrefs.Save();
		return true;
	}

	internal static bool SpendCoinsFromEconomy(Player player, int amount)
	{
		if ((Object)(object)player == (Object)null || amount <= 0)
		{
			return false;
		}
		if ((Object)(object)Instance == (Object)null || !Instance.IsPluginLoadedByName("Carlos MMO Economy"))
		{
			return RemoveItemByPrefabName(player, _currencyItemName.Value, amount);
		}
		int balance = GetBalance(player);
		if (balance < amount)
		{
			return false;
		}
		return SetBalance(player, balance - amount);
	}

	internal static bool AddCoinsToEconomy(Player player, int amount)
	{
		if ((Object)(object)player == (Object)null || amount <= 0)
		{
			return false;
		}
		if ((Object)(object)Instance == (Object)null || !Instance.IsPluginLoadedByName("Carlos MMO Economy"))
		{
			return GiveItemByPrefabName(player, _currencyItemName.Value, amount);
		}
		int balance = GetBalance(player);
		long num = (long)balance + (long)amount;
		if (num > int.MaxValue)
		{
			num = 2147483647L;
		}
		return SetBalance(player, (int)num);
	}

	private static string ResolveEconomyWalletKey(Player player)
	{
		string text = "default";
		try
		{
			if ((Object)(object)Game.instance != (Object)null && Game.instance.GetPlayerProfile() != null)
			{
				string name = Game.instance.GetPlayerProfile().GetName();
				if (!string.IsNullOrEmpty(name))
				{
					text = name;
				}
			}
		}
		catch
		{
		}
		return "CarlosMMOEconomy_Balance_" + text;
	}

	private static bool ShouldBlockInput(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		int result;
		switch (name)
		{
		default:
			result = ((name == "JoyHide") ? 1 : 0);
			break;
		case "Attack":
		case "SecondaryAttack":
		case "Block":
		case "Use":
		case "JoyUse":
		case "JoyAttack":
		case "JoySecondaryAttack":
		case "JoyBlock":
		case "AltPlace":
		case "JoyAltPlace":
		case "Hide":
			result = 1;
			break;
		}
		return (byte)result != 0;
	}
}
public class TraderNpcComponent : MonoBehaviour, Hoverable, Interactable
{
	public string GetHoverName()
	{
		return CarlosMMONPCTrader.GetConfiguredNpcDisplayName();
	}

	public string GetHoverText()
	{
		return "[E] Negociar com " + GetHoverName();
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_003e: 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)
		if (CarlosMMONPCTrader.UIVisible)
		{
			return false;
		}
		if (hold || (Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer)
		{
			return false;
		}
		float configuredInteractDistance = CarlosMMONPCTrader.GetConfiguredInteractDistance();
		if (Vector3.Distance(((Component)user).transform.position, ((Component)this).transform.position) > configuredInteractDistance)
		{
			((Character)user).Message((MessageType)2, "Chegue mais perto do comerciante.", 0, (Sprite)null);
			return false;
		}
		CarlosMMONPCTrader.OpenUI(this);
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}
}