diff --git a/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java b/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java index 8120001..0015a20 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java +++ b/src/main/java/ca/tweetzy/auctionhouse/AuctionHouse.java @@ -183,7 +183,8 @@ public class AuctionHouse extends TweetyPlugin { new _6_BigIntMigration(), new _7_TransactionBigIntMigration(), new _8_ItemPerWorldMigration(), - new _9_StatsMigration() + new _9_StatsMigration(), + new _10_InfiniteItemsMigration() ); dataMigrationManager.runMigrations(); diff --git a/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java b/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java index 496ef33..e8af928 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java +++ b/src/main/java/ca/tweetzy/auctionhouse/api/AuctionAPI.java @@ -605,25 +605,25 @@ public class AuctionAPI { return NBTEditor.contains(item, "AuctionHouseRepaired"); } - public void listAuction(Player seller, AuctionedItem item, boolean bundle, boolean requiresHandRemove) { - listAuction(seller, item.getItem(), item.getItem(), (int) ((item.getExpiresAt() - System.currentTimeMillis()) / 1000), item.getBasePrice(), item.getBidStartingPrice(), item.getBidIncrementPrice(), item.getCurrentPrice(), item.isBidItem(), bundle, requiresHandRemove); + public void listAuction(Player seller, ItemStack original, ItemStack item, int seconds, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, boolean isBiddingItem, boolean isUsingBundle, boolean requiresHandRemove) { + listAuction(seller, original, item, seconds, basePrice, bidStartPrice, bidIncPrice, currentPrice, isBiddingItem, isUsingBundle, requiresHandRemove, false); } - /** - * Used to insert an auction into the database - * - * @param seller Is the player who is listing the item - * @param item Is the item stack being listed to the auction house - * @param original Is the original item stack (only applies if using a bundle) - * @param seconds Is the total amount of seconds the item will be active for - * @param basePrice Is the buy now price - * @param bidStartPrice Is the price the bidding will start at if the item is an auction - * @param bidIncPrice Is the default price increment for an auction - * @param currentPrice Is the current/start price of an item - * @param isBiddingItem States whether the item is an auction or bin item - * @param isUsingBundle States whether the item is a bundled item - */ - public void listAuction(Player seller, ItemStack original, ItemStack item, int seconds, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, boolean isBiddingItem, boolean isUsingBundle, boolean requiresHandRemove) { + /** + * Used to insert an auction into the database + * + * @param seller Is the player who is listing the item + * @param item Is the item stack being listed to the auction house + * @param original Is the original item stack (only applies if using a bundle) + * @param seconds Is the total amount of seconds the item will be active for + * @param basePrice Is the buy now price + * @param bidStartPrice Is the price the bidding will start at if the item is an auction + * @param bidIncPrice Is the default price increment for an auction + * @param currentPrice Is the current/start price of an item + * @param isBiddingItem States whether the item is an auction or bin item + * @param isUsingBundle States whether the item is a bundled item + */ + public void listAuction(Player seller, ItemStack original, ItemStack item, int seconds, double basePrice, double bidStartPrice, double bidIncPrice, double currentPrice, boolean isBiddingItem, boolean isUsingBundle, boolean requiresHandRemove, boolean isInfinite) { if (McMMOHook.isUsingAbility(seller)) { AuctionHouse.getInstance().getLocale().getMessage("general.mcmmo_ability_active").sendPrefixedMessage(seller); return; @@ -655,6 +655,7 @@ public class AuctionAPI { auctionedItem.setBidIncrementPrice(bidIncPrice); auctionedItem.setCurrentPrice(currentPrice); auctionedItem.setListedWorld(seller.getWorld().getName()); + auctionedItem.setInfinite(isInfinite); if (Settings.TAX_ENABLED.getBoolean() && Settings.TAX_CHARGE_LISTING_FEE.getBoolean()) { if (!EconomyManager.hasBalance(seller, Settings.TAX_LISTING_FEE.getDouble())) { diff --git a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionedItem.java b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionedItem.java index 03ad10a..d5e9f75 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionedItem.java +++ b/src/main/java/ca/tweetzy/auctionhouse/auction/AuctionedItem.java @@ -48,6 +48,7 @@ public class AuctionedItem { private long expiresAt; private String listedWorld = null; + private boolean infinite = false; public AuctionedItem() { } @@ -94,13 +95,17 @@ public class AuctionedItem { lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_CURRENT_PRICE.getStringList().stream().map(s -> s.replace("%currentprice%", Settings.USE_SHORT_NUMBERS_ON_ITEMS.getBoolean() ? AuctionAPI.getInstance().getFriendlyNumber(this.currentPrice) : AuctionAPI.getInstance().formatNumber(this.currentPrice))).collect(Collectors.toList()))); lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_HIGHEST_BIDDER.getStringList().stream().map(s -> s.replace("%highestbidder%", this.highestBidder.equals(this.owner) ? AuctionHouse.getInstance().getLocale().getMessage("auction.nobids").getMessage() : this.highestBidderName)).collect(Collectors.toList()))); - long[] times = AuctionAPI.getInstance().getRemainingTimeValues((this.expiresAt - System.currentTimeMillis()) / 1000); - lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_TIME_LEFT.getStringList().stream().map(s -> s - .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])) - ).collect(Collectors.toList()))); + if (this.infinite) { + lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_INFINITE.getStringList())); + } else { + long[] times = AuctionAPI.getInstance().getRemainingTimeValues((this.expiresAt - System.currentTimeMillis()) / 1000); + lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_TIME_LEFT.getStringList().stream().map(s -> s + .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])) + ).collect(Collectors.toList()))); + } lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_PURCHASE_CONTROL_FOOTER.getStringList())); @@ -130,13 +135,17 @@ public class AuctionedItem { lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_HIGHEST_BIDDER.getStringList().stream().map(s -> s.replace("%highestbidder%", this.highestBidder.equals(this.owner) ? AuctionHouse.getInstance().getLocale().getMessage("auction.nobids").getMessage() : this.highestBidderName)).collect(Collectors.toList()))); } - long[] times = AuctionAPI.getInstance().getRemainingTimeValues((this.expiresAt - System.currentTimeMillis()) / 1000); - lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_TIME_LEFT.getStringList().stream().map(s -> s - .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])) - ).collect(Collectors.toList()))); + if (this.infinite) { + lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_INFINITE.getStringList())); + } else { + long[] times = AuctionAPI.getInstance().getRemainingTimeValues((this.expiresAt - System.currentTimeMillis()) / 1000); + lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_DETAILS_TIME_LEFT.getStringList().stream().map(s -> s + .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])) + ).collect(Collectors.toList()))); + } lore.addAll(TextUtils.formatText(Settings.AUCTION_STACK_PURCHASE_CONTROL_HEADER.getStringList())); diff --git a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java index 29d5dcf..1e3787c 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java +++ b/src/main/java/ca/tweetzy/auctionhouse/commands/CommandSell.java @@ -132,6 +132,7 @@ public final class CommandSell extends AbstractCommand { Double startingBid = null; Double bidIncrement = null; boolean isBundle = false; + boolean isInfinite = false; for (int i = 0; i < args.length; i++) { @@ -147,6 +148,9 @@ public final class CommandSell extends AbstractCommand { if (args[i].equalsIgnoreCase("-b") || args[i].equalsIgnoreCase("-bundle")) isBundle = true; + if ((args[i].equalsIgnoreCase("-i") || args[i].equalsIgnoreCase("-infinite")) && (player.hasPermission("auctionhouse.admin") || player.isOp())) + isInfinite = true; + if (args[i].toLowerCase().startsWith("-t") && Settings.ALLOW_PLAYERS_TO_DEFINE_AUCTION_TIME.getBoolean()) { if (i + 2 < args.length) { int customTime = (int) AuctionAPI.toTicks(args[i + 1] + " " + args[i + 2]); @@ -250,7 +254,8 @@ public final class CommandSell extends AbstractCommand { /* bid inc price */ isBiddingItem ? bidIncrement != null ? bidIncrement : Settings.MIN_AUCTION_INCREMENT_PRICE.getDouble() : 0, isBiddingItem, isBundle, - true + true, + isInfinite )); } else { AuctionAPI.getInstance().listAuction( @@ -264,7 +269,8 @@ public final class CommandSell extends AbstractCommand { /* current price */ isBiddingItem ? startingBid : buyNowPrice <= -1 ? startingBid : buyNowPrice, isBiddingItem || !buyNowAllow, isBundle, - true + true, + isInfinite ); } diff --git a/src/main/java/ca/tweetzy/auctionhouse/database/DataManager.java b/src/main/java/ca/tweetzy/auctionhouse/database/DataManager.java index c927cc7..92378cf 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/database/DataManager.java +++ b/src/main/java/ca/tweetzy/auctionhouse/database/DataManager.java @@ -14,10 +14,7 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -246,7 +243,7 @@ public class DataManager extends DataManagerAbstract { public void insertAuction(AuctionedItem item, Callback callback) { this.databaseConnector.connect(connection -> { - try (PreparedStatement statement = connection.prepareStatement("INSERT INTO " + this.getTablePrefix() + "auctions(id, owner, highest_bidder, owner_name, highest_bidder_name, category, base_price, bid_start_price, bid_increment_price, current_price, expired, expires_at, item_material, item_name, item_lore, item_enchants, item, listed_world) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + try (PreparedStatement statement = connection.prepareStatement("INSERT INTO " + this.getTablePrefix() + "auctions(id, owner, highest_bidder, owner_name, highest_bidder_name, category, base_price, bid_start_price, bid_increment_price, current_price, expired, expires_at, item_material, item_name, item_lore, item_enchants, item, listed_world, infinite) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { PreparedStatement fetch = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "auctions WHERE id = ?"); fetch.setString(1, item.getId().toString()); @@ -268,6 +265,7 @@ public class DataManager extends DataManagerAbstract { statement.setString(16, AuctionAPI.getInstance().serializeLines(AuctionAPI.getInstance().getItemEnchantments(item.getItem()))); statement.setString(17, AuctionAPI.encodeItem(item.getItem())); statement.setString(18, item.getListedWorld()); + statement.setBoolean(19, item.isInfinite()); statement.executeUpdate(); if (callback != null) { @@ -491,7 +489,7 @@ public class DataManager extends DataManagerAbstract { ); auctionItem.setListedWorld(resultSet.getString("listed_world")); - + auctionItem.setInfinite(hasColumn(resultSet, "infinite") && resultSet.getBoolean("infinite")); return auctionItem; } @@ -524,4 +522,15 @@ public class DataManager extends DataManagerAbstract { AuctionAPI.getInstance().logException(this.plugin, ex, "SQLite"); } } + + private boolean hasColumn(ResultSet rs, String columnName) throws SQLException { + ResultSetMetaData rsmd = rs.getMetaData(); + int columns = rsmd.getColumnCount(); + for (int x = 1; x <= columns; x++) { + if (columnName.equals(rsmd.getColumnName(x))) { + return true; + } + } + return false; + } } diff --git a/src/main/java/ca/tweetzy/auctionhouse/database/migrations/_10_InfiniteItemsMigration.java b/src/main/java/ca/tweetzy/auctionhouse/database/migrations/_10_InfiniteItemsMigration.java new file mode 100644 index 0000000..514dd42 --- /dev/null +++ b/src/main/java/ca/tweetzy/auctionhouse/database/migrations/_10_InfiniteItemsMigration.java @@ -0,0 +1,27 @@ +package ca.tweetzy.auctionhouse.database.migrations; + +import ca.tweetzy.core.database.DataMigration; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * The current file has been created by Kiran Hart + * Date Created: August 24 2021 + * Time Created: 4:04 p.m. + * Usage of any code found within this class is prohibited unless given explicit permission otherwise + */ +public final class _10_InfiniteItemsMigration extends DataMigration { + + public _10_InfiniteItemsMigration() { + super(10); + } + + @Override + public void migrate(Connection connection, String tablePrefix) throws SQLException { + try (Statement statement = connection.createStatement()) { + statement.execute("ALTER TABLE " + tablePrefix + "auctions ADD infinite BOOLEAN NULL"); + } + } +} diff --git a/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java b/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java index 09bbeef..eecfa09 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java +++ b/src/main/java/ca/tweetzy/auctionhouse/guis/GUIAuctionHouse.java @@ -136,6 +136,8 @@ public class GUIAuctionHouse extends Gui { this.items = this.items.stream().sorted(Comparator.comparingLong(AuctionedItem::getExpiresAt).reversed()).collect(Collectors.toList()); } + this.items = this.items.stream().sorted(Comparator.comparing(AuctionedItem::isInfinite).reversed()).collect(Collectors.toList()); + return this.items.stream().skip((page - 1) * 45L).limit(45L).collect(Collectors.toList()); }).asyncLast((data) -> { pages = (int) Math.max(1, Math.ceil(this.items.size() / (double) 45L)); diff --git a/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmListing.java b/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmListing.java index b94caf9..a8eaae2 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmListing.java +++ b/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmListing.java @@ -29,9 +29,10 @@ public class GUIConfirmListing extends Gui { private final boolean isBiddingItem; private final boolean isBundle; private final boolean requiresHandRemove; + private final boolean isInfinite; - public GUIConfirmListing(Player player, ItemStack originalItem, ItemStack itemToSell, int allowedTime, double basePrice, double startingBid, double bidIncrement, boolean isBiddingItem, boolean bundle, boolean requiresHandRemove) { + public GUIConfirmListing(Player player, ItemStack originalItem, ItemStack itemToSell, int allowedTime, double basePrice, double startingBid, double bidIncrement, boolean isBiddingItem, boolean bundle, boolean requiresHandRemove, boolean isInfinite) { this.player = player; this.originalItem = originalItem; this.itemToSell = itemToSell; @@ -42,7 +43,7 @@ public class GUIConfirmListing extends Gui { this.isBiddingItem = isBiddingItem; this.isBundle = bundle; this.requiresHandRemove = requiresHandRemove; - + this.isInfinite = isInfinite; setTitle(TextUtils.formatText(Settings.GUI_CONFIRM_LISTING_TITLE.getString())); setAcceptsItems(false); @@ -75,7 +76,8 @@ public class GUIConfirmListing extends Gui { /* current price */ this.isBiddingItem ? this.startingBid : this.basePrice <= -1 ? this.startingBid : this.basePrice, this.isBiddingItem, this.isBundle, - this.requiresHandRemove + this.requiresHandRemove, + this.isInfinite ); e.gui.close(); }); diff --git a/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmPurchase.java b/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmPurchase.java index 6964f45..70470cc 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmPurchase.java +++ b/src/main/java/ca/tweetzy/auctionhouse/guis/confirmation/GUIConfirmPurchase.java @@ -138,13 +138,18 @@ public class GUIConfirmPurchase extends Gui { if (item.getAmount() - this.purchaseQuantity >= 1) { item.setAmount(item.getAmount() - this.purchaseQuantity); - located.setItem(item); - located.setBasePrice(located.getBasePrice() - buyNowPrice); + + if (!located.isInfinite()) { + located.setItem(item); + located.setBasePrice(located.getBasePrice() - buyNowPrice); + } + item.setAmount(this.purchaseQuantity); transferFunds(e.player, buyNowPrice); } else { transferFunds(e.player, buyNowPrice); - AuctionHouse.getInstance().getAuctionItemManager().sendToGarbage(located); + if (!located.isInfinite()) + AuctionHouse.getInstance().getAuctionItemManager().sendToGarbage(located); } PlayerUtils.giveItem(e.player, item); @@ -152,7 +157,9 @@ public class GUIConfirmPurchase extends Gui { } else { transferFunds(e.player, buyNowPrice); - AuctionHouse.getInstance().getAuctionItemManager().sendToGarbage(located); + if (!located.isInfinite()) + AuctionHouse.getInstance().getAuctionItemManager().sendToGarbage(located); + PlayerUtils.giveItem(e.player, located.getItem()); sendMessages(e, located, false, 0); } diff --git a/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java b/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java index 898647c..972877b 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java +++ b/src/main/java/ca/tweetzy/auctionhouse/settings/Settings.java @@ -874,6 +874,12 @@ public class Settings { "&eTime Left: &b%remaining_days%&fd &b%remaining_hours%&fh &b%remaining_minutes%&fm &b%remaining_seconds%s" )); + public static final ConfigSetting AUCTION_STACK_DETAILS_INFINITE = new ConfigSetting(config, "auction stack.infinite lines", Arrays.asList( + "", + "&eTime Left: &bNo Expiration" + ), "this will be used instead of the time left if the item is infinite"); + + public static final ConfigSetting AUCTION_STACK_PURCHASE_CONTROL_HEADER = new ConfigSetting(config, "auction stack.controls.header", Collections.singletonList("&7&m-------------------------")); public static final ConfigSetting AUCTION_STACK_PURCHASE_CONTROL_FOOTER = new ConfigSetting(config, "auction stack.controls.footer", Collections.singletonList("&7&m-------------------------")); public static final ConfigSetting AUCTION_STACK_PURCHASE_CONTROLS_INSPECTION = new ConfigSetting(config, "auction stack.controls.inspection", Collections.singletonList("&eShift Right-Click to inspect"), "This will only be added to the control lore if the item can be inspected (skulker box/bundled item)"); diff --git a/src/main/java/ca/tweetzy/auctionhouse/tasks/TickAuctionsTask.java b/src/main/java/ca/tweetzy/auctionhouse/tasks/TickAuctionsTask.java index 7d9ee6d..ea44584 100644 --- a/src/main/java/ca/tweetzy/auctionhouse/tasks/TickAuctionsTask.java +++ b/src/main/java/ca/tweetzy/auctionhouse/tasks/TickAuctionsTask.java @@ -59,6 +59,8 @@ public class TickAuctionsTask extends BukkitRunnable { continue; } + if (auctionItem.isInfinite()) continue; + long timeRemaining = (auctionItem.getExpiresAt() - System.currentTimeMillis()) / 1000; if (!auctionItem.isExpired()) {