diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6f67cf7 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java b/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java index 17ec62a..8d5f7df 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java +++ b/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java @@ -1,10 +1,13 @@ package ca.tweetzy.auctionhouse; import ca.tweetzy.auctionhouse.commands.CommandAuctionHouse; +import ca.tweetzy.auctionhouse.commands.CommandSell; +import ca.tweetzy.auctionhouse.managers.AuctionItemManager; import ca.tweetzy.auctionhouse.settings.Settings; import ca.tweetzy.core.TweetyCore; import ca.tweetzy.core.TweetyPlugin; import ca.tweetzy.core.commands.CommandManager; + import ca.tweetzy.core.compatibility.ServerVersion; import ca.tweetzy.core.configuration.Config; import ca.tweetzy.core.core.PluginID; @@ -31,6 +34,7 @@ public class AuctionHouse extends TweetyPlugin { protected Metrics metrics; private CommandManager commandManager; + private AuctionItemManager auctionItemManager; @Override public void onPluginLoad() { @@ -61,9 +65,17 @@ public class AuctionHouse extends TweetyPlugin { setLocale(Settings.LANG.getString(), false); // commands + this.commandManager = new CommandManager(this); + this.commandManager.addCommand(new CommandAuctionHouse(this)).addSubCommands( + new CommandSell(this) + ); this.data.load(); + // load auction items + this.auctionItemManager = new AuctionItemManager(); + this.auctionItemManager.loadItems(); + // metrics if (Settings.METRICS.getBoolean()) { this.metrics = new Metrics(this, (int) PluginID.AUCTION_HOUSE.getbStatsID()); @@ -103,4 +115,8 @@ public class AuctionHouse extends TweetyPlugin { public CommandManager getCommandManager() { return commandManager; } + + public AuctionItemManager getAuctionItemManager() { + return auctionItemManager; + } } diff --git a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java index 03aaae8..edd9cf3 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java +++ b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItem.java @@ -3,6 +3,7 @@ package ca.tweetzy.auctionhouse.auction; import ca.tweetzy.auctionhouse.api.AuctionAPI; import ca.tweetzy.auctionhouse.settings.Settings; import ca.tweetzy.core.utils.PlayerUtils; +import ca.tweetzy.core.utils.TextUtils; import ca.tweetzy.core.utils.items.ItemUtils; import ca.tweetzy.core.utils.nms.NBTEditor; import lombok.Getter; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.UUID; +import java.util.stream.Collectors; /** * The current file has been created by Kiran Hart @@ -33,6 +35,7 @@ public class AuctionItem { private UUID highestBidder; private ItemStack originalItem; + private AuctionItemCategory category; private UUID key; private double basePrice; @@ -42,10 +45,11 @@ public class AuctionItem { private int remainingTime; - public AuctionItem(UUID owner, UUID highestBidder, ItemStack originalItem, UUID key, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, int remainingTime) { + public AuctionItem(UUID owner, UUID highestBidder, ItemStack originalItem, AuctionItemCategory category, UUID key, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, int remainingTime) { this.owner = owner; this.highestBidder = highestBidder; this.originalItem = originalItem; + this.category = category; this.key = key; this.basePrice = basePrice; this.bidStartPrice = bidStartPrice; @@ -54,10 +58,11 @@ public class AuctionItem { this.remainingTime = remainingTime; } - public AuctionItem(UUID owner, UUID highestBidder, ItemStack originalItem, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, int remainingTime) { + public AuctionItem(UUID owner, UUID highestBidder, ItemStack originalItem, AuctionItemCategory category, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, int remainingTime) { this.owner = owner; this.highestBidder = highestBidder; this.originalItem = originalItem; + this.category = category; this.key = UUID.randomUUID(); this.basePrice = basePrice; this.bidStartPrice = bidStartPrice; @@ -71,7 +76,7 @@ public class AuctionItem { } public String getDisplayName() { - String name = this.key.toString(); + String name; if (this.originalItem.hasItemMeta()) { name = (this.originalItem.getItemMeta().hasDisplayName()) ? this.originalItem.getItemMeta().getDisplayName() : StringUtils.capitalize(this.originalItem.getType().name().toLowerCase().replace("_", " ")); } else { @@ -89,15 +94,48 @@ public class AuctionItem { String theSeller = (this.owner == null) ? "&eSeller Name???" : Bukkit.getOfflinePlayer(this.owner).getName(); String highestBidder = (this.bidStartPrice <= 0) ? "" : (this.owner.equals(this.highestBidder)) ? Bukkit.getOfflinePlayer(this.owner).getName() : (Bukkit.getOfflinePlayer(this.highestBidder).isOnline()) ? Bukkit.getOfflinePlayer(this.highestBidder).getPlayer().getName() : "Offline"; String basePrice = Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.basePrice) : String.format("%,.2f", this.basePrice); - String bidStartPrice = Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.bidStartPrice) : String.format("%,.2f", this.bidStartPrice); - String bidIncPrice = (this.bidStartPrice <= 0) ? "" : Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.bidIncPrice) : String.format("%,.2f", this.bidIncPrice); - String currentPrice = (this.bidStartPrice <= 0) ? "" : Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.currentPrice) : String.format("%,.2f", this.currentPrice); + // String bidStartPrice = Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.bidStartPrice) : String.format("%,.2f", this.bidStartPrice); + String bidIncPrice = (this.bidStartPrice <= 0) ? "0" : Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.bidIncPrice) : String.format("%,.2f", this.bidIncPrice); + String currentPrice = (this.bidStartPrice <= 0) ? "0" : Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.currentPrice) : String.format("%,.2f", this.currentPrice); + double[] times = AuctionAPI.getInstance().getRemainingTimeValues(this.remainingTime); + if (type == AuctionStackType.MAIN_AUCTION_HOUSE) { + Settings.AUCTION_ITEM_AUCTION_STACK.getStringList().forEach(line -> { + lore.add(TextUtils.formatText(line + .replace("%seller%", theSeller) + .replace("%buynowprice%", basePrice) + .replace("%currentprice%", currentPrice) + .replace("%bidincrement%", bidIncPrice) + .replace("%highestbidder%", highestBidder) + .replace("%remaining_days%", String.valueOf(times[0])) + .replace("%remaining_hours%", String.valueOf(times[1])) + .replace("%remaining_minutes", String.valueOf(times[2])) + .replace("%remaining_seconds", String.valueOf(times[3])) + )); + }); + + lore.addAll(this.bidStartPrice <= 0 ? Settings.AUCTION_PURCHASE_CONTROLS_BID_OFF.getStringList().stream().map(TextUtils::formatText).collect(Collectors.toList()) : Settings.AUCTION_PURCHASE_CONTROLS_BID_ON.getStringList().stream().map(TextUtils::formatText).collect(Collectors.toList())); + } else { + Settings.AUCTION_ITEM_LISTING_STACK.getStringList().forEach(line -> { + lore.add(TextUtils.formatText(line + .replace("%seller%", theSeller) + .replace("%buynowprice%", basePrice) + .replace("%currentprice%", currentPrice) + .replace("%bidincrement%", bidIncPrice) + .replace("%highestbidder%", highestBidder) + .replace("%remaining_days%", String.valueOf(times[0])) + .replace("%remaining_hours%", String.valueOf(times[1])) + .replace("%remaining_minutes", String.valueOf(times[2])) + .replace("%remaining_seconds", String.valueOf(times[3])) + )); + }); + } meta.setLore(lore); itemStack.setItemMeta(meta); itemStack = NBTEditor.set(itemStack, getKey(), "AuctionItemKey"); + itemStack = NBTEditor.set(itemStack, this.bidStartPrice <= 0 ? "NOT_BID_ITEM" : "IS_BID_ITEM", "AuctionItemType"); return itemStack; } } diff --git a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItemCategory.java b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItemCategory.java new file mode 100644 index 0000000..11debc7 --- /dev/null +++ b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionItemCategory.java @@ -0,0 +1,27 @@ +package ca.tweetzy.auctionhouse.auction; + +/** + * The current file has been created by Kiran Hart + * Date Created: February 01 2021 + * Time Created: 6:52 p.m. + * Usage of any code found within this class is prohibited unless given explicit permission otherwise + */ +public enum AuctionItemCategory { + + FOOD("Food"), + ARMOR("Armor"), + BLOCKS("Blocks"), + TOOLS("Tools"), + MISC("Misc"); + + + private String type; + + AuctionItemCategory(String type) { + this.type = type; + } + + public String getType() { + return type; + } +} diff --git a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionPlayer.java b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionPlayer.java new file mode 100644 index 0000000..1f8a736 --- /dev/null +++ b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionPlayer.java @@ -0,0 +1,40 @@ +package ca.tweetzy.auctionhouse.auction; + +import ca.tweetzy.auctionhouse.AuctionHouse; +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * The current file has been created by Kiran Hart + * Date Created: February 02 2021 + * Time Created: 6:26 p.m. + * Usage of any code found within this class is prohibited unless given explicit permission otherwise + */ +public class AuctionPlayer { + + @Getter + private Player player; + + public AuctionPlayer(Player player) { + this.player = player; + } + + public List getActiveItems() { + return AuctionHouse.getInstance().getAuctionItemManager().getAuctionItems().stream().filter(item -> item.getOwner().equals(this.player.getUniqueId())).collect(Collectors.toList()); + } + + public int getSellLimit() { + if (player.hasPermission("auctionhouse.maxsell.*")) return Integer.MAX_VALUE; + for (int i = 1001; i > 0; i--) { + if (player.hasPermission("auctionhouse.maxsell." + i)) return i; + } + return 0; + } + + public boolean isAtSellLimit() { + return getSellLimit() - 1 < getActiveItems().size(); + } +} diff --git a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java index d7f1101..01b9aa6 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java +++ b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java @@ -2,15 +2,22 @@ package ca.tweetzy.auctionhouse.commands; import ca.tweetzy.auctionhouse.AuctionHouse; import ca.tweetzy.auctionhouse.auction.AuctionItem; +import ca.tweetzy.auctionhouse.auction.AuctionPlayer; +import ca.tweetzy.auctionhouse.helpers.MaterialCategorizer; import ca.tweetzy.auctionhouse.helpers.PlayerHelper; +import ca.tweetzy.auctionhouse.settings.Settings; import ca.tweetzy.core.commands.AbstractCommand; import ca.tweetzy.core.compatibility.XMaterial; +import ca.tweetzy.core.utils.NumberUtils; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.UUID; /** * The current file has been created by Kiran Hart @@ -29,14 +36,76 @@ public class CommandSell extends AbstractCommand { @Override protected ReturnType runCommand(CommandSender sender, String... args) { - if (args.length == 0) return ReturnType.SYNTAX_ERROR; + if (args.length <= 0) return ReturnType.SYNTAX_ERROR; Player player = (Player) sender; + AuctionPlayer auctionPlayer = new AuctionPlayer(player); - if (PlayerHelper.getHeldItem(player).getType() == XMaterial.AIR.parseMaterial()) { + ItemStack itemToSell = PlayerHelper.getHeldItem(player); + + if (itemToSell.getType() == XMaterial.AIR.parseMaterial()) { instance.getLocale().getMessage("general.air").sendPrefixedMessage(player); return ReturnType.FAILURE; } + // Check for block items + if (Settings.BLOCKED_ITEMS.getStringList().contains(itemToSell.getType().name())) { + instance.getLocale().getMessage("general.blocked").processPlaceholder("item", itemToSell.getType().name()).sendPrefixedMessage(player); + return ReturnType.FAILURE; + } + + List possibleTimes = new ArrayList<>(); + Settings.AUCTION_TIME.getStringList().forEach(line -> { + String[] split = line.split(":"); + if (player.hasPermission("auctionhouse.time." + split[0])) { + possibleTimes.add(Integer.parseInt(split[1])); + } + }); + + // get the max allowed time for this player. + int allowedTime = possibleTimes.size() <= 0 ? Settings.DEFAULT_AUCTION_TIME.getInt() : Collections.max(possibleTimes); + + // check if player is at their selling limit + if (auctionPlayer.isAtSellLimit()) { + instance.getLocale().getMessage("general.sellinglimit").sendPrefixedMessage(player); + return ReturnType.FAILURE; + } + + if (args.length <= 1) { + if (!NumberUtils.isDouble(args[0])) { + instance.getLocale().getMessage("general.notanumber").processPlaceholder("value", args[0]).sendPrefixedMessage(player); + return ReturnType.SYNTAX_ERROR; + } + + double basePrice = Double.parseDouble(args[0]); + + if (basePrice < Settings.MIN_AUCTION_PRICE.getDouble()) { + instance.getLocale().getMessage("pricing.minbaseprice").processPlaceholder("price", args[0]).sendPrefixedMessage(player); + return ReturnType.FAILURE; + } + + if (basePrice > Settings.MAX_AUCTION_PRICE.getDouble()) { + instance.getLocale().getMessage("pricing.maxbaseprice").processPlaceholder("price", args[0]).sendPrefixedMessage(player); + return ReturnType.FAILURE; + } + + // list the item + instance.getAuctionItemManager().addItem(new AuctionItem( + player.getUniqueId(), + player.getUniqueId(), + itemToSell, + MaterialCategorizer.getMaterialCategory(itemToSell), + UUID.randomUUID(), + basePrice, + 0, + 0, + basePrice, + allowedTime + )); + + } else { + // they want to use the bidding system, so make it a bid item + } + return ReturnType.SUCCESS; } diff --git a/src/main/java/ca/tweetzy/auctionhouse/helpers/MaterialCategorizer.java b/src/main/java/ca/tweetzy/auctionhouse/helpers/MaterialCategorizer.java new file mode 100644 index 0000000..f1cc9a0 --- /dev/null +++ b/src/main/java/ca/tweetzy/auctionhouse/helpers/MaterialCategorizer.java @@ -0,0 +1,26 @@ +package ca.tweetzy.auctionhouse.helpers; + +import ca.tweetzy.auctionhouse.auction.AuctionItemCategory; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +/** + * The current file has been created by Kiran Hart + * Date Created: February 02 2021 + * Time Created: 5:34 p.m. + * Usage of any code found within this class is prohibited unless given explicit permission otherwise + */ +public class MaterialCategorizer { + + public static AuctionItemCategory getMaterialCategory(ItemStack stack) { + return getMaterialCategory(stack.getType()); + } + + public static AuctionItemCategory getMaterialCategory(Material material) { + if (material.isEdible()) return AuctionItemCategory.FOOD; + if (material.isBlock()) return AuctionItemCategory.BLOCKS; + if (material.name().endsWith("_HELMET") || material.name().endsWith("_CHESTPLATE") || material.name().endsWith("_LEGGINGS") || material.name().endsWith("_BOOTS")) return AuctionItemCategory.ARMOR; + if (material.name().endsWith("_AXE") || material.name().endsWith("_PICKAXE") || material.name().endsWith("_SWORD") || material.name().endsWith("_HOE") || material.name().endsWith("SHOVEL") || material.name().equals("BOW")) return AuctionItemCategory.TOOLS; + return AuctionItemCategory.MISC; + } +} diff --git a/src/main/java/ca/tweetzy/auctionhouse/managers/AuctionItemManager.java b/src/main/java/ca/tweetzy/auctionhouse/managers/AuctionItemManager.java new file mode 100644 index 0000000..4293bd5 --- /dev/null +++ b/src/main/java/ca/tweetzy/auctionhouse/managers/AuctionItemManager.java @@ -0,0 +1,30 @@ +package ca.tweetzy.auctionhouse.managers; + +import ca.tweetzy.auctionhouse.AuctionHouse; +import ca.tweetzy.auctionhouse.auction.AuctionItem; +import lombok.Getter; +import org.bukkit.Bukkit; + +import java.util.LinkedList; + +/** + * The current file has been created by Kiran Hart + * Date Created: February 02 2021 + * Time Created: 6:27 p.m. + * Usage of any code found within this class is prohibited unless given explicit permission otherwise + */ +@Getter +public class AuctionItemManager { + + private final LinkedList auctionItems = new LinkedList<>(); + + public void loadItems() { + + } + + public void addItem(AuctionItem item) { + Bukkit.getServer().getScheduler().runTaskAsynchronously(AuctionHouse.getInstance(), () -> { + auctionItems.add(item); + }); + } +} diff --git a/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java b/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java index 8ef18d8..3018c86 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java +++ b/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java @@ -39,6 +39,16 @@ public class Settings { public static final ConfigSetting TIME_TO_INCREASE_BY_ON_BID = new ConfigSetting(config, "auction setting.time to increase by on the bid", 20, "How much ticks should be added to the bid? 20 == 1 second"); public static final ConfigSetting TIME_TO_DECREASE_BY = new ConfigSetting(config, "auction setting.decrease time by", 5, "How much ticks to decrease auction times by each run. 20 == 1 second"); + /* =============================== + * BLOCKED ITEMS + * ===============================*/ + public static final ConfigSetting BLOCKED_ITEMS = new ConfigSetting(config, "blocked items", Collections.singletonList("ENDER_CHEST"), "Materials that should be blocked (not allowed to sell)"); + + /* =============================== + * MAX AUCTION TIME + * ===============================*/ + public static final ConfigSetting AUCTION_TIME = new ConfigSetting(config, "auction time", Collections.singletonList("rankone:1200"), "Special time permissions for users.", "If they have the following permission in this format:", "auctionhouse.time.rankone", "rankone refers to the list item under auction time, they will get the time specified (in seconds)"); + /* =============================== * GLOBAL ITEMS * ===============================*/ @@ -117,6 +127,43 @@ public class Settings { "&e&l%expired_player_auctions% Item(s)" )); + /* =============================== + * AUCTION STACKS + * ===============================*/ + public static final ConfigSetting AUCTION_ITEM_AUCTION_STACK = new ConfigSetting(config, "auction items.auction stack", Arrays.asList( + "&7-------------------------", + "&eSeller&f: &b%seller%", + "", + "&eBuy Now: &a$%buynowprice%", + "&eCurrent Price: &a$%currentprice%", + "&eBid Increment: &a$%bidincrement%", + "&eHighest Bidder: &a$%highestbidder%", + "", + "&eTime Left: &b%remaining_days%&f:&b%remaining_hours%&f:&b%remaining_minutes%&f:&b%remaining_seconds%" + ), "This the item stack lore that will be appended to", "auction items in /ah (lore will be applied first, then these)"); + + public static final ConfigSetting AUCTION_ITEM_LISTING_STACK = new ConfigSetting(config, "auction items.listing stack", Arrays.asList( + "&7-------------------------", + "&eBuy Now: &a$%buynowprice%", + "&eCurrent Price: &a$%currentprice%", + "&eBid Increment: &a$%bidincrement%", + "&eHighest Bidder: &a$%highestbidder%", + "&eTime Left: &b%remaining_days%&f:&b%remaining_hours%&f:&b%remaining_minutes%&f:&b%remaining_seconds%" + ), "This the item stack lore that will be appended to", "auction items in /ah listings (lore will be applied first, then these)"); + + public static final ConfigSetting AUCTION_PURCHASE_CONTROLS_BID_ON = new ConfigSetting(config, "auction items.controls.using bid", Arrays.asList( + "&7-------------------------", + "&eLeft-Click&f: &bBid", + "&eRight-Click&f: &bBuy Now", + "&7-------------------------" + ), "This will be appended at the end of the lore", "If the auction item is using a bid, this will show"); + + public static final ConfigSetting AUCTION_PURCHASE_CONTROLS_BID_OFF = new ConfigSetting(config, "auction items.controls.not using bid", Arrays.asList( + "&7-------------------------", + "&eLeft-Click&f: &bBuy Now", + "&7-------------------------" + ), "This will be appended at the end of the lore", "If the auction item is not using a bid, this will show"); + public static void setup() { config.load(); config.setAutoremove(true).setAutosave(true); diff --git a/src/main/resources/en_US.lang b/src/main/resources/en_US.lang index 67fe7bd..d2ac776 100644 --- a/src/main/resources/en_US.lang +++ b/src/main/resources/en_US.lang @@ -5,8 +5,18 @@ general: notenoughmoney: '&cYou do not have enough money!' cantbidonown: '&cYou cannot bid on your own item!' cantbuyown: '&cYou cannot buy your own item!' - blockeditem: '&cYou're not allowed to auction that item. (%item%) + blockeditem: '&cYou are not allowed to auction that item. (%item%) air: '&cSorry, but you cannot sell air o.O' + blocked: '&cSorry, you are not allowed to sell &e%item%' + sellinglimit: 'You cannot sell more items, please remove/sell current active items' + +pricing: + minbaseprice: '&cThe minimum base price must be &a$%price%' + minstartingprice: '&cThe minimum starting bid price must be &a$%price%' + minbidincrementprice: '&cThe minimum bid increment must be &a$%price%' + maxbaseprice: '&cThe maximum base price is &a$%price%' + maxstartingprice: '&cThe maximum starting bid price is &a$%price%' + maxbidincrementprice: '&cThe maximum bid increment is &a$%price%'