private void PerformTrade(TSPlayer player, ProtectionEntry protection, Inventory chestInventory, Item sellItem, Item payItem) { Inventory playerInventory = new Inventory(new PlayerItemsAdapter(player.Index, player.TPlayer.inventory, 0, 53), specificPrefixes: false); ItemData sellItemData = ItemData.FromItem(sellItem); ItemData payItemData = ItemData.FromItem(payItem); ItemData?[] playerInvUpdates; try { playerInvUpdates = playerInventory.Remove(payItemData); playerInventory.Add(playerInvUpdates, sellItemData); } catch (InvalidOperationException) { player.SendErrorMessage($"You either don't have the needed {TShock.Utils.ItemTag(payItem)} to purchase {TShock.Utils.ItemTag(sellItem)} or your inventory is full."); return; } bool isRefillChest = (protection.RefillChestData != null); ItemData?[] chestInvUpdates; try { if (isRefillChest) { chestInvUpdates = chestInventory.Add(payItemData); } else { chestInvUpdates = chestInventory.Remove(sellItemData); chestInventory.Add(chestInvUpdates, payItemData); } } catch (InvalidOperationException) { player.SendErrorMessage("The items in the trade chest are either sold out or there's no space in it to add your payment."); return; } try { protection.TradeChestData.AddOrUpdateLooter(player.User.ID); } catch (InvalidOperationException) { player.SendErrorMessage($"The vendor doesn't allow more than {protection.TradeChestData.LootLimitPerPlayer} purchases per player."); return; } playerInventory.ApplyUpdates(playerInvUpdates); chestInventory.ApplyUpdates(chestInvUpdates); protection.TradeChestData.AddJournalEntry(player.Name, sellItem, payItem); player.SendSuccessMessage($"You've just purchased {TShock.Utils.ItemTag(sellItem)} for {TShock.Utils.ItemTag(payItem)} from {TShock.Utils.ColorTag(GetUserName(protection.Owner), Color.Red)}."); }
private void InitTrade(TSPlayer player, IChest chest, ProtectionEntry protection) { TradeChestMetadata tradeChestData = protection.TradeChestData; Item sellItem = new Item(); sellItem.netDefaults(tradeChestData.ItemToSellId); sellItem.stack = tradeChestData.ItemToSellAmount; Item payItem = new Item(); payItem.netDefaults(tradeChestData.ItemToPayId); payItem.stack = tradeChestData.ItemToPayAmount; player.SendMessage($"This is a trade chest owned by {TShock.Utils.ColorTag(GetUserName(protection.Owner), Color.Red)}.", Color.LightGray); Inventory chestInventory = new Inventory(chest.Items, specificPrefixes: false); int stock = chestInventory.Amount(sellItem.netID); if (stock < sellItem.stack) { player.SendMessage($"It was trading {TShock.Utils.ItemTag(sellItem)} for {TShock.Utils.ItemTag(payItem)} but it is out of stock.", Color.LightGray); return; } player.SendMessage($"Click again to purchase {TShock.Utils.ItemTag(sellItem)} for {TShock.Utils.ItemTag(payItem)}", Color.LightGray); CommandInteraction interaction = this.StartOrResetCommandInteraction(player); interaction.ChestOpenCallback += (playerLocal, chestLocation) => { bool complete; bool wasThisChestHit = (chestLocation == chest.Location); if (wasThisChestHit) { // this is important to check, otherwise players could use trade chests to easily duplicate items if (!this.IsChestInUse(playerLocal, chest)) this.PerformTrade(player, protection, chestInventory, sellItem, payItem); else player.SendErrorMessage("Another player is currently viewing the content of this chest."); complete = false; } else { this.HandleChestGetContents(playerLocal, chestLocation, skipInteractions: true); complete = true; } playerLocal.SendTileSquare(chest.Location); return new CommandInteractionResult {IsHandled = true, IsInteractionCompleted = complete}; }; }