From d5d4bf7c45eabc4edcc9e30973b6db4138629307 Mon Sep 17 00:00:00 2001 From: Shyanne Date: Mon, 2 Oct 2023 01:03:56 -0400 Subject: [PATCH] Added payPerRegen setting - added `payPerRegen` setting to allow servers to charge players to regenerate their island - includes a message sent to players of the island with `%schematic% placeholder to add schematic name to message - missing schematic lore --- .../commands/RegenCommand.java | 7 ++ .../configs/Configuration.java | 1 + .../iridiumskyblock/configs/Messages.java | 1 + .../iridiumskyblock/configs/Schematics.java | 95 ++++++++++++++----- .../managers/SchematicManager.java | 84 ++++++++++++++++ 5 files changed, 162 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/iridium/iridiumskyblock/commands/RegenCommand.java b/src/main/java/com/iridium/iridiumskyblock/commands/RegenCommand.java index efdd82db8..5dd44a298 100644 --- a/src/main/java/com/iridium/iridiumskyblock/commands/RegenCommand.java +++ b/src/main/java/com/iridium/iridiumskyblock/commands/RegenCommand.java @@ -47,6 +47,13 @@ public boolean execute(User user, Island island, String[] args, IridiumTeams schematics = ImmutableMap.builder() - .put("desert", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 11, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGY0OTNkZDgwNjUzM2Q5ZDIwZTg0OTUzOTU0MzY1ZjRkMzY5NzA5Y2ViYzlkZGVmMDIyZDFmZDQwZDg2YTY4ZiJ9fX0=", 1, "&9&lDesert Island", Collections.singletonList("&7A starter desert island.")), - -0.5, 89, -0.5, 90, new SchematicWorld(Biome.DESERT, - "desert.schem", 90.0, true - ), new SchematicWorld(Biome.NETHER_WASTES, - "desert_nether.schem", 90.0, true - ), new SchematicWorld(Biome.THE_END, - "desert_end.schem", 90.0, true - ))) - .put("jungle", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 13, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjgzYWRmNDU2MGRlNDc0MTQwNDA5M2FjNjFjMzNmYjU1NmIzZDllZTUxNDBmNjIwMzYyNTg5ZmRkZWRlZmEyZCJ9fX0=", 1, "&9&lJungle Island", Collections.singletonList("&7A starter jungle island.")), - 1.5, 83, 1.5, 90, new SchematicWorld(Biome.JUNGLE, - "jungle.schem", 90.0, true - ), new SchematicWorld(Biome.NETHER_WASTES, - "jungle_nether.schem", 90.0, true - ), new SchematicWorld(Biome.THE_END, - "jungle_end.schem", 90.0, true - ))) - .put("mushroom", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 15, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE0NWQxYjQxN2NiZGRjMjE3NjdiMDYwNDRlODk5YjI2NmJmNzhhNjZlMjE4NzZiZTNjMDUxNWFiNTVkNzEifX19", 1, "&9&lMushroom Island", Collections.singletonList("&7A starter mushroom island.")), - 0.5, 89, -0.5, 90, new SchematicWorld(Biome.MUSHROOM_FIELDS, - "mushroom.schem", 90.0, true - ), new SchematicWorld(Biome.NETHER_WASTES, - "mushroom_nether.schem", 90.0, true - ), new SchematicWorld(Biome.THE_END, - "mushroom_end.schem", 90.0, true - ))) - .build(); + public Map schematics; + public String buyPriceLore; + public String notPurchasableLore; + public boolean abbreviatePrices; + public XSound failSound; + public XSound successSound; + public List schematicPurchaseLore; + + public Schematics() { + this("&c"); + } + + public Schematics(String color) { + schematics = ImmutableMap.builder() + .put("desert", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 11, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGY0OTNkZDgwNjUzM2Q5ZDIwZTg0OTUzOTU0MzY1ZjRkMzY5NzA5Y2ViYzlkZGVmMDIyZDFmZDQwZDg2YTY4ZiJ9fX0=", 1, "&9&lDesert Island", Collections.singletonList("&7A starter desert island.")), + new Schematics.Cost(100, new HashMap<>()), -0.5, 89, -0.5, 90, new SchematicWorld(Biome.DESERT, + "desert.schem", 90.0, true + ), new SchematicWorld(Biome.NETHER_WASTES, + "desert_nether.schem", 90.0, true + ), new SchematicWorld(Biome.THE_END, + "desert_end.schem", 90.0, true + ))) + .put("jungle", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 13, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjgzYWRmNDU2MGRlNDc0MTQwNDA5M2FjNjFjMzNmYjU1NmIzZDllZTUxNDBmNjIwMzYyNTg5ZmRkZWRlZmEyZCJ9fX0=", 1, "&9&lJungle Island", Collections.singletonList("&7A starter jungle island.")), + new Schematics.Cost(100, new HashMap<>()), 1.5, 83, 1.5, 90, new SchematicWorld(Biome.JUNGLE, + "jungle.schem", 90.0, true + ), new SchematicWorld(Biome.NETHER_WASTES, + "jungle_nether.schem", 90.0, true + ), new SchematicWorld(Biome.THE_END, + "jungle_end.schem", 90.0, true + ))) + .put("mushroom", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 15, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE0NWQxYjQxN2NiZGRjMjE3NjdiMDYwNDRlODk5YjI2NmJmNzhhNjZlMjE4NzZiZTNjMDUxNWFiNTVkNzEifX19", 1, "&9&lMushroom Island", Collections.singletonList("&7A starter mushroom island.")), + new Schematics.Cost(100, new HashMap<>()), 0.5, 89, -0.5, 90, new SchematicWorld(Biome.MUSHROOM_FIELDS, + "mushroom.schem", 90.0, true + ), new SchematicWorld(Biome.NETHER_WASTES, + "mushroom_nether.schem", 90.0, true + ), new SchematicWorld(Biome.THE_END, + "mushroom_end.schem", 90.0, true + ))) + .build(); + + buyPriceLore = "&aBuy Price: $%vault_cost%"; + notPurchasableLore = "&cThis item cannot be purchased!"; + + abbreviatePrices = true; + + failSound = XSound.BLOCK_ANVIL_LAND; + successSound = XSound.ENTITY_PLAYER_LEVELUP; + + schematicPurchaseLore = Arrays.asList( + " ", + color + "&l[!] " + color + "Left-Click to Purchase %amount%, Shift for 64", + color + "&l[!] " + color + "Right Click to Sell %amount%, Shift for 64" + ); + } @NoArgsConstructor @AllArgsConstructor public static class SchematicConfig { public Item item; + public Cost regenCost; public double xHome; public double yHome; public double zHome; @@ -69,4 +100,16 @@ public SchematicWorld(Biome biome, String schematicID, Double islandHeight, Bool } } + @AllArgsConstructor + @NoArgsConstructor + public static class Cost { + public double money; + public Map bankItems; + + @JsonIgnore + public boolean canPurchase() { + return money > 0 || bankItems.values().stream().anyMatch(value -> value > 0); + } + } + } diff --git a/src/main/java/com/iridium/iridiumskyblock/managers/SchematicManager.java b/src/main/java/com/iridium/iridiumskyblock/managers/SchematicManager.java index 71476c898..1c81eed36 100644 --- a/src/main/java/com/iridium/iridiumskyblock/managers/SchematicManager.java +++ b/src/main/java/com/iridium/iridiumskyblock/managers/SchematicManager.java @@ -1,20 +1,30 @@ package com.iridium.iridiumskyblock.managers; +import com.iridium.iridiumcore.utils.Placeholder; +import com.iridium.iridiumcore.utils.StringUtils; import com.iridium.iridiumskyblock.IridiumSkyblock; import com.iridium.iridiumskyblock.configs.Schematics; import com.iridium.iridiumskyblock.database.Island; +import com.iridium.iridiumskyblock.database.User; import com.iridium.iridiumskyblock.schematics.FastAsyncWorldEdit; import com.iridium.iridiumskyblock.schematics.SchematicAsync; import com.iridium.iridiumskyblock.schematics.SchematicPaster; import com.iridium.iridiumskyblock.schematics.WorldEdit; +import com.iridium.iridiumteams.bank.BankItem; +import com.iridium.iridiumteams.database.TeamBank; +import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.entity.Player; import java.io.File; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; public class SchematicManager { @@ -115,4 +125,78 @@ private CompletableFuture pasteSchematic(Island island, Schematics.Schemat return completableFuture; } + public boolean buy(Player player, Schematics.SchematicConfig schematic) { + if (!canPurchase(player, schematic)) { + player.sendMessage(StringUtils.color(IridiumSkyblock.getInstance().getMessages().cannotAfford + .replace("%prefix%", IridiumSkyblock.getInstance().getConfiguration().prefix))); + IridiumSkyblock.getInstance().getSchematics().failSound.play(player); + return false; + } + + purchase(player, schematic); + + IridiumSkyblock.getInstance().getSchematics().successSound.play(player); + + List bankPlaceholders = IridiumSkyblock.getInstance().getBankItemList().stream() + .map(BankItem::getName) + .map(name -> new Placeholder(name + "_cost", formatPrice(getBankBalance(player, name)))) + .collect(Collectors.toList()); + + player.sendMessage(StringUtils.color(StringUtils.processMultiplePlaceholders(IridiumSkyblock.getInstance().getMessages().paidForRegen + .replace("%prefix%", IridiumSkyblock.getInstance().getConfiguration().prefix) + .replace("%player%", player.getName()) + .replace("%schematic%", StringUtils.color(schematic.item.displayName)) + .replace("%vault_cost%", formatPrice(schematic.regenCost.money)), + bankPlaceholders) + )); + + return true; + } + + private double getBankBalance(Player player, String bankItem) { + User user = IridiumSkyblock.getInstance().getUserManager().getUser(player); + return IridiumSkyblock.getInstance().getTeamManager().getTeamViaID(user.getTeamID()) + .map(team -> IridiumSkyblock.getInstance().getTeamManager().getTeamBank(team, bankItem)) + .map(TeamBank::getNumber) + .orElse(0.0); + } + + private void setBankBalance(Player player, String bankItem, double amount) { + User user = IridiumSkyblock.getInstance().getUserManager().getUser(player); + Optional island = IridiumSkyblock.getInstance().getTeamManager().getTeamViaID(user.getTeamID()); + if (!island.isPresent()) return; + IridiumSkyblock.getInstance().getTeamManager().getTeamBank(island.get(), bankItem).setNumber(amount); + } + + private boolean canPurchase(Player player, Schematics.SchematicConfig schematic) { + double moneyCost = schematic.regenCost.money; + Economy economy = IridiumSkyblock.getInstance().getEconomy(); + for (String bankItem : schematic.regenCost.bankItems.keySet()) { + double cost = round(schematic.regenCost.bankItems.get(bankItem), 2); + if (getBankBalance(player, bankItem) < cost) return false; + } + + return moneyCost == 0 || economy != null && economy.getBalance(player) >= schematic.regenCost.money; + } + + private void purchase(Player player, Schematics.SchematicConfig schematic) { + IridiumSkyblock.getInstance().getEconomy().withdrawPlayer(player, schematic.regenCost.money); + + for (String bankItem : schematic.regenCost.bankItems.keySet()) { + setBankBalance(player, bankItem, getBankBalance(player, bankItem) - round(schematic.regenCost.bankItems.get(bankItem), 2)); + } + } + + private double round(double value, int places) { + BigDecimal bigDecimal = BigDecimal.valueOf(value); + bigDecimal = bigDecimal.setScale(places, RoundingMode.HALF_UP); + return bigDecimal.doubleValue(); + } + + public String formatPrice(double value) { + if (IridiumSkyblock.getInstance().getSchematics().abbreviatePrices) { + return IridiumSkyblock.getInstance().getConfiguration().numberFormatter.format(value); + } + return String.valueOf(value); + } }