public static void SpawnChest(Point pos, Point[] items, string name = "", int type = 21) { int x = pos.X; int y = pos.Y; WorldGen.PlaceChest(x, y, (ushort)type); int index = Chest.FindEmptyChest(x, y); Chest chest = Main.chest[index - 1]; chest.name = name; for (int i = 0; i < items.Length; i++) { chest.item[i].SetDefaults(items[i].X, false); chest.item[i].stack = items[i].Y; } }
private void ItemShop(CommandArgs args) { var parameters = args.Parameters; var player = args.Player; var playerGroupConfig = Config.Instance.GetGroupConfig(player.Group.Name); var subcommand = parameters.Count > 0 ? parameters[0] : ""; if (subcommand.Equals("1", StringComparison.OrdinalIgnoreCase)) { player.AwaitingTempPoint = 1; player.SendInfoMessage("Hit a block to set the first point."); } else if (subcommand.Equals("2", StringComparison.OrdinalIgnoreCase)) { player.AwaitingTempPoint = 2; player.SendInfoMessage("Hit a block to set the second point."); } else if (subcommand.Equals("buy", StringComparison.OrdinalIgnoreCase)) { if (parameters.Count != 2 && parameters.Count != 3) { player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop buy <item-index> [amount]"); return; } var session = GetOrCreateSession(player); if (session.CurrentlyViewedShop == null) { player.SendErrorMessage("You aren't currently viewing a shop."); return; } var shop = session.CurrentlyViewedShop; var inputItemIndex = parameters[1]; if (!int.TryParse(inputItemIndex, out var itemIndex) || itemIndex < 1 || itemIndex > Chest.maxItems) { player.SendErrorMessage($"Invalid item index '{inputItemIndex}'."); return; } var shopItem = shop.Items.FirstOrDefault(i => i.Index == itemIndex - 1 && i.StackSize > 0); if (shopItem == null) { player.SendErrorMessage($"Invalid item index '{inputItemIndex}'."); return; } var inputAmount = parameters.Count == 3 ? parameters[2] : "1"; if (!int.TryParse(inputAmount, out var amount) || amount < 1 || amount > shopItem.StackSize) { player.SendErrorMessage($"Invalid amount '{inputAmount}'."); return; } var item = new Item(); var itemId = shopItem.ItemId; item.SetDefaults(itemId); //var unitPrice = shop.UnitPrices.Get(itemId, item.value / 5); var unitPriceInfo = shop.UnitPrices[itemId]; if (!unitPriceInfo.IsValid) { player.SendErrorMessage("Unfortunately, this item is priced incorrectly. Please contact the shop owner."); return; } var currencyConverter = unitPriceInfo.Currency.GetCurrencyConverter(); //var purchaseCost = (amount * shop.UnitPrices.Get(itemId, item.value / 5)); var purchaseCost = amount * unitPriceInfo.Value; var salesTax = Math.Round(purchaseCost * (decimal)playerGroupConfig.SalesTaxRate); var purchaseCostString = currencyConverter.ToString(purchaseCost); var salesTaxString = currencyConverter.ToString(salesTax); var itemText = $"[i/s{amount},p{shopItem.PrefixId}:{shopItem.ItemId}]"; player.SendInfoMessage( $"Purchasing {itemText} will cost [c/{Color.OrangeRed.Hex3()}:{purchaseCostString}], " + $"with a sales tax of [c/{Color.OrangeRed.Hex3()}:{salesTaxString}]."); player.SendInfoMessage("Do you wish to proceed? Use /yes or /no."); player.AddResponse("yes", args2 => { player.AwaitingResponse.Remove("no"); var account = BankingPlugin.Instance.GetBankAccount(player.Name, unitPriceInfo.Currency.InternalName); if (account == null || account.Balance < purchaseCost + salesTax) { player.SendErrorMessage($"You do not have enough of a balance to purchase {itemText}."); shop.TryShowStock(player, MessageRefreshDelay); return; } if (shopItem.StackSize < amount || shopItem.ItemId != itemId || shop.IsBeingChanged) { player.SendErrorMessage("While waiting, the shop changed."); //shop.TryShowStock(player, MessageRefreshDelay * 2);//if the shop is changing, lets not spam anyones display while it is return; } if (purchaseCost > 0) { var account2 = BankingPlugin.Instance.GetBankAccount(shop.OwnerName, unitPriceInfo.Currency.InternalName); account.TryTransferTo(account2, purchaseCost); } if (salesTax > 0) { account.TryTransferTo(BankingPlugin.Instance.GetWorldAccount(), salesTax); } shopItem.StackSize -= amount; database.Update(shop); var totalCost = purchaseCost + salesTax; var totalCostString = currencyConverter.ToString(totalCost); player.GiveItem( itemId, "", Player.defaultWidth, Player.defaultHeight, amount, shopItem.PrefixId); player.SendSuccessMessage($"Purchased {itemText} for " + $"[c/{Color.OrangeRed.Hex3()}:{totalCostString}]."); var player2 = TShock.Players.Where(p => p?.Active == true) .FirstOrDefault(p => p.User?.Name == shop.OwnerName); player2?.SendInfoMessage($"{player.Name} purchased {itemText} for " + $"[c/{Color.OrangeRed.Hex3()}:{totalCostString}]."); shop.TryShowStock(player, MessageRefreshDelay); }); player.AddResponse("no", args2 => { player.AwaitingResponse.Remove("yes"); player.SendInfoMessage("Canceled purchase."); shop.TryShowStock(player, MessageRefreshDelay); }); } else if (subcommand.Equals("close", StringComparison.OrdinalIgnoreCase)) { var session = GetOrCreateSession(player); if (session.CurrentShop == null) { player.SendErrorMessage("You aren't currently in a shop."); return; } var shop = session.CurrentShop; if (shop.OwnerName != player.User?.Name && !player.HasPermission("housing.itemshop.admin")) { player.SendErrorMessage( $"You can't close {shop.OwnerName}'s shop [c/{Color.LimeGreen.Hex3()}:{shop}]."); return; } shop.IsOpen = false; database.Update(shop); player.SendSuccessMessage( $"Closed {(shop.OwnerName == player.User?.Name ? "your shop" : shop.OwnerName + "'s shop")} " + $"[c/{Color.LimeGreen.Hex3()}:{shop}]."); } else if (subcommand.Equals("info", StringComparison.OrdinalIgnoreCase)) { var session = GetOrCreateSession(player); if (session.CurrentShop == null) { player.SendErrorMessage("You aren't currently in a shop."); return; } var shop = session.CurrentShop; player.SendInfoMessage($"Owner: {shop.OwnerName}, Name: {shop.Name}"); var prices = shop.UnitPrices.Where(kvp => kvp.Value.IsValid && kvp.Value.Value > 0) .Select(kvp => $"[i:{kvp.Key}]: {Color.OrangeRed.ColorText(kvp.Value.Price)}"); player.SendInfoMessage( $"Prices: {string.Join(", ", prices)}. All other items are default sell prices."); if (shop.OwnerName == player.User?.Name) { //var ownerConfig = shop.GetGroupConfig(); var house = session.CurrentHouse; var taxRate = playerGroupConfig.StoreTaxRate - playerGroupConfig.TaxRate; var taxCost = (decimal)Math.Round(house.Area * taxRate); player.SendInfoMessage($"Extra tax on house: {Color.OrangeRed.ColorText(taxCost.ToMoneyString())}"); } } else if (subcommand.Equals("open", StringComparison.OrdinalIgnoreCase)) { var session = GetOrCreateSession(player); if (session.CurrentShop == null) { player.SendErrorMessage("You aren't currently in a shop."); return; } var shop = session.CurrentShop; if (shop.OwnerName != player.User?.Name && !player.HasPermission("housing.itemshop.admin")) { player.SendErrorMessage( $"You can't open {shop.OwnerName}'s shop {Color.LimeGreen.ColorText(shop)}."); return; } shop.IsOpen = true; database.Update(shop); player.SendSuccessMessage( $"Opened {(shop.OwnerName == player.User?.Name ? "your shop" : shop.OwnerName + "'s shop")} " + $"{Color.LimeGreen.ColorText(shop)}."); } else if (subcommand.Equals("remove", StringComparison.OrdinalIgnoreCase)) { var session = GetOrCreateSession(player); if (session.CurrentShop == null) { player.SendErrorMessage("You aren't currently in a shop."); return; } var shop = session.CurrentShop; if (shop.OwnerName != player.User?.Name && !player.HasPermission("housing.itemshop.admin")) { player.SendErrorMessage( $"You can't remove {shop.OwnerName}'s shop {Color.LimeGreen.ColorText(shop)}."); return; } // Revert the chest to a normal chest. var chestId = Chest.FindEmptyChest(shop.ChestX, shop.ChestY); if (chestId >= 0) { var chest = new Chest(); for (var i = 0; i < Chest.maxItems; ++i) { var shopItem = shop.Items.FirstOrDefault(si => si.Index == i); var item = new Item(); item.SetDefaults(shopItem?.ItemId ?? 0); item.stack = shopItem?.StackSize ?? 0; item.prefix = shopItem?.PrefixId ?? 0; chest.item[i] = item; } Main.chest[chestId] = chest; } database.Remove(shop); player.SendSuccessMessage( $"Removed {(shop.OwnerName == player.User?.Name ? "your shop" : shop.OwnerName + "'s shop")} " + $"{Color.LimeGreen.ColorText(shop)}."); } else if (subcommand.Equals("set", StringComparison.OrdinalIgnoreCase)) { if (parameters.Count != 2) { player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop set <shop-name>"); return; } if (player.TempPoints.Any(p => p == Point.Zero)) { player.SendErrorMessage("Not all points have been set."); return; } var session = GetOrCreateSession(player); if (session.CurrentHouse == null || session.CurrentHouse.OwnerName != player.User?.Name) { player.SendErrorMessage("You aren't currently in a house that you own."); return; } //var playerGroupConfig = Config.Instance.GetGroupConfig(player.Group.Name); var point1 = player.TempPoints[0]; var point2 = player.TempPoints[1]; var inputShopName = parameters[1]; var x = Math.Min(point1.X, point2.X); var y = Math.Min(point1.Y, point2.Y); var x2 = Math.Max(point1.X, point2.X); var y2 = Math.Max(point1.Y, point2.Y); var area = (x2 - x + 1) * (y2 - y + 1); if (area < playerGroupConfig.MinShopSize) { player.SendErrorMessage($"Your shop is too small. Minimum area is {playerGroupConfig.MinShopSize}."); return; } if (area > playerGroupConfig.MaxShopSize) { player.SendErrorMessage($"Your shop is too large.Maximum area is {playerGroupConfig.MaxShopSize}."); return; } var rectangle = new Rectangle(x, y, x2 - x + 1, y2 - y + 1); if (!session.CurrentHouse.Rectangle.Contains(rectangle)) { player.SendErrorMessage("Your shop must lie entirely within your house."); return; } session.NextShopHouse = session.CurrentHouse; session.NextShopName = inputShopName; session.NextShopX = x; session.NextShopY = y; session.NextShopX2 = x2; session.NextShopY2 = y2; player.SendInfoMessage("Place a chest to serve as the item shop chest."); } else if (subcommand.Equals("setmsg", StringComparison.OrdinalIgnoreCase)) { if (parameters.Count < 2) { player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop setmsg <message>"); return; } var session = GetOrCreateSession(player); if (session.CurrentShop == null) { player.SendErrorMessage("You aren't currently in a shop."); return; } var shop = session.CurrentShop; if (shop.OwnerName != player.User?.Name && !player.HasPermission("housing.itemshop.admin")) { player.SendErrorMessage( $"You can't set the message for {shop.OwnerName}'s {Color.LimeGreen.ColorText(shop)} shop."); return; } var message = string.Join(" ", parameters.Skip(1)); shop.Message = message; database.Update(shop); player.SendSuccessMessage( $"Updated {(shop.OwnerName == player.User?.Name ? "your" : shop.OwnerName + "'s")} " + $"{Color.LimeGreen.ColorText(shop)} shop message."); } else if (subcommand.Equals("setprice", StringComparison.OrdinalIgnoreCase)) { if (parameters.Count != 3) { player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop setprice <item-name> <price>"); return; } var session = GetOrCreateSession(player); if (session.CurrentShop == null) { player.SendErrorMessage("You aren't currently in a shop."); return; } var shop = session.CurrentShop; if (shop.OwnerName != player.User?.Name && !player.HasPermission("housing.itemshop.admin")) { player.SendErrorMessage( $"You can't modify {shop.OwnerName}'s {Color.LimeGreen.ColorText(shop)} shop."); return; } var inputItemName = parameters[1]; var items = TShock.Utils.GetItemByIdOrName(inputItemName); if (items.Count > 1) { player.SendErrorMessage($"Multiple items matched '{inputItemName}':"); TShock.Utils.SendMultipleMatchError(player, items); return; } if (items.Count == 0) { player.SendErrorMessage($"Invalid item '{inputItemName}'."); return; } var inputPrice = parameters[2]; var priceInfo = new PriceInfo(inputPrice); var disable = false; if (inputPrice == "0" || inputPrice == "none") { disable = true; } //if(!BankingPlugin.Instance.Bank.CurrencyManager.TryFindCurrencyFromString(inputPrice, out var priceCurrency)) if (!priceInfo.IsValid && !disable) { player.SendErrorMessage($"Invalid price. '{inputPrice}' is not a valid currency format."); return; } if (priceInfo.Value <= 0m && !disable) { player.SendErrorMessage($"Invalid price '{inputPrice}'. Price cannot be less than 1."); return; } //we use CurrencyConverter.ToString() here to ensure the unit price uses the largest currency values possible. //shop.UnitPrices[items[0].type] = priceCurrency.GetCurrencyConverter().ToString(price); shop.UnitPrices[items[0].type] = priceInfo; database.Update(shop); if (disable) { player.SendSuccessMessage( $"Removed {inputItemName} from the {Color.LimeGreen.ColorText(shop)} item listing."); } else { player.SendSuccessMessage( $"Updated {(shop.OwnerName == player.User?.Name ? "your" : shop.OwnerName + "'s")} " + $"{Color.LimeGreen.ColorText(shop)} shop prices."); } } else { player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop 1/2"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop buy <item-index> [amount]"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop close"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop info"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop open"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop remove"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop set <shop-name>"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop setmsg <message>"); player.SendErrorMessage($"Syntax: {Commands.Specifier}itemshop setprice <item-name> <price> ( 0 or none disables listing. )"); } }