public class AuctionDataManager { private Main main = Main.getInstance(); private AuctionConfig auctionConfig = main.getAuctionConfig(); private ILocaleManager localeManager = main.getLocaleManager(); private CrafterYamlConfigManager data = new CrafterYamlConfigManager(new File(main.getDataFolder(), "auctionData.yml"), false, main) { @Override public CrafterYamlConfigManager save() { return super.save(); } @Override protected Runnable getAsynchronousSaveRunnable() { AuctionDataManager.this.save(); return super.getAsynchronousSaveRunnable(); } }; private ArrayList<Lot> lots = new ArrayList<>(); public AuctionDataManager() { this.load(); data.setAutoSaveInterval(60); data.setAsynchronousAutoSave(true); new LotMaintainTask().runTaskTimer(main, 20L, 20L); } public void shutdownGracefully() { data.setAutoSaveInterval(0); data.shutdownAsynchronousSavingConsumer(); this.save(); data.save(); } public Map<UUID, ItemStack> getVaultContents(Player p) { String vaultPath = new StringBuilder(43).append("vaults.").append(p.getUniqueId()).toString(); ConfigurationSection singlePlayerVaultSection = data.getConfigurationSection(vaultPath); HashMap<UUID, ItemStack> result = new HashMap<>(); for (String lotUuidString : singlePlayerVaultSection.getKeys(false)) { if (lotUuidString.length() != 36) continue; // There is an itemCount field result.put( UUID.fromString(lotUuidString), singlePlayerVaultSection.getItemStack(lotUuidString)); } return result; } public boolean removeVaultItem(Player p, UUID lotUuid) { String vaultPath = new StringBuilder(43).append("vaults.").append(p.getUniqueId()).toString(); ConfigurationSection singlePlayerVaultSection = data.getConfigurationSection(vaultPath); String uuidString = lotUuid.toString(); if (singlePlayerVaultSection.isSet(uuidString)) { singlePlayerVaultSection.set(uuidString, null); unoccupyVault(p.getUniqueId()); return true; } else { return false; } } public boolean hasLot(Lot lot) { return lots.contains(lot); } public boolean addLot(ItemStack item) { AuctionableItem ai = auctionConfig.getAuctionableItemConfig(item); if (null == ai) return false; double startingPrice = (((int) (ai.getStartingPrice() * 100)) * item.getAmount()) / 100D; double minimumIncrement = (((int) (ai.getMinimumIncrement() * 100)) * item.getAmount()) / 100D; Lot lot = new Lot( item, false, startingPrice, null, null, -1, minimumIncrement, System.currentTimeMillis() + ai.getPreserveTimeInSeconds() * 1000, ai.getAuctionDurationInSeconds() * 1000); lots.add(lot); LotShowcase.updateAll(); return true; } public void addLots(List<ItemStack> items) { for (ItemStack item : items) { AuctionableItem ai = auctionConfig.getAuctionableItemConfig(item); if (null == ai) continue; double startingPrice = (((int) (ai.getStartingPrice() * 100)) * item.getAmount()) / 100D; double minimumIncrement = (((int) (ai.getMinimumIncrement() * 100)) * item.getAmount()) / 100D; Lot lot = new Lot( item, false, startingPrice, null, null, -1, minimumIncrement, System.currentTimeMillis() + ai.getPreserveTimeInSeconds() * 1000, ai.getAuctionDurationInSeconds() * 1000); lots.add(lot); } LotShowcase.updateAll(); } public boolean removeLot(Lot lot) { boolean success = lots.remove(lot); removeFromBackend(lot); LotShowcase.updateAll(); LotOperationMenu.updateAll(); return success; } public List<Lot> getLots() { return Collections.unmodifiableList(lots); } private void save() { for (Lot lot : lots) { this.saveToBackend(lot); } // Vaults section cleanup ConfigurationSection vaultsSection = data.getYamlConfig().getConfigurationSection("vaults"); if (vaultsSection != null) { for (Entry<String, Object> e : vaultsSection.getValues(false).entrySet()) { Object v = e.getValue(); if (!(v instanceof ConfigurationSection)) continue; ConfigurationSection singleVaultSection = (ConfigurationSection) v; int size = singleVaultSection.getKeys(false).size(); if (size == 0 || (size == 1 && singleVaultSection.getInt("itemCount", -1) == 0)) { vaultsSection.set(e.getKey(), null); } } } } public boolean hasBidBefore(Player p, Lot lot) { String depositPath = new StringBuilder(86) .append("lots.") .append(lot.getUuid()) .append(".deposit.") .append(p.getUniqueId()) .toString(); return data.isSet(depositPath); } private void saveToBackend(Lot lot) { UUID uuid = lot.getUuid(); String uuidString = uuid.toString(); ItemStack item = lot.getItem(); boolean started = lot.isStarted(); double price = lot.getPrice(); String lastBidPlayerName = lot.getLastBidPlayerName(); UUID lastBidPlayerUuid = lot.getLastBidPlayerUuid(); double lastBidPrice = lot.getLastBidPrice(); double minimumIncrement = lot.getMinimumIncrement(); long preserveTimeExpire = lot.getPreserveTimeExpire(); long auctionDurationExpire = lot.getAuctionDurationExpire(); String sectionPath = "lots." + uuidString; ConfigurationSection singleLotSection = data.getYamlConfig().getConfigurationSection(sectionPath); if (null == singleLotSection) { singleLotSection = data.getYamlConfig().createSection(sectionPath); } singleLotSection.set("item", item); singleLotSection.set("started", started); singleLotSection.set("price", price); singleLotSection.set("lastBidPlayerName", lastBidPlayerName); singleLotSection.set( "lastBidPlayerUuid", null == lastBidPlayerUuid ? null : lastBidPlayerUuid.toString()); singleLotSection.set("lastBidPrice", lastBidPrice); singleLotSection.set("minimumIncrement", minimumIncrement); singleLotSection.set("preserveTimeExpire", preserveTimeExpire); singleLotSection.set("auctionDurationExpire", auctionDurationExpire); } private void removeFromBackend(Lot lot) { data.set("lots." + lot.getUuid().toString(), null); } public void bid(Player p, boolean anonymous, Lot lot, double priceIncrement) { if (hasBidBefore(p, lot)) { addDeposit(lot, p, priceIncrement); } else { occupyVault(p); addDeposit(lot, p, lot.getPrice() + priceIncrement); } if (!lot.isStarted()) { lot.setAuctionDurationExpire(lot.getAuctionDurationExpire() + System.currentTimeMillis()); lot.setStarted(true); } lot.setLastBidPlayerName( anonymous ? localeManager.getLocalizedString("ui.anonymous") : p.getName()); lot.setLastBidPlayerUuid(p.getUniqueId()); lot.setLastBidPrice(priceIncrement); lot.setPrice(lot.getPrice() + priceIncrement); LotShowcase.updateAll(); LotOperationMenu.updateAll(); } public long getLastBid(Player p, Lot lot) { String lastBidPath = new StringBuilder(90) .append("lots.") .append(lot.getUuid()) .append(".bid.lastBid.") .append(p.getUniqueId()) .toString(); return data.getYamlConfig().getLong(lastBidPath); } public void setLastBid(Player p, Lot lot, long lastBid) { String lastBidPath = new StringBuilder(90) .append("lots.") .append(lot.getUuid()) .append(".bid.lastBid.") .append(p.getUniqueId()) .toString(); data.set(lastBidPath, lastBid); } public boolean isVaultAvailable(Player p) { String vaultPath = new StringBuilder(43).append("vaults.").append(p.getUniqueId()).toString(); ConfigurationSection singlePlayerVaultSection = data.getConfigurationSection(vaultPath); return singlePlayerVaultSection.getInt("itemCount", 0) < auctionConfig.getVaultCapacity(p); } public boolean occupyVault(Player p) { String vaultPath = new StringBuilder(43).append("vaults.").append(p.getUniqueId()).toString(); ConfigurationSection singlePlayerVaultSection = data.getConfigurationSection(vaultPath); int itemCount = singlePlayerVaultSection.getInt("itemCount", 0); if (itemCount < auctionConfig.getVaultCapacity(p)) { singlePlayerVaultSection.set("itemCount", ++itemCount); return true; } else { return false; } } public void unoccupyVault(UUID uuid) { String vaultPath = new StringBuilder(43).append("vaults.").append(uuid).toString(); ConfigurationSection singlePlayerVaultSection = data.getConfigurationSection(vaultPath); int itemCount = singlePlayerVaultSection.getInt("itemCount", 0); if (itemCount <= 0) return; singlePlayerVaultSection.set("itemCount", --itemCount); } public void addDepositToVault(UUID uuid, double deposit) { String path = new StringBuilder(51) .append("vaults.") .append(uuid.toString()) .append('.') .append("deposit") .toString(); double original = data.getYamlConfig().getDouble(path, 0); data.set(path, original + deposit); } public void removeDepositFromVault(UUID uuid, double deposit) { String path = new StringBuilder(51) .append("vaults.") .append(uuid.toString()) .append('.') .append("deposit") .toString(); double original = data.getYamlConfig().getDouble(path, 0); double newDeposit = original - deposit; if (newDeposit <= 0) { data.set(path, null); } else { data.set(path, newDeposit); } } public void removeDepositFromVault(UUID uuid) { String path = new StringBuilder(51) .append("vaults.") .append(uuid.toString()) .append('.') .append("deposit") .toString(); data.set(path, null); } public double getDepositInVault(UUID uuid) { String path = new StringBuilder(51) .append("vaults.") .append(uuid.toString()) .append('.') .append("deposit") .toString(); return data.getYamlConfig().getDouble(path, 0); } public void returnDepositInVault(UUID uuid) { Player p = CompatUtils.getPlayer(uuid); double deposit = getDepositInVault(uuid); if (deposit <= 0) return; Main.economy.depositPlayer(p, deposit); removeDepositFromVault(uuid); } public void addDeposit(Lot lot, Player p, double deposit) { String depositPath = new StringBuilder(86) .append("lots.") .append(lot.getUuid()) .append(".deposit.") .append(p.getUniqueId()) .toString(); data.set(depositPath, data.getYamlConfig().getDouble(depositPath, 0) + deposit); } public Map<UUID, Double> getDeposit(Lot lot) { HashMap<UUID, Double> result = new HashMap<>(); String path = new StringBuilder(49).append("lots.").append(lot.getUuid()).append(".deposit").toString(); ConfigurationSection singleLotDepositSection = data.getConfigurationSection(path); for (String uuidString : singleLotDepositSection.getKeys(false)) { UUID uuid = UUID.fromString(uuidString); result.put(uuid, singleLotDepositSection.getDouble(uuidString)); } return result; } public void returnDeposit(Lot lot) { for (Entry<UUID, Double> e : getDeposit(lot).entrySet()) { Player p = CompatUtils.getPlayer(e.getKey()); if (p != null) { Main.economy.depositPlayer(p, e.getValue()); } else { addDepositToVault(e.getKey(), e.getValue()); } } } public void hammer(Lot lot) { UUID buyerUuid = lot.getLastBidPlayerUuid(); Player buyer = CompatUtils.getPlayer(buyerUuid); if (null == buyer || buyer.getInventory().firstEmpty() == -1) { String path = new StringBuilder(80) .append("vaults.") .append(buyerUuid.toString()) .append('.') .append(lot.getUuid()) .toString(); data.set(path, lot.getItem()); } else { unoccupyVault(buyerUuid); buyer.getInventory().addItem(lot.getItem()); } if (buyer != null) buyer.sendMessage(localeManager.getLocalizedString("ui.hammerBuyer")); Map<UUID, Double> deposit = getDeposit(lot); deposit.remove(buyerUuid); for (Entry<UUID, Double> e : deposit.entrySet()) { Player p = CompatUtils.getPlayer(e.getKey()); if (null != p) { p.sendMessage(localeManager.getLocalizedString("ui.hammerOthers")); Main.economy.depositPlayer(p, e.getValue()); } else { addDepositToVault(e.getKey(), e.getValue()); } unoccupyVault(e.getKey()); } removeLot(lot); } private void load() { ConfigurationSection lotsSection = data.getConfigurationSection("lots"); for (String uuidString : lotsSection.getKeys(false)) { ConfigurationSection singleLotSection = lotsSection.getConfigurationSection(uuidString); ItemStack item = singleLotSection.getItemStack("item"); boolean started = singleLotSection.getBoolean("started"); double price = singleLotSection.getDouble("price"); String lastBidPlayerName = singleLotSection.getString("lastBidPlayerName"); UUID lastBidPlayerUuid = singleLotSection.isSet("lastBidPlayerUuid") ? UUID.fromString(singleLotSection.getString("lastBidPlayerUuid")) : null; double lastBidPrice = singleLotSection.getDouble("lastBidPrice"); double minimumIncrement = singleLotSection.getDouble("minimumIncrement"); long preserveTimeExpire = singleLotSection.getLong("preserveTimeExpire"); long auctionDurationExpire = singleLotSection.getLong("auctionDurationExpire"); Lot lot = new Lot( UUID.fromString(uuidString), item, started, price, lastBidPlayerName, lastBidPlayerUuid, lastBidPrice, minimumIncrement, preserveTimeExpire, auctionDurationExpire); lots.add(lot); } } private class LotMaintainTask extends BukkitRunnable { @Override public void run() { long currentTime = System.currentTimeMillis(); List<Lot> lotsToHammer = null; List<Lot> lotsToRemove = null; for (Lot lot : lots) { if (lot.isStarted()) { if (currentTime > lot.getAuctionDurationExpire()) { if (null == lotsToHammer) { lotsToHammer = new ArrayList<Lot>(); } lotsToHammer.add(lot); } } else { if (currentTime > lot.getPreserveTimeExpire()) { if (null == lotsToRemove) { lotsToRemove = new ArrayList<Lot>(); } lotsToRemove.add(lot); } } } if (lotsToHammer != null) { for (Lot lot : lotsToHammer) { hammer(lot); } } if (lotsToRemove != null) { for (Lot lot : lotsToRemove) { removeLot(lot); } } } } }