Decompiled source of MerchantNPCs v0.0.4
MerchantNPCs.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using MerchantNPCs.MerchantTrading; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("YamlDotNet")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MerchantNPCs")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("A mod that adds buildable merchant NPCs to Valheim")] [assembly: AssemblyFileVersion("0.0.3.0")] [assembly: AssemblyInformationalVersion("0.0.3")] [assembly: AssemblyProduct("MerchantNPCs")] [assembly: AssemblyTitle("MerchantNPCs")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.3.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 MerchantNPCs { [BepInPlugin("ruijven.merchantnpcs", "MerchantNPCs", "0.0.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class MerchantNPCsPlugin : BaseUnityPlugin { public const string PluginGUID = "ruijven.merchantnpcs"; public const string PluginName = "MerchantNPCs"; public const string PluginVersion = "0.0.4"; internal static ManualLogSource Logger; private const string AssetBundleName = "merchant1_ru"; private AssetBundle _merchantAssetBundle; private MerchantPieces _merchantPieces; private ConfigEntry<bool> _isModEnabled; internal static MerchantNPCsPlugin Instance { get; private set; } public Dictionary<string, MerchantCostConfig> MerchantCosts { get; private set; } = new Dictionary<string, MerchantCostConfig>(); private void ExtractEmbeddedConfigs() { try { string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames(); Logger.LogInfo((object)$"Found {manifestResourceNames.Length} embedded resources:"); string[] array = manifestResourceNames; foreach (string text in array) { Logger.LogInfo((object)(" - " + text)); } string text2 = Path.Combine(Paths.ConfigPath, "MerchantNPCs"); if (!Directory.Exists(text2)) { Directory.CreateDirectory(text2); Logger.LogInfo((object)("Created config directory: " + text2)); } string[] array2 = new string[9] { "Meadows.txt", "BlackForest.txt", "Swamp.txt", "Mountains.txt", "Plains.txt", "Mistlands.txt", "Ashlands.txt", "DeepNorth.txt", "Extra.txt" }; string[] array3 = array2; foreach (string text3 in array3) { string[] array4 = new string[3] { "MerchantNPCs.Configs." + text3, "Configs." + text3, text3 }; string text4 = Path.Combine(text2, text3); bool flag = false; if (!File.Exists(text4)) { string[] array5 = array4; foreach (string text5 in array5) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text5); if (stream != null) { using (FileStream destination = new FileStream(text4, FileMode.Create)) { stream.CopyTo(destination); } Logger.LogInfo((object)("Extracted config file: " + text3 + " from resource " + text5)); flag = true; break; } } if (!flag) { string text6 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..\\..\\..\\Configs", text3); if (File.Exists(text6)) { File.Copy(text6, text4); Logger.LogInfo((object)("Copied config file from project directory: " + text3)); } else { Logger.LogWarning((object)("Could not find config file " + text3 + " as embedded resource or in project directory")); File.WriteAllText(text4, "# " + text3.Replace(".txt", "") + " Merchant Items\n# Format: item:price\n\n# Add your items here\n"); Logger.LogInfo((object)("Created empty config file: " + text3)); } } } else { Logger.LogDebug((object)("Config file already exists: " + text3)); } } } catch (Exception ex) { Logger.LogError((object)("Error extracting config files: " + ex.Message)); } } private void Awake() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; _isModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IsModEnabled", true, "Enables or disables the mod"); if (!_isModEnabled.Value) { Logger.LogInfo((object)"Mod is disabled via configuration"); return; } InitializeMerchantCostConfigs(); ExtractEmbeddedConfigs(); PrefabManager.OnVanillaPrefabsAvailable += AddMerchantPieces; ZoneManager.OnVanillaLocationsAvailable += InitializeMerchantTrading; Harmony val = new Harmony("ruijven.merchantnpcs"); val.PatchAll(Assembly.GetExecutingAssembly()); Logger.LogInfo((object)"MerchantNPCs v0.0.4 loaded successfully!"); } private void InitializeMerchantCostConfigs() { Logger.LogInfo((object)"Initializing merchant cost configurations"); MerchantCostConfig merchantCostConfig = new MerchantCostConfig(); merchantCostConfig.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Meadows Merchant", 1, "Wood", 50); merchantCostConfig.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Meadows Merchant", 2, "Stone", 50); merchantCostConfig.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Meadows Merchant", 3, "Flint", 25); MerchantCosts["Meadows"] = merchantCostConfig; MerchantCostConfig merchantCostConfig2 = new MerchantCostConfig(); merchantCostConfig2.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Black Forest Merchant", 1, "RoundLog", 20); merchantCostConfig2.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Black Forest Merchant", 2, "TrollHide", 10); merchantCostConfig2.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Black Forest Merchant", 3, "Copper", 10); merchantCostConfig2.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Black Forest Merchant", 4, "TrophyEikthyr", 1); MerchantCosts["BlackForest"] = merchantCostConfig2; MerchantCostConfig merchantCostConfig3 = new MerchantCostConfig(); merchantCostConfig3.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Swamp Merchant", 1, "ElderBark", 20); merchantCostConfig3.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Swamp Merchant", 2, "Guck", 10); merchantCostConfig3.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Swamp Merchant", 3, "Iron", 10); merchantCostConfig3.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Swamp Merchant", 4, "TrophyTheElder", 1); MerchantCosts["Swamp"] = merchantCostConfig3; MerchantCostConfig merchantCostConfig4 = new MerchantCostConfig(); merchantCostConfig4.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mountains Merchant", 1, "FreezeGland", 10); merchantCostConfig4.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mountains Merchant", 2, "WolfPelt", 10); merchantCostConfig4.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mountains Merchant", 3, "Silver", 10); merchantCostConfig4.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mountains Merchant", 4, "TrophyBonemass", 1); MerchantCosts["Mountain"] = merchantCostConfig4; MerchantCostConfig merchantCostConfig5 = new MerchantCostConfig(); merchantCostConfig5.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Plains Merchant", 1, "Barley", 10); merchantCostConfig5.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Plains Merchant", 2, "BlackMetalScrap", 10); merchantCostConfig5.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Plains Merchant", 3, "Needle", 5); merchantCostConfig5.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Plains Merchant", 4, "TrophyDragonQueen", 1); MerchantCosts["Plains"] = merchantCostConfig5; MerchantCostConfig merchantCostConfig6 = new MerchantCostConfig(); merchantCostConfig6.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mistlands Merchant", 1, "RoyalJelly", 10); merchantCostConfig6.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mistlands Merchant", 2, "YggdrasilWood", 20); merchantCostConfig6.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mistlands Merchant", 3, "Carapace", 5); merchantCostConfig6.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Mistlands Merchant", 4, "TrophyGoblinKing", 1); MerchantCosts["Mistlands"] = merchantCostConfig6; MerchantCostConfig merchantCostConfig7 = new MerchantCostConfig(); merchantCostConfig7.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Ashlands Merchant", 1, "Blackwood", 20); merchantCostConfig7.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Ashlands Merchant", 2, "FlametalOreNew", 5); merchantCostConfig7.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Ashlands Merchant", 3, "Fiddleheadfern", 10); merchantCostConfig7.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Ashlands Merchant", 4, "TrophySeekerQueen", 1); MerchantCosts["Ashlands"] = merchantCostConfig7; MerchantCostConfig merchantCostConfig8 = new MerchantCostConfig(); merchantCostConfig8.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Deep North Merchant", 1, "FreezeGland", 200); merchantCostConfig8.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Deep North Merchant", 2, "WolfPelt", 200); merchantCostConfig8.AddResourceRequirement(((BaseUnityPlugin)this).Config, "Deep North Merchant", 3, "TrophyGoblinKing", 20); MerchantCosts["DeepNorth"] = merchantCostConfig8; Logger.LogInfo((object)$"Initialized {MerchantCosts.Count} merchant cost configurations"); } private void AddMerchantPieces() { try { LoadAssetBundle(); if ((Object)(object)_merchantAssetBundle == (Object)null) { Logger.LogError((object)"Failed to load asset bundle"); return; } RegisterAllAssets(); CreateMerchantPieceTab(); _merchantPieces = new MerchantPieces(_merchantAssetBundle, this); _merchantPieces.AddAllPieces(); Logger.LogInfo((object)"Merchant pieces added successfully"); } catch (Exception ex) { Logger.LogError((object)("Error adding merchant pieces: " + ex.Message + "\n" + ex.StackTrace)); } } private void LoadAssetBundle() { try { _merchantAssetBundle = AssetUtils.LoadAssetBundleFromResources("merchant1_ru", Assembly.GetExecutingAssembly()); if ((Object)(object)_merchantAssetBundle != (Object)null) { string[] allAssetNames = _merchantAssetBundle.GetAllAssetNames(); Logger.LogInfo((object)$"Asset bundle contains {allAssetNames.Length} assets:"); string[] array = allAssetNames; foreach (string text in array) { Logger.LogInfo((object)("- " + text)); } Logger.LogInfo((object)"Asset bundle contains the following asset types:"); string[] array2 = (from name in _merchantAssetBundle.GetAllAssetNames() where (Object)(object)_merchantAssetBundle.LoadAsset<GameObject>(name) != (Object)null select name).ToArray(); Logger.LogInfo((object)string.Format("GameObjects ({0}): {1}", array2.Length, string.Join(", ", array2))); string[] array3 = (from name in _merchantAssetBundle.GetAllAssetNames() where (Object)(object)_merchantAssetBundle.LoadAsset<Sprite>(name) != (Object)null select name).ToArray(); Logger.LogInfo((object)string.Format("Sprites ({0}): {1}", array3.Length, string.Join(", ", array3))); string[] array4 = (from name in _merchantAssetBundle.GetAllAssetNames() where (Object)(object)_merchantAssetBundle.LoadAsset<Material>(name) != (Object)null select name).ToArray(); Logger.LogInfo((object)string.Format("Materials ({0}): {1}", array4.Length, string.Join(", ", array4))); string[] array5 = (from name in _merchantAssetBundle.GetAllAssetNames() where (Object)(object)_merchantAssetBundle.LoadAsset<Texture>(name) != (Object)null select name).ToArray(); Logger.LogInfo((object)string.Format("Textures ({0}): {1}", array5.Length, string.Join(", ", array5))); string[] array6 = (from name in _merchantAssetBundle.GetAllAssetNames() where (Object)(object)_merchantAssetBundle.LoadAsset<AnimationClip>(name) != (Object)null select name).ToArray(); Logger.LogInfo((object)string.Format("Animations ({0}): {1}", array6.Length, string.Join(", ", array6))); Logger.LogInfo((object)"Asset bundle loaded successfully"); } else { Logger.LogError((object)"Asset bundle is null after loading"); } } catch (Exception ex) { Logger.LogError((object)("Error loading asset bundle: " + ex.Message + "\n" + ex.StackTrace)); } } private void CreateMerchantPieceTab() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) try { Sprite val = null; if ((Object)(object)_merchantAssetBundle != (Object)null) { val = _merchantAssetBundle.LoadAsset<Sprite>("tradericon_ru"); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)"Could not load tradericon_ru from asset bundle, using default tab icon"); } } PieceTableConfig val2 = new PieceTableConfig(); val2.CanRemovePieces = true; val2.UseCategories = true; val2.UseCustomCategories = true; val2.CustomCategories = new string[1] { "Merchants" }; PieceTableConfig val3 = val2; CustomPieceTable val4 = new CustomPieceTable("_MerchantPieceTable", val3); PieceManager.Instance.AddPieceTable(val4); PieceManager.Instance.AddPieceCategory("Merchants"); Logger.LogInfo((object)"Created merchant piece table with name: _MerchantPieceTable"); Logger.LogInfo((object)"Added custom category 'Merchants' to the Hammer"); Logger.LogInfo((object)"Merchant piece tab created successfully"); } catch (Exception ex) { Logger.LogError((object)("Error creating merchant piece tab: " + ex.Message + "\n" + ex.StackTrace)); } } private void RegisterAllAssets() { try { if ((Object)(object)_merchantAssetBundle == (Object)null) { Logger.LogError((object)"Cannot register assets: Asset bundle is null"); return; } string[] allAssetNames = _merchantAssetBundle.GetAllAssetNames(); Logger.LogInfo((object)$"Preparing to register {allAssetNames.Length} assets from bundle"); int num = 0; string[] array = allAssetNames; foreach (string path in array) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); GameObject val = _merchantAssetBundle.LoadAsset<GameObject>(fileNameWithoutExtension); if ((Object)(object)val != (Object)null) { try { PrefabManager.Instance.AddPrefab(val); Logger.LogInfo((object)("Registered prefab: " + fileNameWithoutExtension)); num++; } catch (Exception ex) { Logger.LogWarning((object)("Failed to register prefab " + fileNameWithoutExtension + ": " + ex.Message)); } } } Logger.LogInfo((object)$"Registered {num} prefabs"); int num2 = 0; string[] array2 = allAssetNames; foreach (string path2 in array2) { string fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(path2); Sprite val2 = _merchantAssetBundle.LoadAsset<Sprite>(fileNameWithoutExtension2); if ((Object)(object)val2 != (Object)null) { Logger.LogInfo((object)("Loaded sprite: " + fileNameWithoutExtension2)); num2++; } } Logger.LogInfo((object)$"Loaded {num2} sprites"); int num3 = 0; string[] array3 = allAssetNames; foreach (string path3 in array3) { string fileNameWithoutExtension3 = Path.GetFileNameWithoutExtension(path3); Material val3 = _merchantAssetBundle.LoadAsset<Material>(fileNameWithoutExtension3); if ((Object)(object)val3 != (Object)null) { Logger.LogInfo((object)("Loaded material: " + fileNameWithoutExtension3)); num3++; } } Logger.LogInfo((object)$"Loaded {num3} materials"); int num4 = 0; string[] array4 = allAssetNames; foreach (string path4 in array4) { string fileNameWithoutExtension4 = Path.GetFileNameWithoutExtension(path4); Texture val4 = _merchantAssetBundle.LoadAsset<Texture>(fileNameWithoutExtension4); if ((Object)(object)val4 != (Object)null) { Logger.LogInfo((object)("Loaded texture: " + fileNameWithoutExtension4)); num4++; } } Logger.LogInfo((object)$"Loaded {num4} textures"); int num5 = 0; string[] array5 = allAssetNames; foreach (string path5 in array5) { string fileNameWithoutExtension5 = Path.GetFileNameWithoutExtension(path5); AnimationClip val5 = _merchantAssetBundle.LoadAsset<AnimationClip>(fileNameWithoutExtension5); if ((Object)(object)val5 != (Object)null) { Logger.LogInfo((object)("Loaded animation: " + fileNameWithoutExtension5)); num5++; } } Logger.LogInfo((object)$"Loaded {num5} animations"); Logger.LogInfo((object)"All assets registered successfully"); } catch (Exception ex2) { Logger.LogError((object)("Error registering assets: " + ex2.Message + "\n" + ex2.StackTrace)); } } private void InitializeMerchantTrading() { try { if (MerchantManager.Instance != null) { MerchantManager.Instance.Initialize(); Logger.LogInfo((object)"Merchant manager initialized successfully"); } else { Logger.LogError((object)"MerchantManager instance is null"); } try { MerchantUI.Initialize(); Logger.LogInfo((object)"MerchantUI instance initialized - UI will be created on demand"); } catch (Exception ex) { Logger.LogError((object)("Error initializing merchant UI instance: " + ex.Message + "\n" + ex.StackTrace)); Logger.LogInfo((object)"MerchantUI instance initialization failed, but the mod will continue to function"); } Logger.LogInfo((object)"Merchant trading system initialized successfully"); } catch (Exception ex2) { Logger.LogError((object)("Error initializing merchant trading system: " + ex2.Message + "\n" + ex2.StackTrace)); } } } public class MerchantBehavior : MonoBehaviour, Hoverable, Interactable { [Header("Merchant Settings")] [SerializeField] private string _merchantName = "Merchant"; [SerializeField] private string _merchantType = ""; [SerializeField] private string _merchantGreeting = "Hello, traveler!"; [SerializeField] private float _interactionDistance = 5f; private Player _interactingPlayer; private string _hoverText; private void Awake() { if (string.IsNullOrEmpty(_merchantName) || _merchantName == "Merchant") { if (((Object)((Component)this).gameObject).name.Contains("Merch_ru")) { string name = ((Object)((Component)this).gameObject).name; name = name.Replace("(Clone)", ""); string text = name.Replace("Merch_ru", ""); if (text == "Blackforest") { _merchantName = "Black Forest Merchant"; _merchantType = "BlackForest"; } else if (text == "DeepNorth") { _merchantName = "Deep North Merchant"; _merchantType = "DeepNorth"; } else { _merchantName = text + " Merchant"; _merchantType = text; } MerchantNPCsPlugin.Logger.LogInfo((object)("Set merchant name to " + _merchantName + " based on prefab " + name)); } else { _merchantName = "Merchant"; _merchantType = ""; MerchantNPCsPlugin.Logger.LogWarning((object)("Could not determine merchant type from prefab name: " + ((Object)((Component)this).gameObject).name)); } } _hoverText = "[<color=yellow><b>E</b></color>] Trade with " + _merchantName; if (!Object.op_Implicit((Object)(object)((Component)this).GetComponent<ZNetView>())) { MerchantNPCsPlugin.Logger.LogWarning((object)("Merchant " + ((Object)((Component)this).gameObject).name + " is missing ZNetView component")); } } public string GetHoverText() { return _hoverText; } public string GetHoverName() { return _merchantName; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_009b: 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) MerchantNPCsPlugin.Logger.LogInfo((object)("Merchant " + ((Object)((Component)this).gameObject).name + " interaction started")); if (hold) { MerchantNPCsPlugin.Logger.LogInfo((object)"Hold interaction not supported"); return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"User is not a Player"); return false; } MerchantNPCsPlugin.Logger.LogInfo((object)("Player " + val.GetPlayerName() + " is interacting with merchant " + _merchantName)); float num = Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position); MerchantNPCsPlugin.Logger.LogInfo((object)$"Distance to player: {num}, Interaction distance: {_interactionDistance}"); if (num > _interactionDistance) { MerchantNPCsPlugin.Logger.LogInfo((object)"Player is too far away"); ((Character)val).Message((MessageType)2, "Get closer to interact with the merchant", 0, (Sprite)null); return false; } _interactingPlayer = val; MerchantNPCsPlugin.Logger.LogInfo((object)"Set interacting player"); ((Character)val).Message((MessageType)2, _merchantName + ": " + _merchantGreeting, 0, (Sprite)null); MerchantNPCsPlugin.Logger.LogInfo((object)("Showed greeting: " + _merchantName + ": " + _merchantGreeting)); MerchantNPCsPlugin.Logger.LogInfo((object)"Opening merchant UI..."); OpenMerchantUI(); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void OpenMerchantUI() { try { MerchantNPCsPlugin.Logger.LogInfo((object)"OpenMerchantUI method called"); if ((Object)(object)_interactingPlayer == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Cannot open merchant UI: No interacting player"); return; } MerchantNPCsPlugin.Logger.LogInfo((object)("Interacting player: " + _interactingPlayer.GetPlayerName())); MerchantNPCsPlugin.Logger.LogInfo((object)("Merchant type: " + _merchantType)); if ((Object)(object)MerchantUI.Instance == (Object)null) { MerchantNPCsPlugin.Logger.LogInfo((object)"MerchantUI instance is null, initializing..."); MerchantUI.Initialize(); if ((Object)(object)MerchantUI.Instance == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to initialize MerchantUI instance"); ((Character)_interactingPlayer).Message((MessageType)2, "Error initializing merchant UI", 0, (Sprite)null); return; } MerchantNPCsPlugin.Logger.LogInfo((object)"MerchantUI instance initialized successfully"); } else { MerchantNPCsPlugin.Logger.LogInfo((object)"MerchantUI instance already exists"); } MerchantNPCsPlugin.Logger.LogInfo((object)"Calling MerchantUI.Show method..."); MerchantUI.Instance.Show(_merchantType, _interactingPlayer); MerchantNPCsPlugin.Logger.LogInfo((object)"MerchantUI.Show method completed"); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error opening merchant UI: " + ex.Message + "\n" + ex.StackTrace)); if ((Object)(object)_interactingPlayer != (Object)null) { ((Character)_interactingPlayer).Message((MessageType)2, "Error opening merchant UI", 0, (Sprite)null); } } } } public class ResourceRequirement { public ConfigEntry<string> ItemType { get; set; } public ConfigEntry<int> Amount { get; set; } } public class MerchantCostConfig { private List<ResourceRequirement> _requirements = new List<ResourceRequirement>(); public void AddResourceRequirement(ConfigFile config, string merchantType, int index, string defaultItemType, int defaultAmount) { ResourceRequirement item = new ResourceRequirement { ItemType = config.Bind<string>(merchantType, $"Resource{index}Type", defaultItemType, $"Item type for resource requirement #{index}"), Amount = config.Bind<int>(merchantType, $"Resource{index}Amount", defaultAmount, $"Amount required for resource #{index} ({defaultItemType})") }; _requirements.Add(item); } public List<(string itemType, int amount)> GetRequirements() { List<(string, int)> list = new List<(string, int)>(); foreach (ResourceRequirement requirement in _requirements) { if (!string.IsNullOrEmpty(requirement.ItemType.Value) && requirement.Amount.Value > 0) { list.Add((requirement.ItemType.Value, requirement.Amount.Value)); } } return list; } } internal class MerchantPieces { private readonly AssetBundle _assetBundle; private readonly MerchantNPCsPlugin _plugin; private readonly List<CustomPiece> _addedPieces = new List<CustomPiece>(); public MerchantPieces(AssetBundle assetBundle, MerchantNPCsPlugin plugin) { _assetBundle = assetBundle; _plugin = plugin; } public void AddAllPieces() { try { if ((Object)(object)_assetBundle == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Asset bundle is null, cannot add pieces"); return; } AddMeadowsMerchant(); AddBlackForestMerchant(); AddSwampMerchant(); AddMountainMerchant(); AddPlainsMerchant(); AddMistlandsMerchant(); AddAshlandsMerchant(); AddDeepNorthMerchant(); MerchantNPCsPlugin.Logger.LogInfo((object)$"Added {_addedPieces.Count} merchant pieces to the game"); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error adding merchant pieces: " + ex.Message + "\n" + ex.StackTrace)); } } private void AddMerchantPiece(string prefabName, string pieceName, string description, List<RequirementConfig> requirements) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown try { GameObject val = _assetBundle.LoadAsset<GameObject>(prefabName); if ((Object)(object)val == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)("Failed to load prefab " + prefabName + " from asset bundle")); return; } EnsurePieceComponents(val); string text = prefabName.Replace("Merch_ru", ""); Sprite val2 = null; string text2 = ((!(text == "Mountain")) ? (text + "Icon_ru") : "MountainsIcon_ru"); val2 = _assetBundle.LoadAsset<Sprite>(text2); MerchantNPCsPlugin.Logger.LogInfo((object)("Trying to load icon " + text2 + " for " + prefabName)); if ((Object)(object)val2 == (Object)null) { val2 = _assetBundle.LoadAsset<Sprite>("texts_icon1"); MerchantNPCsPlugin.Logger.LogWarning((object)("Using fallback icon for " + prefabName)); } if ((Object)(object)val2 == (Object)null) { MerchantNPCsPlugin.Logger.LogWarning((object)("Failed to load any icon for " + prefabName)); } PieceConfig val3 = new PieceConfig { Name = pieceName, Description = description, PieceTable = "Hammer", Category = "Merchants", Requirements = requirements.ToArray(), Icon = val2 }; CustomPiece val4 = new CustomPiece(val, false, val3); PieceManager.Instance.AddPiece(val4); _addedPieces.Add(val4); MerchantNPCsPlugin.Logger.LogInfo((object)("Added merchant piece: " + pieceName)); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error adding merchant piece " + prefabName + ": " + ex.Message + "\n" + ex.StackTrace)); } } private void EnsurePieceComponents(GameObject prefab) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_02e8: Unknown result type (might be due to invalid IL or missing references) try { Piece val = prefab.GetComponent<Piece>(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent<Piece>(); MerchantNPCsPlugin.Logger.LogInfo((object)("Added Piece component to " + ((Object)prefab).name)); } val.m_resources = (Requirement[])(object)new Requirement[0]; val.m_craftingStation = null; val.m_enabled = true; val.m_category = (PieceCategory)0; val.m_canBeRemoved = true; val.m_allowedInDungeons = false; WearNTear val2 = prefab.GetComponent<WearNTear>(); if ((Object)(object)val2 == (Object)null) { val2 = prefab.AddComponent<WearNTear>(); MerchantNPCsPlugin.Logger.LogInfo((object)("Added WearNTear component to " + ((Object)prefab).name)); } val2.m_noRoofWear = false; val2.m_noSupportWear = false; val2.m_supports = true; val2.m_materialType = (MaterialType)1; val2.m_health = 10000000f; val2.m_damages.m_blunt = (DamageModifier)0; val2.m_damages.m_slash = (DamageModifier)0; val2.m_damages.m_pierce = (DamageModifier)0; val2.m_damages.m_chop = (DamageModifier)0; val2.m_damages.m_pickaxe = (DamageModifier)0; val2.m_damages.m_fire = (DamageModifier)0; val2.m_damages.m_frost = (DamageModifier)0; val2.m_damages.m_lightning = (DamageModifier)0; val2.m_damages.m_poison = (DamageModifier)0; val2.m_damages.m_spirit = (DamageModifier)0; val.m_groundPiece = false; val.m_groundOnly = false; val.m_cultivatedGroundOnly = false; val.m_waterPiece = false; val.m_noInWater = true; val.m_notOnWood = false; val.m_notOnTiltingSurface = false; ((StaticTarget)val).m_primaryTarget = false; if (val.m_resources == null || val.m_resources.Length == 0) { val.m_resources = (Requirement[])(object)new Requirement[0]; } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab2 = ZNetScene.instance.GetPrefab("sfx_build_hammer_stone"); if ((Object)(object)prefab2 != (Object)null) { Piece obj = val; EffectList val3 = new EffectList(); val3.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = prefab2 } }; obj.m_placeEffect = val3; } } val.m_clipEverything = true; ZNetView val4 = prefab.GetComponent<ZNetView>(); if ((Object)(object)val4 == (Object)null) { val4 = prefab.AddComponent<ZNetView>(); MerchantNPCsPlugin.Logger.LogInfo((object)("Added ZNetView component to " + ((Object)prefab).name)); } val4.m_persistent = true; val4.m_type = (ObjectType)0; val4.m_syncInitialScale = true; if ((Object)(object)val2 != (Object)null && !val4.m_syncInitialScale) { val4.m_syncInitialScale = true; } CapsuleCollider[] components = prefab.GetComponents<CapsuleCollider>(); CapsuleCollider[] array = components; foreach (CapsuleCollider val5 in array) { if (((Collider)val5).isTrigger) { MerchantNPCsPlugin.Logger.LogInfo((object)("Found trigger collider on " + ((Object)prefab).name + ", not removing it")); } } CapsuleCollider val6 = prefab.AddComponent<CapsuleCollider>(); val6.center = new Vector3(0f, 1f, 0f); val6.radius = 0.4f; val6.height = 1.8f; val6.direction = 1; ((Collider)val6).isTrigger = false; MerchantNPCsPlugin.Logger.LogInfo((object)("Added solid capsule collider to " + ((Object)prefab).name)); MerchantBehavior component = prefab.GetComponent<MerchantBehavior>(); if ((Object)(object)component == (Object)null) { component = prefab.AddComponent<MerchantBehavior>(); MerchantNPCsPlugin.Logger.LogInfo((object)("Added MerchantBehavior component to " + ((Object)prefab).name)); string value = ""; if (((Object)prefab).name.Contains("MeadowsMerch")) { value = "Meadows"; } else if (((Object)prefab).name.Contains("BlackforestMerch")) { value = "BlackForest"; } else if (((Object)prefab).name.Contains("SwampMerch")) { value = "Swamp"; } else if (((Object)prefab).name.Contains("MountainMerch")) { value = "Mountain"; } else if (((Object)prefab).name.Contains("PlainsMerch")) { value = "Plains"; } else if (((Object)prefab).name.Contains("MistlandsMerch")) { value = "Mistlands"; } else if (((Object)prefab).name.Contains("AshlandsMerch")) { value = "Ashlands"; } else if (((Object)prefab).name.Contains("DeepNorthMerch")) { value = "DeepNorth"; } FieldInfo field = typeof(MerchantBehavior).GetField("_merchantType", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(component, value); } } } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error ensuring piece components for " + ((Object)prefab).name + ": " + ex.Message + "\n" + ex.StackTrace)); } } private void AddMeadowsMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("Meadows", ("$item_wood", 50), ("$item_stone", 50), ("$item_flint", 25)); AddMerchantPiece("MeadowsMerch_ru", "Meadows Merchant", "A merchant selling basic meadows resources and tools", requirementsFromConfig); } private void AddBlackForestMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("BlackForest", ("RoundLog", 20), ("TrollHide", 10), ("Copper", 10), ("TrophyEikthyr", 1)); AddMerchantPiece("BlackforestMerch_ru", "Black Forest Merchant", "A merchant selling Black Forest resources and bronze equipment", requirementsFromConfig); } private List<RequirementConfig> GetRequirementsFromConfig(string merchantType, params (string itemType, int defaultAmount)[] defaultRequirements) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_0056: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0082: Expected O, but got Unknown MerchantCostConfig value; MerchantCostConfig merchantCostConfig = (_plugin.MerchantCosts.TryGetValue(merchantType, out value) ? value : null); List<RequirementConfig> list = new List<RequirementConfig>(); if (merchantCostConfig != null) { List<(string, int)> requirements = merchantCostConfig.GetRequirements(); foreach (var (item, amount) in requirements) { list.Add(new RequirementConfig { Item = item, Amount = amount, Recover = true, AmountPerLevel = 0 }); } } if (list.Count == 0) { for (int i = 0; i < defaultRequirements.Length; i++) { var (item2, amount2) = defaultRequirements[i]; list.Add(new RequirementConfig { Item = item2, Amount = amount2, Recover = true, AmountPerLevel = 0 }); } } return list; } private void AddSwampMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("Swamp", ("$item_elderbark", 20), ("$item_guck", 10), ("$item_iron", 10), ("$item_trophy_elder", 1)); AddMerchantPiece("SwampMerch_ru", "Swamp Merchant", "A merchant selling swamp resources and iron equipment", requirementsFromConfig); } private void AddPlainsMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("Plains", ("Barley", 10), ("BlackMetalScrap", 10), ("Needle", 5), ("TrophyDragonQueen", 1)); AddMerchantPiece("PlainsMerch_ru", "Plains Merchant", "A merchant selling plains resources and black metal equipment", requirementsFromConfig); } private void AddMountainMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("Mountains", ("FreezeGland", 10), ("WolfPelt", 10), ("Silver", 10), ("TrophyBonemass", 1)); AddMerchantPiece("MountainMerch_ru", "Mountains Merchant", "A merchant selling mountains resources and silver equipment", requirementsFromConfig); } private void AddMistlandsMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("Mistlands", ("RoyalJelly", 10), ("YggdrasilWood", 20), ("Carapace", 5), ("TrophyGoblinKing", 1)); AddMerchantPiece("MistlandsMerch_ru", "Mistlands Merchant", "A merchant selling mistlands resources and carapace equipment", requirementsFromConfig); } private void AddAshlandsMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("Ashlands", ("Blackwood", 20), ("FlametalOreNew", 5), ("Fiddleheadfern", 10), ("TrophySeekerQueen", 1)); AddMerchantPiece("AshlandsMerch_ru", "Ashlands Merchant", "A merchant selling ashlands resources and flametal equipment", requirementsFromConfig); } private void AddDeepNorthMerchant() { List<RequirementConfig> requirementsFromConfig = GetRequirementsFromConfig("DeepNorth", ("FreezeGland", 200), ("WolfPelt", 200), ("TrophyFader", 20)); AddMerchantPiece("DeepNorthMerch_ru", "Deep North Merchant", "A merchant selling Deep North resources and frost equipment", requirementsFromConfig); } } } namespace MerchantNPCs.MerchantTrading { public class MerchantItem { public string ItemName { get; set; } public string OriginalItemName { get; set; } public int BuyPrice { get; set; } public int SellPrice => BuyPrice / 2; public ItemData ItemData { get; set; } public string PrefabName { get; set; } public bool IsAvailable => true; } public class MerchantInventory { public string MerchantType { get; set; } public List<MerchantItem> Items { get; set; } = new List<MerchantItem>(); } public class MerchantManager { [CompilerGenerated] private sealed class <UpdatePlayerEquipmentDelayed>d__15 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Player player; public ItemData newItem; public MerchantManager <>4__this; private Exception <ex>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdatePlayerEquipmentDelayed>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <ex>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; try { ((Humanoid)player).SetupEquipment(); if ((Object)(object)((Humanoid)player).m_visEquipment != (Object)null) { ((Humanoid)player).SetupVisEquipment(((Humanoid)player).m_visEquipment, false); } else { MerchantNPCsPlugin.Logger.LogWarning((object)"Visual equipment component still null after initialization attempt"); } if (Object.op_Implicit((Object)(object)((Character)player).m_nview) && ((Character)player).m_nview.IsValid()) { ((Humanoid)player).GetInventory().Changed(); } MerchantNPCsPlugin.Logger.LogInfo((object)"Equipment update completed successfully"); } catch (Exception ex) { <ex>5__1 = ex; MerchantNPCsPlugin.Logger.LogError((object)("Error in delayed equipment update: " + <ex>5__1.Message)); } 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 MerchantManager _instance; private Dictionary<string, MerchantInventory> _merchantInventories = new Dictionary<string, MerchantInventory>(); private string _configPath; public static MerchantManager Instance => _instance ?? (_instance = new MerchantManager()); private MerchantManager() { _configPath = Path.Combine(Paths.ConfigPath, "MerchantNPCs"); if (!Directory.Exists(_configPath)) { Directory.CreateDirectory(_configPath); CreateDefaultConfigs(); } } public void Initialize() { LoadAllMerchantConfigs(); MerchantNPCsPlugin.Logger.LogInfo((object)$"Loaded {_merchantInventories.Count} merchant inventories"); } private void CreateDefaultConfigs() { CreateDefaultConfig("Blacksmith", new List<MerchantItem> { new MerchantItem { ItemName = "AxeIron", BuyPrice = 120 }, new MerchantItem { ItemName = "Hammer", BuyPrice = 80 }, new MerchantItem { ItemName = "PickaxeIron", BuyPrice = 150 }, new MerchantItem { ItemName = "ArrowIron", BuyPrice = 8 }, new MerchantItem { ItemName = "SwordIron", BuyPrice = 200 }, new MerchantItem { ItemName = "SwordSilver", BuyPrice = 350 }, new MerchantItem { ItemName = "AtgeirIron", BuyPrice = 180 }, new MerchantItem { ItemName = "MaceSilver", BuyPrice = 300 } }); CreateDefaultConfig("Farmer", new List<MerchantItem> { new MerchantItem { ItemName = "Carrot", BuyPrice = 10 }, new MerchantItem { ItemName = "CarrotSeeds", BuyPrice = 5 }, new MerchantItem { ItemName = "Turnip", BuyPrice = 15 }, new MerchantItem { ItemName = "TurnipSeeds", BuyPrice = 8 }, new MerchantItem { ItemName = "Flax", BuyPrice = 25 }, new MerchantItem { ItemName = "Barley", BuyPrice = 20 }, new MerchantItem { ItemName = "Honey", BuyPrice = 12 }, new MerchantItem { ItemName = "QueenBee", BuyPrice = 200 }, new MerchantItem { ItemName = "Cultivator", BuyPrice = 60 } }); CreateDefaultConfig("Innkeeper", new List<MerchantItem> { new MerchantItem { ItemName = "MeadBaseFrostResist", BuyPrice = 50 }, new MerchantItem { ItemName = "MeadBaseHealthMedium", BuyPrice = 60 }, new MerchantItem { ItemName = "MeadBaseStaminaMedium", BuyPrice = 60 }, new MerchantItem { ItemName = "MeadBasePoisonResist", BuyPrice = 50 }, new MerchantItem { ItemName = "MeadBaseTasty", BuyPrice = 40 }, new MerchantItem { ItemName = "Bread", BuyPrice = 20 }, new MerchantItem { ItemName = "FishCooked", BuyPrice = 15 }, new MerchantItem { ItemName = "NeckTailGrilled", BuyPrice = 15 }, new MerchantItem { ItemName = "SerpentMeatCooked", BuyPrice = 80 } }); CreateDefaultConfig("Trader", new List<MerchantItem> { new MerchantItem { ItemName = "Ruby", BuyPrice = 200 }, new MerchantItem { ItemName = "Amber", BuyPrice = 100 }, new MerchantItem { ItemName = "FineWood", BuyPrice = 5 }, new MerchantItem { ItemName = "Iron", BuyPrice = 20 }, new MerchantItem { ItemName = "Silver", BuyPrice = 40 }, new MerchantItem { ItemName = "BlackMetal", BuyPrice = 60 }, new MerchantItem { ItemName = "Obsidian", BuyPrice = 25 }, new MerchantItem { ItemName = "Chitin", BuyPrice = 30 } }); } private void CreateDefaultConfig(string merchantType, List<MerchantItem> items) { string path = Path.Combine(_configPath, merchantType.ToLower() + ".txt"); List<string> list = new List<string>(); list.Add("# " + merchantType + " Items"); list.Add("# Format: item:price"); list.Add(""); foreach (MerchantItem item in items) { list.Add($"{item.ItemName}:{item.BuyPrice}"); } File.WriteAllLines(path, list); MerchantNPCsPlugin.Logger.LogInfo((object)("Created default config for " + merchantType)); } public void LoadAllMerchantConfigs() { _merchantInventories.Clear(); string[] files = Directory.GetFiles(_configPath, "*.txt"); if (files.Length != 0) { string[] array = files; foreach (string text in array) { try { LoadCompactFormatConfig(text); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error loading merchant config " + text + ": " + ex.Message)); } } } else { string[] files2 = Directory.GetFiles(_configPath, "*.yaml"); string[] array2 = files2; foreach (string text2 in array2) { try { ConvertYamlToCompactFormat(text2); } catch (Exception ex2) { MerchantNPCsPlugin.Logger.LogError((object)("Error converting YAML config " + text2 + ": " + ex2.Message)); } } files = Directory.GetFiles(_configPath, "*.txt"); string[] array3 = files; foreach (string text3 in array3) { try { LoadCompactFormatConfig(text3); } catch (Exception ex3) { MerchantNPCsPlugin.Logger.LogError((object)("Error loading merchant config " + text3 + ": " + ex3.Message)); } } } PopulateItemData(); } private void LoadCompactFormatConfig(string configFile) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(configFile); fileNameWithoutExtension = char.ToUpper(fileNameWithoutExtension[0]) + fileNameWithoutExtension.Substring(1); List<MerchantItem> list = new List<MerchantItem>(); string[] array = File.ReadAllLines(configFile); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#")) { continue; } string[] array3 = text2.Split(':'); if (array3.Length >= 2) { string text3 = array3[0].Trim(); string originalItemName = text3; if (!text3.StartsWith("$item_") && !text3.StartsWith("$")) { text3 = "$item_" + text3.Replace(" ", "_"); } if (int.TryParse(array3[1].Trim(), out var result)) { list.Add(new MerchantItem { ItemName = text3, OriginalItemName = originalItemName, BuyPrice = result }); } } } MerchantInventory value = new MerchantInventory { MerchantType = fileNameWithoutExtension, Items = list }; _merchantInventories[fileNameWithoutExtension] = value; MerchantNPCsPlugin.Logger.LogInfo((object)$"Loaded merchant config for {fileNameWithoutExtension} with {list.Count} items"); } private void ConvertYamlToCompactFormat(string yamlFile) { try { string text = Path.ChangeExtension(yamlFile, ".txt"); if (!File.Exists(text)) { MerchantNPCsPlugin.Logger.LogWarning((object)("Could not find converted file " + text + " for " + yamlFile)); } } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error converting YAML file " + yamlFile + ": " + ex.Message)); } } private void PopulateItemData() { foreach (MerchantInventory value in _merchantInventories.Values) { foreach (MerchantItem item in value.Items) { try { GameObject val = null; string text = null; ZNetScene instance = ZNetScene.instance; val = ((instance != null) ? instance.GetPrefab(item.ItemName) : null); if ((Object)(object)val != (Object)null) { text = item.ItemName; MerchantNPCsPlugin.Logger.LogDebug((object)("Found prefab using prefixed item name: " + item.ItemName)); } if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(item.OriginalItemName)) { ZNetScene instance2 = ZNetScene.instance; val = ((instance2 != null) ? instance2.GetPrefab(item.OriginalItemName) : null); if ((Object)(object)val != (Object)null) { text = item.OriginalItemName; MerchantNPCsPlugin.Logger.LogDebug((object)("Found prefab using original item name: " + item.OriginalItemName)); } } if ((Object)(object)val == (Object)null) { string text2 = item.OriginalItemName.ToLower(); ZNetScene instance3 = ZNetScene.instance; val = ((instance3 != null) ? instance3.GetPrefab(text2) : null); if ((Object)(object)val != (Object)null) { text = text2; MerchantNPCsPlugin.Logger.LogDebug((object)("Found prefab using lowercase name: " + text2)); } } if ((Object)(object)val == (Object)null) { string text3 = item.OriginalItemName.Replace(" ", "").ToLower(); ZNetScene instance4 = ZNetScene.instance; val = ((instance4 != null) ? instance4.GetPrefab(text3) : null); if ((Object)(object)val != (Object)null) { text = text3; MerchantNPCsPlugin.Logger.LogDebug((object)("Found prefab using no spaces lowercase name: " + text3)); } } if ((Object)(object)val == (Object)null) { string text4 = item.OriginalItemName.Replace(" ", ""); if (text4.Length > 0) { text4 = char.ToUpper(text4[0]) + text4.Substring(1).ToLower(); ZNetScene instance5 = ZNetScene.instance; val = ((instance5 != null) ? instance5.GetPrefab(text4) : null); if ((Object)(object)val != (Object)null) { text = text4; MerchantNPCsPlugin.Logger.LogDebug((object)("Found prefab using pascal case name: " + text4)); } } } if ((Object)(object)val == (Object)null) { string[] array = item.OriginalItemName.Split(' '); string text5 = ""; string[] array2 = array; foreach (string text6 in array2) { if (!string.IsNullOrEmpty(text6)) { text5 = text5 + char.ToUpper(text6[0]) + text6.Substring(1).ToLower(); } } ZNetScene instance6 = ZNetScene.instance; val = ((instance6 != null) ? instance6.GetPrefab(text5) : null); if ((Object)(object)val != (Object)null) { text = text5; MerchantNPCsPlugin.Logger.LogDebug((object)("Found prefab using multi-word pascal case name: " + text5)); } } if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { item.ItemData = component.m_itemData; item.PrefabName = ((Object)val).name; MerchantNPCsPlugin.Logger.LogDebug((object)("Found item data for " + item.ItemName + ", using prefab name: " + ((Object)val).name)); if (component.m_itemData.m_shared.m_name != item.ItemName) { MerchantNPCsPlugin.Logger.LogDebug((object)("Item name mismatch: Config=" + item.ItemName + ", Game=" + component.m_itemData.m_shared.m_name)); } } else { MerchantNPCsPlugin.Logger.LogWarning((object)("Prefab " + ((Object)val).name + " does not have an ItemDrop component")); } } else { MerchantNPCsPlugin.Logger.LogWarning((object)("Could not find prefab for item " + item.ItemName + " or " + item.OriginalItemName)); } } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error populating item data for " + item.ItemName + ": " + ex.Message)); } } } } public MerchantInventory GetMerchantInventory(string merchantType) { if (_merchantInventories.TryGetValue(merchantType, out var value)) { return value; } if (merchantType == "Mountain" && !_merchantInventories.ContainsKey("Mountain") && _merchantInventories.ContainsKey("Mountains")) { MerchantNPCsPlugin.Logger.LogInfo((object)"Using Mountains inventory for Mountains Merchant"); return _merchantInventories["Mountains"]; } if (merchantType == "Mountains" && !_merchantInventories.ContainsKey("Mountains") && _merchantInventories.ContainsKey("Mountain")) { MerchantNPCsPlugin.Logger.LogInfo((object)"Using Mountain inventory for Mountains Merchant"); return _merchantInventories["Mountain"]; } return null; } public bool BuyItem(Player player, MerchantItem item, int quantity = 1) { //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Expected O, but got Unknown try { if ((Object)(object)player == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"BuyItem: Player is null"); return false; } if (item == null) { MerchantNPCsPlugin.Logger.LogError((object)"BuyItem: Item is null"); ((Character)player).Message((MessageType)2, "Error: Invalid item", 0, (Sprite)null); return false; } if (quantity <= 0) { MerchantNPCsPlugin.Logger.LogError((object)$"BuyItem: Invalid quantity {quantity}"); return false; } MerchantNPCsPlugin.Logger.LogInfo((object)$"Attempting to buy {quantity}x {item.ItemName}"); if (!item.IsAvailable) { MerchantNPCsPlugin.Logger.LogInfo((object)("Item " + item.ItemName + " is not available for purchase")); ((Character)player).Message((MessageType)2, "This item is not available for purchase", 0, (Sprite)null); return false; } int num = item.BuyPrice * quantity; MerchantNPCsPlugin.Logger.LogInfo((object)$"Total cost: {num} coins"); if (!HasEnoughCoins(player, num)) { MerchantNPCsPlugin.Logger.LogInfo((object)"Player doesn't have enough coins"); ((Character)player).Message((MessageType)2, "You don't have enough coins for that", 0, (Sprite)null); return false; } if (item.ItemData == null) { MerchantNPCsPlugin.Logger.LogError((object)("BuyItem: ItemData is null for " + item.ItemName)); ((Character)player).Message((MessageType)2, "Error: Invalid item data", 0, (Sprite)null); return false; } if (!HasEnoughInventorySpace(player, item.ItemData, quantity)) { MerchantNPCsPlugin.Logger.LogInfo((object)"Player doesn't have enough inventory space"); ((Character)player).Message((MessageType)2, "You don't have enough space for that", 0, (Sprite)null); return false; } MerchantNPCsPlugin.Logger.LogInfo((object)$"Removing {num} coins from player"); RemoveCoins(player, num); GameObject val = null; if ((Object)(object)ZNetScene.instance == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"ZNetScene.instance is null"); ((Character)player).Message((MessageType)2, "Error: Game scene not fully loaded", 0, (Sprite)null); return false; } try { val = ZNetScene.instance.GetPrefab(item.ItemName); MerchantNPCsPlugin.Logger.LogInfo((object)("Trying to get prefab by ItemName: " + item.ItemName + ", result: " + (((Object)(object)val != (Object)null) ? "found" : "not found"))); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when getting prefab by ItemName: " + ex.Message)); } if ((Object)(object)val == (Object)null && item.ItemData != null && item.ItemData.m_shared != null) { try { string name = item.ItemData.m_shared.m_name; MerchantNPCsPlugin.Logger.LogInfo((object)("Trying to get prefab by shared name: " + name)); val = ZNetScene.instance.GetPrefab(name); } catch (Exception ex2) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when getting prefab by shared name: " + ex2.Message)); } } if ((Object)(object)val == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { try { val = ObjectDB.instance.GetItemPrefab(item.ItemName); MerchantNPCsPlugin.Logger.LogInfo((object)("Trying to get prefab from ObjectDB: " + (((Object)(object)val != (Object)null) ? "found" : "not found"))); } catch (Exception ex3) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when getting prefab from ObjectDB: " + ex3.Message)); } if ((Object)(object)val == (Object)null && item.ItemData != null && item.ItemData.m_shared != null) { try { string name2 = item.ItemData.m_shared.m_name; MerchantNPCsPlugin.Logger.LogInfo((object)("Searching ObjectDB items for: " + name2)); foreach (GameObject item2 in ObjectDB.instance.m_items) { if (!((Object)(object)item2 == (Object)null)) { ItemDrop component = item2.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_name == name2) { val = item2; MerchantNPCsPlugin.Logger.LogInfo((object)("Found prefab in ObjectDB items: " + ((Object)item2).name)); break; } } } } catch (Exception ex4) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when searching ObjectDB items: " + ex4.Message)); } } } if ((Object)(object)val == (Object)null) { try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating a simple prefab as last resort"); val = new GameObject(item.ItemName); ItemDrop val2 = val.AddComponent<ItemDrop>(); val2.m_itemData = item.ItemData.Clone(); } catch (Exception ex5) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when creating simple prefab: " + ex5.Message)); } } if ((Object)(object)val == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)("Could not find or create prefab for " + item.ItemName)); ((Character)player).Message((MessageType)2, "Error: Could not find item", 0, (Sprite)null); return false; } ItemDrop component2 = val.GetComponent<ItemDrop>(); if ((Object)(object)component2 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)("Prefab " + item.ItemName + " does not have an ItemDrop component")); ((Character)player).Message((MessageType)2, "Error: Invalid item", 0, (Sprite)null); return false; } try { ItemData val3 = component2.m_itemData.Clone(); val3.m_stack = quantity; if (val3.m_shared == null) { MerchantNPCsPlugin.Logger.LogWarning((object)("Item " + item.ItemName + " has null m_shared, attempting to fix")); val3.m_shared = component2.m_itemData.m_shared; } GameObject dropPrefab = val3.m_dropPrefab; if (string.IsNullOrEmpty((dropPrefab != null) ? ((Object)dropPrefab).name : null)) { MerchantNPCsPlugin.Logger.LogWarning((object)("Item " + item.ItemName + " has null prefab name, setting from original")); val3.m_dropPrefab = ((Component)component2).gameObject; } if (((Humanoid)player).GetInventory().AddItem(val3)) { string name3 = item.ItemData.m_shared.m_name; MerchantNPCsPlugin.Logger.LogInfo((object)$"Player purchased {quantity}x {name3}"); ((Character)player).Message((MessageType)2, $"You purchased {quantity}x {name3}", 0, (Sprite)null); ((Humanoid)player).GetInventory().Changed(); if (val3.IsEquipable()) { try { MerchantNPCsPlugin.Logger.LogInfo((object)"Updating equipment after purchase"); if ((Object)(object)((Humanoid)player).m_visEquipment == (Object)null) { MerchantNPCsPlugin.Logger.LogWarning((object)"Player visual equipment is null, attempting to initialize"); ((Humanoid)player).m_visEquipment = ((Component)player).GetComponent<VisEquipment>(); if ((Object)(object)((Humanoid)player).m_visEquipment == (Object)null) { ((Humanoid)player).m_visEquipment = ((Component)player).gameObject.AddComponent<VisEquipment>(); } } ((Humanoid)player).GetInventory().Changed(); ((MonoBehaviour)player).StartCoroutine(UpdatePlayerEquipmentDelayed(player, val3)); MerchantNPCsPlugin.Logger.LogInfo((object)"Equipment update initiated"); } catch (Exception ex6) { MerchantNPCsPlugin.Logger.LogError((object)("Error updating equipment: " + ex6.Message)); } } return true; } MerchantNPCsPlugin.Logger.LogError((object)("Failed to add " + item.ItemName + " to player inventory")); ((Character)player).Message((MessageType)2, "Error: Could not add item to inventory", 0, (Sprite)null); return false; } catch (Exception ex7) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when adding item to inventory: " + ex7.Message)); ((Character)player).Message((MessageType)2, "Error: Failed to add item to inventory", 0, (Sprite)null); return false; } } catch (Exception ex8) { MerchantNPCsPlugin.Logger.LogError((object)("Unhandled exception in BuyItem: " + ex8.Message + "\n" + ex8.StackTrace)); if ((Object)(object)player != (Object)null) { ((Character)player).Message((MessageType)2, "Error: Failed to complete purchase", 0, (Sprite)null); } return false; } } [IteratorStateMachine(typeof(<UpdatePlayerEquipmentDelayed>d__15))] private IEnumerator UpdatePlayerEquipmentDelayed(Player player, ItemData newItem) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <UpdatePlayerEquipmentDelayed>d__15(0) { <>4__this = this, player = player, newItem = newItem }; } public bool SellItem(Player player, ItemData item, int quantity = 1) { if ((Object)(object)player == (Object)null || item == null || quantity <= 0 || quantity > item.m_stack) { return false; } MerchantItem merchantItem = FindMerchantItem(item.m_shared.m_name); if (merchantItem == null) { ((Character)player).Message((MessageType)2, "This merchant doesn't buy that item", 0, (Sprite)null); return false; } int num = merchantItem.SellPrice * quantity; ((Humanoid)player).GetInventory().RemoveItem(item.m_shared.m_name, quantity, -1, true); ((Humanoid)player).GetInventory().AddItem("Coins", num, 1, 0, 0L, "0", false); ((Character)player).Message((MessageType)2, $"You sold {quantity}x {item.m_shared.m_name} for {num} coins", 0, (Sprite)null); return true; } private MerchantItem FindMerchantItem(string itemName) { foreach (MerchantInventory value in _merchantInventories.Values) { foreach (MerchantItem item in value.Items) { if (item.ItemName == itemName || (item.ItemData != null && item.ItemData.m_shared.m_name == itemName)) { return item; } } } return null; } private bool HasEnoughCoins(Player player, int amount) { int num = 0; Inventory inventory = ((Humanoid)player).GetInventory(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_shared.m_name.ToLower() == "coins" || allItem.m_shared.m_name == "$item_coins") { num += allItem.m_stack; } } MerchantNPCsPlugin.Logger.LogInfo((object)$"Player has {num} coins, needs {amount}"); return num >= amount; } private void RemoveCoins(Player player, int amount) { int num = amount; Inventory inventory = ((Humanoid)player).GetInventory(); List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_shared.m_name.ToLower() == "coins" || allItem.m_shared.m_name == "$item_coins") { list.Add(allItem); } } foreach (ItemData item in list) { if (num <= 0) { break; } if (item.m_stack <= num) { num -= item.m_stack; inventory.RemoveItem(item); continue; } item.m_stack -= num; num = 0; break; } MerchantNPCsPlugin.Logger.LogInfo((object)$"Removed {amount} coins from player's inventory"); } private bool HasEnoughInventorySpace(Player player, ItemData itemData, int quantity) { if ((Object)(object)player == (Object)null || itemData == null || quantity <= 0) { MerchantNPCsPlugin.Logger.LogError((object)"Invalid parameters in HasEnoughInventorySpace"); return false; } if ((Object)(object)ZNetScene.instance == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"ZNetScene.instance is null"); return true; } if (itemData.m_shared == null) { MerchantNPCsPlugin.Logger.LogError((object)"itemData.m_shared is null"); return true; } string name = itemData.m_shared.m_name; if (string.IsNullOrEmpty(name)) { MerchantNPCsPlugin.Logger.LogError((object)"Item name is null or empty"); return true; } MerchantNPCsPlugin.Logger.LogInfo((object)("Checking inventory space for item: " + name)); GameObject val = null; try { val = ZNetScene.instance.GetPrefab(name); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when getting prefab by name: " + ex.Message)); } if ((Object)(object)val == (Object)null && (Object)(object)itemData.m_dropPrefab != (Object)null) { try { val = ZNetScene.instance.GetPrefab(((Object)itemData.m_dropPrefab).name); } catch (Exception ex2) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when getting prefab by dropPrefab name: " + ex2.Message)); } } if ((Object)(object)val == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { try { val = ObjectDB.instance.GetItemPrefab(name); } catch (Exception ex3) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when getting prefab from ObjectDB: " + ex3.Message)); } if ((Object)(object)val == (Object)null) { try { foreach (GameObject item in ObjectDB.instance.m_items) { if (!((Object)(object)item == (Object)null)) { ItemDrop component = item.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_name == name) { val = item; break; } } } } catch (Exception ex4) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when searching ObjectDB items: " + ex4.Message)); } } } if ((Object)(object)val == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)("Could not find prefab for " + name + " - assuming inventory has space")); return true; } try { bool flag = ((Humanoid)player).GetInventory().CanAddItem(val, quantity); MerchantNPCsPlugin.Logger.LogInfo((object)$"Can player add {quantity}x {name}? {flag}"); return flag; } catch (Exception ex5) { MerchantNPCsPlugin.Logger.LogError((object)("Exception when checking CanAddItem: " + ex5.Message)); return true; } } } public class MerchantUI : MonoBehaviour { private static MerchantUI _instance; private bool _uiCreated = false; private bool _needsRecreation = false; private GameObject _uiPanel; private Text _merchantNameText; private InputField _buySearchInput; private InputField _sellSearchInput; private RectTransform _buyItemsContainer; private RectTransform _sellItemsContainer; private Button _buyButton; private Button _sellButton; private Button _closeButton; private Button _quantity1Button; private Button _quantity5Button; private Button _quantity10Button; private Text _quantityText; private Player _player; private string _merchantType; private MerchantInventory _merchantInventory; private MerchantItem _selectedBuyItem; private ItemData _selectedSellItem; private int _currentQuantity = 1; private string _buySearchFilter = ""; private string _sellSearchFilter = ""; private GameObject _itemButtonPrefab; public static MerchantUI Instance => _instance; public static void Initialize() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("MerchantUI"); Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent<MerchantUI>(); MerchantNPCsPlugin.Logger.LogInfo((object)"MerchantUI instance created - UI will be created on demand"); SceneManager.sceneLoaded += OnSceneLoaded; } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if ((Object)(object)_instance != (Object)null) { MerchantNPCsPlugin.Logger.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name + ", marking UI for recreation")); _instance._needsRecreation = true; _instance._uiCreated = false; } } private void OnDestroy() { MerchantNPCsPlugin.Logger.LogInfo((object)"MerchantUI OnDestroy called"); SceneManager.sceneLoaded -= OnSceneLoaded; CleanupUIElements(); } private void CleanupUIElements() { MerchantNPCsPlugin.Logger.LogInfo((object)"Cleaning up UI elements"); if ((Object)(object)_uiPanel != (Object)null) { Object.Destroy((Object)(object)_uiPanel); _uiPanel = null; } _merchantNameText = null; _buySearchInput = null; _sellSearchInput = null; _buyItemsContainer = null; _sellItemsContainer = null; _buyButton = null; _sellButton = null; _closeButton = null; _quantity1Button = null; _quantity5Button = null; _quantity10Button = null; _quantityText = null; if ((Object)(object)_itemButtonPrefab != (Object)null) { Object.Destroy((Object)(object)_itemButtonPrefab); _itemButtonPrefab = null; } _uiCreated = false; } private void CreateUI() { //IL_0d5c: Unknown result type (might be due to invalid IL or missing references) //IL_0d63: Expected O, but got Unknown //IL_15da: Unknown result type (might be due to invalid IL or missing references) //IL_15e1: Expected O, but got Unknown //IL_0540: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_055e: Unknown result type (might be due to invalid IL or missing references) //IL_0574: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Unknown result type (might be due to invalid IL or missing references) //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_0676: Unknown result type (might be due to invalid IL or missing references) //IL_07e7: Unknown result type (might be due to invalid IL or missing references) //IL_07ee: Expected O, but got Unknown //IL_081c: Unknown result type (might be due to invalid IL or missing references) //IL_0833: Unknown result type (might be due to invalid IL or missing references) //IL_0840: Unknown result type (might be due to invalid IL or missing references) //IL_084d: Unknown result type (might be due to invalid IL or missing references) //IL_0864: Unknown result type (might be due to invalid IL or missing references) //IL_0870: Unknown result type (might be due to invalid IL or missing references) //IL_08b7: Unknown result type (might be due to invalid IL or missing references) //IL_08be: Expected O, but got Unknown //IL_08e8: Unknown result type (might be due to invalid IL or missing references) //IL_08ff: Unknown result type (might be due to invalid IL or missing references) //IL_0916: Unknown result type (might be due to invalid IL or missing references) //IL_092d: Unknown result type (might be due to invalid IL or missing references) //IL_0957: Unknown result type (might be due to invalid IL or missing references) //IL_0987: Unknown result type (might be due to invalid IL or missing references) //IL_098e: Expected O, but got Unknown //IL_09b8: Unknown result type (might be due to invalid IL or missing references) //IL_09cf: Unknown result type (might be due to invalid IL or missing references) //IL_09dc: Unknown result type (might be due to invalid IL or missing references) //IL_09e9: Unknown result type (might be due to invalid IL or missing references) //IL_0a41: Unknown result type (might be due to invalid IL or missing references) //IL_0a48: Expected O, but got Unknown //IL_0a72: Unknown result type (might be due to invalid IL or missing references) //IL_0a89: Unknown result type (might be due to invalid IL or missing references) //IL_0a96: Unknown result type (might be due to invalid IL or missing references) //IL_0aa3: Unknown result type (might be due to invalid IL or missing references) //IL_0acb: Unknown result type (might be due to invalid IL or missing references) //IL_0b08: Unknown result type (might be due to invalid IL or missing references) //IL_0b0f: Expected O, but got Unknown //IL_0b41: Unknown result type (might be due to invalid IL or missing references) //IL_0b5c: Unknown result type (might be due to invalid IL or missing references) //IL_0b77: Unknown result type (might be due to invalid IL or missing references) //IL_0b92: Unknown result type (might be due to invalid IL or missing references) //IL_0bad: Unknown result type (might be due to invalid IL or missing references) //IL_0bd8: Unknown result type (might be due to invalid IL or missing references) //IL_0be2: Expected O, but got Unknown //IL_0c64: Unknown result type (might be due to invalid IL or missing references) //IL_0c77: Unknown result type (might be due to invalid IL or missing references) //IL_0c8a: Unknown result type (might be due to invalid IL or missing references) //IL_0c9d: Unknown result type (might be due to invalid IL or missing references) //IL_0cbf: Unknown result type (might be due to invalid IL or missing references) //IL_0ccb: Unknown result type (might be due to invalid IL or missing references) //IL_0ed6: Unknown result type (might be due to invalid IL or missing references) //IL_0ee5: Unknown result type (might be due to invalid IL or missing references) //IL_0ef4: Unknown result type (might be due to invalid IL or missing references) //IL_1065: Unknown result type (might be due to invalid IL or missing references) //IL_106c: Expected O, but got Unknown //IL_109a: Unknown result type (might be due to invalid IL or missing references) //IL_10b1: Unknown result type (might be due to invalid IL or missing references) //IL_10be: Unknown result type (might be due to invalid IL or missing references) //IL_10cb: Unknown result type (might be due to invalid IL or missing references) //IL_10e2: Unknown result type (might be due to invalid IL or missing references) //IL_10ee: Unknown result type (might be due to invalid IL or missing references) //IL_1135: Unknown result type (might be due to invalid IL or missing references) //IL_113c: Expected O, but got Unknown //IL_1166: Unknown result type (might be due to invalid IL or missing references) //IL_117d: Unknown result type (might be due to invalid IL or missing references) //IL_1194: Unknown result type (might be due to invalid IL or missing references) //IL_11ab: Unknown result type (might be due to invalid IL or missing references) //IL_11d5: Unknown result type (might be due to invalid IL or missing references) //IL_1205: Unknown result type (might be due to invalid IL or missing references) //IL_120c: Expected O, but got Unknown //IL_1236: Unknown result type (might be due to invalid IL or missing references) //IL_124d: Unknown result type (might be due to invalid IL or missing references) //IL_125a: Unknown result type (might be due to invalid IL or missing references) //IL_1267: Unknown result type (might be due to invalid IL or missing references) //IL_12bf: Unknown result type (might be due to invalid IL or missing references) //IL_12c6: Expected O, but got Unknown //IL_12f0: Unknown result type (might be due to invalid IL or missing references) //IL_1307: Unknown result type (might be due to invalid IL or missing references) //IL_1314: Unknown result type (might be due to invalid IL or missing references) //IL_1321: Unknown result type (might be due to invalid IL or missing references) //IL_1349: Unknown result type (might be due to invalid IL or missing references) //IL_1386: Unknown result type (might be due to invalid IL or missing references) //IL_138d: Expected O, but got Unknown //IL_13bf: Unknown result type (might be due to invalid IL or missing references) //IL_13da: Unknown result type (might be due to invalid IL or missing references) //IL_13f5: Unknown result type (might be due to invalid IL or missing references) //IL_1410: Unknown result type (might be due to invalid IL or missing references) //IL_142b: Unknown result type (might be due to invalid IL or missing references) //IL_1456: Unknown result type (might be due to invalid IL or missing references) //IL_1460: Expected O, but got Unknown //IL_14e2: Unknown result type (might be due to invalid IL or missing references) //IL_14f5: Unknown result type (might be due to invalid IL or missing references) //IL_1508: Unknown result type (might be due to invalid IL or missing references) //IL_151b: Unknown result type (might be due to invalid IL or missing references) //IL_153d: Unknown result type (might be due to invalid IL or missing references) //IL_1549: Unknown result type (might be due to invalid IL or missing references) //IL_162a: Unknown result type (might be due to invalid IL or missing references) //IL_1639: Unknown result type (might be due to invalid IL or missing references) //IL_1648: Unknown result type (might be due to invalid IL or missing references) //IL_1659: Unknown result type (might be due to invalid IL or missing references) //IL_165f: Unknown result type (might be due to invalid IL or missing references) //IL_16ad: Unknown result type (might be due to invalid IL or missing references) //IL_16bc: Unknown result type (might be due to invalid IL or missing references) //IL_16cb: Unknown result type (might be due to invalid IL or missing references) //IL_16fe: Unknown result type (might be due to invalid IL or missing references) //IL_1708: Expected O, but got Unknown //IL_1728: Unknown result type (might be due to invalid IL or missing references) //IL_1737: Unknown result type (might be due to invalid IL or missing references) //IL_1746: Unknown result type (might be due to invalid IL or missing references) //IL_1779: Unknown result type (might be due to invalid IL or missing references) //IL_1783: Expected O, but got Unknown //IL_17a3: Unknown result type (might be due to invalid IL or missing references) //IL_17b2: Unknown result type (might be due to invalid IL or missing references) //IL_17c1: Unknown result type (might be due to invalid IL or missing references) //IL_17f6: Unknown result type (might be due to invalid IL or missing references) //IL_1800: Expected O, but got Unknown //IL_1820: Unknown result type (might be due to invalid IL or missing references) //IL_182f: Unknown result type (might be due to invalid IL or missing references) //IL_183e: Unknown result type (might be due to invalid IL or missing references) //IL_1873: Unknown result type (might be due to invalid IL or missing references) //IL_187d: Expected O, but got Unknown //IL_189d: Unknown result type (might be due to invalid IL or missing references) //IL_18ac: Unknown result type (might be due to invalid IL or missing references) //IL_18bb: Unknown result type (might be due to invalid IL or missing references) //IL_18f0: Unknown result type (might be due to invalid IL or missing references) //IL_18fa: Expected O, but got Unknown //IL_191a: Unknown result type (might be due to invalid IL or missing references) //IL_1929: Unknown result type (might be due to invalid IL or missing references) //IL_1938: Unknown result type (might be due to invalid IL or missing references) //IL_196d: Unknown result type (might be due to invalid IL or missing references) //IL_1977: Expected O, but got Unknown //IL_0dbe: Unknown result type (might be due to invalid IL or missing references) //IL_0dcd: Unknown result type (might be due to invalid IL or missing references) //IL_0ddc: Unknown result type (might be due to invalid IL or missing references) //IL_0df2: Unknown result type (might be due to invalid IL or missing references) //IL_0df8: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) try { MerchantNPCsPlugin.Logger.LogInfo((object)"CreateUI method called"); int num = 0; while (GUIManager.Instance == null && num < 5) { MerchantNPCsPlugin.Logger.LogWarning((object)$"GUIManager.Instance is null. Waiting for it to be available (attempt {num + 1}/5)..."); Thread.Sleep(500); num++; } if (GUIManager.Instance == null) { MerchantNPCsPlugin.Logger.LogError((object)"GUIManager.Instance is still null after waiting. UI creation failed."); return; } MerchantNPCsPlugin.Logger.LogInfo((object)"GUIManager.Instance is available"); num = 0; while ((Object)(object)GUIManager.CustomGUIFront == (Object)null && num < 5) { MerchantNPCsPlugin.Logger.LogWarning((object)$"GUIManager.CustomGUIFront is null. Waiting for it to be available (attempt {num + 1}/5)..."); Thread.Sleep(500); num++; } if ((Object)(object)GUIManager.CustomGUIFront == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"GUIManager.CustomGUIFront is still null after waiting. UI creation failed."); return; } MerchantNPCsPlugin.Logger.LogInfo((object)"GUIManager.CustomGUIFront is available"); MerchantNPCsPlugin.Logger.LogInfo((object)"Creating main UI panel..."); MerchantNPCsPlugin.Logger.LogInfo((object)"Creating UI panel with GUIManager.Instance.CreateWoodpanel..."); try { _uiPanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-400f, 0f), 800f, 600f, true); if ((Object)(object)_uiPanel == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"CreateWoodpanel returned null"); return; } MerchantNPCsPlugin.Logger.LogInfo((object)"UI panel created successfully"); ((Object)_uiPanel).name = "MerchantUI_Panel"; if (string.IsNullOrEmpty(_merchantType)) { ShowMerchantMessage("Welcome to my shop!"); } else { ShowMerchantMessage("Welcome to " + _merchantType + "'s shop!"); } Canvas component = _uiPanel.GetComponent<Canvas>(); if ((Object)(object)component != (Object)null) { component.sortingOrder = 100; MerchantNPCsPlugin.Logger.LogInfo((object)$"Set UI panel canvas sorting order to {component.sortingOrder}"); } else { MerchantNPCsPlugin.Logger.LogWarning((object)"Could not find Canvas component on UI panel"); } MerchantNPCsPlugin.Logger.LogInfo((object)"UI panel named 'MerchantUI_Panel'"); } catch (Exception ex) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating UI panel: " + ex.Message + "\n" + ex.StackTrace)); return; } ((Object)_uiPanel).name = "MerchantUIPanel"; _uiPanel.SetActive(false); MerchantNPCsPlugin.Logger.LogInfo((object)"Creating merchant name text..."); try { GUIManager instance = GUIManager.Instance; Transform transform = _uiPanel.transform; Vector2 val = new Vector2(0.5f, 1f); Vector2 val2 = new Vector2(0.5f, 1f); Vector2 val3 = new Vector2(0f, -40f); Color valheimOrange = GUIManager.Instance.ValheimOrange; Color black = Color.black; GameObject val4 = instance.CreateText("Merchant", transform, val, val2, val3, GUIManager.Instance.AveriaSerifBold, 25, valheimOrange, true, black, 300f, 40f, false); if ((Object)(object)val4 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"CreateText returned null for merchant name text"); return; } _merchantNameText = val4.GetComponent<Text>(); if ((Object)(object)_merchantNameText == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to get Text component from merchant name object"); return; } _merchantNameText.alignment = (TextAnchor)4; ((Object)_merchantNameText).name = "MerchantUI_MerchantNameText"; MerchantNPCsPlugin.Logger.LogInfo((object)"Merchant name text created successfully"); } catch (Exception ex2) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating merchant name text: " + ex2.Message + "\n" + ex2.StackTrace)); return; } try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating prices info text..."); GUIManager instance2 = GUIManager.Instance; Transform transform2 = _uiPanel.transform; Vector2 val5 = new Vector2(0.5f, 1f); Vector2 val6 = new Vector2(0.5f, 1f); Vector2 val7 = new Vector2(0f, -70f); Color black = Color.yellow; Color valheimOrange = Color.black; GameObject val8 = instance2.CreateText("All prices in coins", transform2, val5, val6, val7, GUIManager.Instance.AveriaSerif, 16, black, true, valheimOrange, 300f, 30f, false); if ((Object)(object)val8 != (Object)null) { Text component2 = val8.GetComponent<Text>(); if ((Object)(object)component2 != (Object)null) { component2.alignment = (TextAnchor)4; ((Object)component2).name = "MerchantUI_PricesInfoText"; MerchantNPCsPlugin.Logger.LogInfo((object)"Prices info text created successfully"); } } } catch (Exception ex3) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating prices info text: " + ex3.Message + "\n" + ex3.StackTrace)); } try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating buy section title..."); GameObject val9 = GUIManager.Instance.CreateText("Buy", _uiPanel.transform, new Vector2(0f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -90f), GUIManager.Instance.AveriaSerif, 20, GUIManager.Instance.ValheimYellow, true, Color.black, 380f, 30f, false); if ((Object)(object)val9 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to create buy title object"); } else { Text component3 = val9.GetComponent<Text>(); if ((Object)(object)component3 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to get Text component from buy title object"); } else { component3.alignment = (TextAnchor)4; MerchantNPCsPlugin.Logger.LogInfo((object)"Buy section title created successfully"); } } } catch (Exception ex4) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating buy section title: " + ex4.Message + "\n" + ex4.StackTrace)); } try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating buy search input..."); GameObject val10 = GUIManager.Instance.CreateInputField(_uiPanel.transform, new Vector2(0f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -120f), (ContentType)0, (string)null, 16, 380f, 30f); if ((Object)(object)val10 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to create buy search input object"); } else { _buySearchInput = val10.GetComponent<InputField>(); if ((Object)(object)_buySearchInput == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to get InputField component from buy search object"); } else { if ((Object)(object)_buySearchInput.placeholder == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Buy search input placeholder is null"); } else { Text component4 = ((Component)_buySearchInput.placeholder).GetComponent<Text>(); if ((Object)(object)component4 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to get Text component from buy search placeholder"); } else { component4.text = "Search..."; } } ((UnityEvent<string>)(object)_buySearchInput.onValueChanged).AddListener((UnityAction<string>)OnBuySearchChanged); MerchantNPCsPlugin.Logger.LogInfo((object)"Buy search input created successfully"); } } } catch (Exception ex5) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating buy search input: " + ex5.Message + "\n" + ex5.StackTrace)); } try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating buy items container with scroll view..."); GameObject val11 = new GameObject("BuyContainer", new Type[1] { typeof(RectTransform) }); val11.transform.SetParent(_uiPanel.transform, false); RectTransform component5 = val11.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0f, 0.25f); component5.anchorMax = new Vector2(0.5f, 0.75f); component5.anchoredPosition = Vector2.zero; component5.sizeDelta = Vector2.zero; MerchantNPCsPlugin.Logger.LogInfo((object)$"Buy container rect: anchorMin={component5.anchorMin}, anchorMax={component5.anchorMax}"); GameObject val12 = new GameObject("BuyItemsPanel", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val12.transform.SetParent(val11.transform, false); RectTransform component6 = val12.GetComponent<RectTransform>(); component6.anchorMin = new Vector2(0f, 0f); component6.anchorMax = new Vector2(1f, 1f); component6.offsetMin = new Vector2(10f, 10f); component6.offsetMax = new Vector2(-10f, -10f); Image component7 = val12.GetComponent<Image>(); ((Graphic)component7).color = new Color(0.1f, 0.1f, 0.1f, 0.3f); GameObject val13 = new GameObject("BuyScroll", new Type[2] { typeof(RectTransform), typeof(ScrollRect) }); val13.transform.SetParent(val12.transform, false); RectTransform component8 = val13.GetComponent<RectTransform>(); component8.anchorMin = new Vector2(0f, 0f); component8.anchorMax = new Vector2(1f, 1f); component8.offsetMin = Vector2.zero; component8.offsetMax = Vector2.zero; ScrollRect component9 = val13.GetComponent<ScrollRect>(); component9.horizontal = false; component9.vertical = true; GameObject val14 = new GameObject("Viewport", new Type[3] { typeof(RectTransform), typeof(Mask), typeof(Image) }); val14.transform.SetParent(val13.transform, false); RectTransform component10 = val14.GetComponent<RectTransform>(); component10.anchorMin = new Vector2(0f, 0f); component10.anchorMax = new Vector2(1f, 1f); component10.offsetMin = Vector2.zero; component10.offsetMax = Vector2.zero; Mask component11 = val14.GetComponent<Mask>(); component11.showMaskGraphic = false; Image component12 = val14.GetComponent<Image>(); ((Graphic)component12).color = Color.white; GameObject val15 = new GameObject("Content", new Type[3] { typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter) }); val15.transform.SetParent(val14.transform, false); _buyItemsContainer = val15.GetComponent<RectTransform>(); _buyItemsContainer.anchorMin = new Vector2(0f, 1f); _buyItemsContainer.anchorMax = new Vector2(1f, 1f); _buyItemsContainer.pivot = new Vector2(0.5f, 1f); _buyItemsContainer.anchoredPosition = new Vector2(0f, -50f); _buyItemsContainer.sizeDelta = new Vector2(0f, 0f); VerticalLayoutGroup component13 = val15.GetComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component13).spacing = 10f; ((LayoutGroup)component13).padding = new RectOffset(10, 10, 10, 10); ((LayoutGroup)component13).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)component13).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component13).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)component13).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)component13).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component13).reverseArrangement = false; ContentSizeFitter component14 = val15.GetComponent<ContentSizeFitter>(); component14.horizontalFit = (FitMode)0; component14.verticalFit = (FitMode)2; component9.viewport = component10; component9.content = _buyItemsContainer; MerchantNPCsPlugin.Logger.LogInfo((object)$"Buy container position: anchorMin={_buyItemsContainer.anchorMin}, anchorMax={_buyItemsContainer.anchorMax}, pivot={_buyItemsContainer.pivot}, position={_buyItemsContainer.anchoredPosition}"); MerchantNPCsPlugin.Logger.LogInfo((object)$"Buy viewport position: anchorMin={component10.anchorMin}, anchorMax={component10.anchorMax}"); MerchantNPCsPlugin.Logger.LogInfo((object)"Buy items container created successfully"); } catch (Exception ex6) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating buy items container: " + ex6.Message + "\n" + ex6.StackTrace)); if ((Object)(object)_buyItemsContainer == (Object)null) { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating fallback buy items container"); GameObject val16 = new GameObject("BuyItemsContainer", new Type[1] { typeof(RectTransform) }); val16.transform.SetParent(_uiPanel.transform, false); _buyItemsContainer = val16.GetComponent<RectTransform>(); } } try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating sell section title..."); GameObject val17 = GUIManager.Instance.CreateText("Sell", _uiPanel.transform, new Vector2(0.5f, 1f), new Vector2(1f, 1f), new Vector2(0f, -90f), GUIManager.Instance.AveriaSerif, 20, GUIManager.Instance.ValheimYellow, true, Color.black, 380f, 30f, false); if ((Object)(object)val17 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to create sell title object"); } else { Text component15 = val17.GetComponent<Text>(); if ((Object)(object)component15 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to get Text component from sell title object"); } else { component15.alignment = (TextAnchor)4; MerchantNPCsPlugin.Logger.LogInfo((object)"Sell section title created successfully"); } } } catch (Exception ex7) { MerchantNPCsPlugin.Logger.LogError((object)("Error creating sell section title: " + ex7.Message + "\n" + ex7.StackTrace)); } try { MerchantNPCsPlugin.Logger.LogInfo((object)"Creating sell search input..."); GameObject val18 = GUIManager.Instance.CreateInputField(_uiPanel.transform, new Vector2(0.5f, 1f), new Vector2(1f, 1f), new Vector2(0f, -120f), (ContentType)0, (string)null, 16, 380f, 30f); if ((Object)(object)val18 == (Object)null) { MerchantNPCsPlugin.Logger.LogError((object)"Failed to create sell search input object"); } else {