From 941b45702c214c2a5287899791e06875db5637fb Mon Sep 17 00:00:00 2001 From: TopchetoEU Date: Thu, 13 Jan 2022 14:29:45 +0200 Subject: [PATCH] First commit --- .gitignore | 3 + pom.xml | 77 +++ .../java/me/topchetoeu/bedwars/Commands.java | 294 +++++++++++ .../topchetoeu/bedwars/InventoryUtility.java | 93 ++++ src/main/java/me/topchetoeu/bedwars/Main.java | 315 +++++++++++ .../java/me/topchetoeu/bedwars/Utility.java | 178 +++++++ .../bedwars/commandUtility/Command.java | 147 ++++++ .../commandUtility/CommandExecutor.java | 7 + .../commandUtility/CommandExecutors.java | 62 +++ .../bedwars/engine/BedwarsPlayer.java | 493 ++++++++++++++++++ .../me/topchetoeu/bedwars/engine/Config.java | 146 ++++++ .../bedwars/engine/DeathMessage.java | 68 +++ .../me/topchetoeu/bedwars/engine/Game.java | 450 ++++++++++++++++ .../topchetoeu/bedwars/engine/Generator.java | 146 ++++++ .../bedwars/engine/GeneratorLabel.java | 46 ++ .../topchetoeu/bedwars/engine/HoverLabel.java | 107 ++++ .../topchetoeu/bedwars/engine/SavedBlock.java | 17 + .../bedwars/engine/ScoreboardManager.java | 79 +++ .../me/topchetoeu/bedwars/engine/Team.java | 255 +++++++++ .../topchetoeu/bedwars/engine/TeamColor.java | 87 ++++ .../bedwars/engine/WoodenSword.java | 26 + .../bedwars/engine/trader/Deal.java | 15 + .../bedwars/engine/trader/DealPtr.java | 26 + .../bedwars/engine/trader/DealType.java | 8 + .../bedwars/engine/trader/DealTypes.java | 20 + .../bedwars/engine/trader/Favourites.java | 81 +++ .../bedwars/engine/trader/Section.java | 48 ++ .../bedwars/engine/trader/Sections.java | 50 ++ .../bedwars/engine/trader/TraderGUI.java | 341 ++++++++++++ .../bedwars/engine/trader/Traders.java | 182 +++++++ .../trader/dealTypes/EnforcedRankedDeal.java | 52 ++ .../dealTypes/EnforcedRankedDealType.java | 35 ++ .../engine/trader/dealTypes/ItemDeal.java | 74 +++ .../engine/trader/dealTypes/ItemDealType.java | 34 ++ .../engine/trader/dealTypes/Price.java | 35 ++ .../bedwars/engine/trader/dealTypes/Rank.java | 259 +++++++++ .../engine/trader/dealTypes/RankTier.java | 55 ++ .../trader/dealTypes/RankTierApplier.java | 24 + .../trader/dealTypes/RankTierItemApplier.java | 72 +++ .../engine/trader/dealTypes/RankedDeal.java | 59 +++ .../trader/dealTypes/RankedDealType.java | 83 +++ .../trader/dealTypes/RankedUpgradeDeal.java | 88 ++++ .../dealTypes/RankedUpgradeDealType.java | 40 ++ .../trader/dealTypes/TeamUpgradeRank.java | 85 +++ .../trader/dealTypes/TeamUpgradeRanks.java | 40 ++ .../trader/upgrades/BlindnessTeamUpgrade.java | 61 +++ .../upgrades/EfficiencyTeamUpgrade.java | 79 +++ .../trader/upgrades/FatigueTeamUpgrade.java | 61 +++ .../trader/upgrades/HealTeamUpgrade.java | 59 +++ .../upgrades/ProtectionTeamUpgrade.java | 77 +++ .../trader/upgrades/SharpnessTeamUpgrade.java | 77 +++ .../engine/trader/upgrades/TeamUpgrade.java | 13 + .../engine/trader/upgrades/TeamUpgrades.java | 22 + 53 files changed, 5351 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/me/topchetoeu/bedwars/Commands.java create mode 100644 src/main/java/me/topchetoeu/bedwars/InventoryUtility.java create mode 100644 src/main/java/me/topchetoeu/bedwars/Main.java create mode 100644 src/main/java/me/topchetoeu/bedwars/Utility.java create mode 100644 src/main/java/me/topchetoeu/bedwars/commandUtility/Command.java create mode 100644 src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutor.java create mode 100644 src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutors.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/BedwarsPlayer.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/Config.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/DeathMessage.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/Game.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/Generator.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/GeneratorLabel.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/HoverLabel.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/SavedBlock.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/ScoreboardManager.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/Team.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/TeamColor.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/WoodenSword.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/Deal.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/DealPtr.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/DealType.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/DealTypes.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/Favourites.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/Section.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/Sections.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/TraderGUI.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/Traders.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDeal.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDealType.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDeal.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDealType.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Price.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Rank.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTier.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierApplier.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierItemApplier.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDeal.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDealType.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDeal.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDealType.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRank.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRanks.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/BlindnessTeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/EfficiencyTeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/FatigueTeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/HealTeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/ProtectionTeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/SharpnessTeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrade.java create mode 100644 src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrades.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e62d94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +deps +target +.vscode \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..07eb485 --- /dev/null +++ b/pom.xml @@ -0,0 +1,77 @@ + + + + 4.0.0 + + me.topchetoeu.bedwars + bedwars-plugin + 0.7.0 + + Bedwars Plugin + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.11 + test + + + org.bukkit + bukkit + 1.0 + system + ${basedir}/deps/bukkit.jar + + + + + + + + maven-clean-plugin + 3.1.0 + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/src/main/java/me/topchetoeu/bedwars/Commands.java b/src/main/java/me/topchetoeu/bedwars/Commands.java new file mode 100644 index 0000000..fbc8526 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/Commands.java @@ -0,0 +1,294 @@ +package me.topchetoeu.bedwars; + +import java.io.File; +import java.util.ArrayList; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import me.topchetoeu.bedwars.commandUtility.Command; +import me.topchetoeu.bedwars.commandUtility.CommandExecutor; +import me.topchetoeu.bedwars.commandUtility.CommandExecutors; +import me.topchetoeu.bedwars.engine.BedwarsPlayer; +import me.topchetoeu.bedwars.engine.Config; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.Team; +import me.topchetoeu.bedwars.engine.TeamColor; + +public class Commands { + private static File confFile = new File(Main.getInstance().getDataFolder(), "config.yml"); + + @SuppressWarnings("deprecation") + public static CommandExecutor kill = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (Game.isStarted()) { + for (String arg : args) { + OfflinePlayer p = Bukkit.getOfflinePlayer(arg); + + if (p != null) { + BedwarsPlayer bwp = Game.instance.getPlayer(p); + + if (bwp != null) { + bwp.kill(bwp.getPlayer().getName() + " definitely died with no admin intervention."); + } + else sender.sendMessage("Player is not in game!"); + } + else sender.sendMessage("Player doesn't exist!"); + } + } + else sender.sendMessage("The game isn't started yet"); + }; + @SuppressWarnings("deprecation") + public static CommandExecutor revive = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (Game.isStarted()) { + for (String arg : args) { + OfflinePlayer p = Bukkit.getOfflinePlayer(arg); + + if (p != null) { + BedwarsPlayer bwp = Game.instance.getPlayer(p); + + if (bwp != null) { + bwp.revive(); + Bukkit.broadcastMessage("Player " + p.getName() + " revived!"); + } + else sender.sendMessage("Player is not in game!"); + } + else sender.sendMessage("Player doesn't exist!"); + } + } + else sender.sendMessage("The game isn't started yet"); + }; + + public static CommandExecutor start = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length == 0) { + if (!Game.isStarted()) { + Game.start(); + sender.sendMessage("Started the game!"); + } + else sender.sendMessage("The game is already started"); + } + else sender.sendMessage("Invalid command syntax. No parameters required!"); + }; + public static CommandExecutor stop = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length == 0) { + if (Game.isStarted()) { + Game.stop(); + } + else sender.sendMessage("The game is not started"); + } + else sender.sendMessage("Invalid command syntax. No parameters required!"); + }; + + public static CommandExecutor baseAdd = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length == 3 && args[2].length() == 1) { + if (!Game.isStarted()) { + if (Utility.isParsable(args[1])) { + String name = args[0]; + int woolId = Integer.parseInt(args[1]); + char chatId = args[2].charAt(0); + + if (woolId >= 0 && woolId < 16) { + if (Config.instance.getColor(name.toLowerCase()) == null) { + Config.instance.getColors().add(new TeamColor(name.toLowerCase(), woolId, chatId)); + Config.instance.save(confFile); + sender.sendMessage("New base was created!"); + } + else sender.sendMessage("Base with this name already exists!"); + } + else sender.sendMessage("woolId must be a valid number between 0 and 15!"); + } else sender.sendMessage("woolId must be a valid number between 0 and 15!"); + } + else sender.sendMessage("Can't make modifications to the map while a game is ongoing!"); + } + else sender.sendMessage("Invalid command syntax. Syntax: /bw conf base new "); + }; + + public static CommandExecutor baseRemove = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length == 1) { + TeamColor color = Config.instance.getColor(args[0]); + if (color != null) { + Config.instance.getColors().remove(color); + Config.instance.save(confFile); + sender.sendMessage("Base removed!"); + } + else sender.sendMessage("Base doesn't exist!"); + } + else sender.sendMessage("Invalid syntax! Syntax: /bw conf base del "); + }; + public static CommandExecutor baseSetSpawn = (CommandSender sender, Command cmd, String alias, String[] args) -> { + boolean aligned = args.length == 2 && args[1].equals("aligned"); + + if (args.length == 1 || aligned) { + if (sender instanceof Player) { + Player p = (Player)sender; + + TeamColor color = Config.instance.getColor(args[0]); + if (color != null) { + Location loc = p.getLocation(); + if (aligned) { + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + } + color.setSpawnLocation(loc); + Config.instance.save(confFile); + sender.sendMessage("Base spawn set to your current location"); + } + else sender.sendMessage("Base doesn't exist!"); + + } + else sender.sendMessage("This commands is for players only!"); + } + else sender.sendMessage("Invalid syntax! Syntax: /bw conf base spawn [aligned]"); + }; + public static CommandExecutor baseSetGenerator = (CommandSender sender, Command cmd, String alias, String[] args) -> { + boolean aligned = args.length == 2 && args[1].equals("aligned"); + + if (args.length == 1 || aligned) { + if (sender instanceof Player) { + Player p = (Player)sender; + + TeamColor color = Config.instance.getColor(args[0]); + if (color != null) { + Location loc = p.getLocation(); + if (aligned) { + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + } + color.setGeneratorLocation(loc); + Config.instance.save(confFile); + sender.sendMessage("Base generator set to your current location"); + } + else sender.sendMessage("Base doesn't exist!"); + + } + else sender.sendMessage("This commands is for players only!"); + } + else sender.sendMessage("Invalid syntax! Syntax: /bw conf base gen [aligned]"); + }; + public static CommandExecutor baseSetBed = (CommandSender sender, Command cmd, String alias, String[] args) -> { + boolean aligned = args.length == 2 && args[1].equals("aligned"); + + if (args.length == 1 || aligned) { + if (sender instanceof Player) { + Player p = (Player)sender; + + TeamColor color = Config.instance.getColor(args[0]); + if (color != null) { + Location loc = p.getLocation(); + if (aligned) { + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + } + color.setBedLocation(loc); + Config.instance.save(confFile); + sender.sendMessage("Base bed set to your current location"); + } + else sender.sendMessage("Base doesn't exist!"); + + } + else sender.sendMessage("This commands is for players only!"); + } + else sender.sendMessage("Invalid syntax! Syntax: /bw conf base bed [aligned]"); + }; + public static CommandExecutor baseList = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length == 0) { + ArrayList colors = Config.instance.getColors(); + + if (colors.size() != 0) { + sender.sendMessage("Bases:"); + for (TeamColor color : colors) { + sender.sendMessage("§" + color.getColorId() + color.getName() + "§r" + ( + color.isFullySpecified() ? "" : " (not fully specified)" + )); + } + } + else sender.sendMessage("No bases found."); + } + else sender.sendMessage("Invalid syntax! No parameters required"); + }; + + public static CommandExecutor breakBed = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (!Game.isStarted()) { + sender.sendMessage("§4A game hasn't been started yet."); + return; + } + + ArrayList teams = new ArrayList<>(); + + for (String arg : args) { + TeamColor color = Config.instance.getColor(arg); + + if (color == null) { + sender.sendMessage(String.format("§4The team color §l§4%s§r§4 doesn't exist.", arg)); + return; + } + + Team team = Game.instance.getTeam(color); + + if (team == null) { + sender.sendMessage(String.format("§6The team color §l§4%s§r§4 isn't in the game.", arg)); + } + + teams.add(team); + } + + for (Team team : teams) { + if (!team.destroyBed(null)) + sender.sendMessage(String.format("§4The %s's bed is already destroyed.", team.getTeamColor().getName())); + + } + }; + + public static CommandExecutor createDiamondGen = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length > 1) { + sender.sendMessage("§4Invalid syntax!§r Syntax: /bw config gen diamond [aligned]"); + return; + } + + boolean aligned = args.length == 1 && args[0] == "aligned"; + + if (sender instanceof Player) { + Player p = (Player)sender; + + Location loc = p.getLocation(); + if (aligned) { + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + } + + Config.instance.getDiamondGenerators().add(loc); + Config.instance.save(confFile); + + p.sendMessage("§aGenerator added!"); + } + else sender.sendMessage("§4Only a player may execute this command."); + }; + public static CommandExecutor createEmeraldGen = (CommandSender sender, Command cmd, String alias, String[] args) -> { + if (args.length > 1) { + sender.sendMessage("§4Invalid syntax!§r Syntax: /bw config gen emerald [aligned]"); + return; + } + + boolean aligned = args.length == 1 && args[0] == "aligned"; + + if (sender instanceof Player) { + Player p = (Player)sender; + + Location loc = p.getLocation(); + if (aligned) { + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + } + + Config.instance.getEmeraldGenerators().add(loc); + Config.instance.save(confFile); + + p.sendMessage("§aGenerator added!"); + } + else sender.sendMessage("§4Only a player may execute this command."); + }; + + public static CommandExecutor _default = CommandExecutors.message("For help do /bw help"); +} diff --git a/src/main/java/me/topchetoeu/bedwars/InventoryUtility.java b/src/main/java/me/topchetoeu/bedwars/InventoryUtility.java new file mode 100644 index 0000000..e096ef3 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/InventoryUtility.java @@ -0,0 +1,93 @@ +package me.topchetoeu.bedwars; + +import org.bukkit.inventory.ItemStack; + +public class InventoryUtility { + public static boolean itemEquals(ItemStack a, ItemStack b, boolean ignoreAmount) { + if (a == null && b == null) return true; + if (a == null || b == null) return false; + + if (ignoreAmount) { + a = a.clone(); + a.setAmount(1); + b = b.clone(); + b.setAmount(1); + + return a.equals(b); + } + else return a.equals(b); + } + public static ItemStack giveItem(ItemStack[] inv, ItemStack _item) { + ItemStack item = _item.clone(); + int remaining = item.getAmount(); + int maxStackSize = item.getMaxStackSize(); + + for (int i = 0; i < 36; i++) { + if (itemEquals(inv[i], item, true)) { + if (inv[i].getAmount() < maxStackSize) { + int newCount = remaining + inv[i].getAmount(); + if (newCount > maxStackSize) { + inv[i].setAmount(maxStackSize); + remaining = newCount - maxStackSize; + } + else { + inv[i].setAmount(newCount); + return null; + } + } + } + } + + item.setAmount(remaining); + + for (int i = 0; i < 36; i++) { + if (inv[i] == null) { + inv[i] = item; + return null; + } + } + + return item; + } + public static boolean hasItem(ItemStack[] inv, ItemStack item) { + int n = 0; + + for (int i = 0; i < inv.length; i++) { + if (inv[i] != null) { + if (itemEquals(inv[i], (item), true)) { + n += inv[i].getAmount(); + if (n >= item.getAmount()) { + return true; + } + } + } + } + + return false; + } + public static ItemStack takeItems(ItemStack[] inv, ItemStack item) { + item = item.clone(); + + for (int i = 0; i < inv.length; i++) { + if (inv[i] != null) { + if (itemEquals(inv[i], (item), true)) { + int amount = inv[i].getAmount(); + if (item.getAmount() > amount) { + item.setAmount(item.getAmount() - amount); + inv[i] = null; + } + else if (item.getAmount() == amount) { + inv[i] = null; + return null; + } + else if (item.getAmount() < amount) { + inv[i].setAmount(inv[i].getAmount() - item.getAmount()); + return null; + } + } + } + } + + return item; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/Main.java b/src/main/java/me/topchetoeu/bedwars/Main.java new file mode 100644 index 0000000..643ac9d --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/Main.java @@ -0,0 +1,315 @@ +package me.topchetoeu.bedwars; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.logging.Level; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import me.topchetoeu.bedwars.commandUtility.Command; +import me.topchetoeu.bedwars.commandUtility.CommandExecutors; +import me.topchetoeu.bedwars.engine.Config; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.trader.Favourites; +import me.topchetoeu.bedwars.engine.trader.Sections; +import me.topchetoeu.bedwars.engine.trader.Traders; +import me.topchetoeu.bedwars.engine.trader.dealTypes.EnforcedRankedDealType; +import me.topchetoeu.bedwars.engine.trader.dealTypes.ItemDealType; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedDealType; +import me.topchetoeu.bedwars.engine.trader.dealTypes.TeamUpgradeRanks; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedUpgradeDealType; +import me.topchetoeu.bedwars.engine.trader.upgrades.BlindnessTeamUpgrade; +import me.topchetoeu.bedwars.engine.trader.upgrades.EfficiencyTeamUpgrade; +import me.topchetoeu.bedwars.engine.trader.upgrades.FatigueTeamUpgrade; +import me.topchetoeu.bedwars.engine.trader.upgrades.HealTeamUpgrade; +import me.topchetoeu.bedwars.engine.trader.upgrades.ProtectionTeamUpgrade; +import me.topchetoeu.bedwars.engine.trader.upgrades.SharpnessTeamUpgrade; + +// TODO add permissions + +public class Main extends JavaPlugin implements Listener { + + + private static Main instance; + private int playerCount; + public static Main getInstance() { + return instance; + } + + private File confFile = new File(getDataFolder(), "config.yml"); + private int getGameSize() { + return Config.instance.getTeamSize() * Config.instance.getColors().size(); + } + + int timer = 0; + BukkitTask timerTask = null; + + private void stopTimer() { + if (timerTask == null) return; + Utility.broadcastTitle("Not enough players!", null, 10, 40, 5); + timerTask.cancel(); + timerTask = null; + } + private void startTimer() { + if (timerTask != null) return; + + timerTask = Bukkit.getScheduler().runTaskTimer(this, () -> { + if (Game.isStarted()) { + stopTimer(); + return; + } + if (timer % 30 == 0 || timer == 15 || timer == 10) + Utility.broadcastTitle("Starting in " + timer + " seconds!", null, 10, 40, 5); + else if (timer <= 5) + Utility.broadcastTitle("Starting in " + timer + " seconds!", null, 0, 20, 0); + timer--; + if (timer <= 0) { + Game.start(); + timerTask.cancel(); + timerTask = null; + } + }, 0, 20); + } + public void updateTimer() { + // TODO make timing configurable + if (!Game.isStarted()) { + if (playerCount <= 1 || playerCount <= getGameSize() / 4) { + Utility.broadcastTitle("Not enough players", "Waiting for more...", 0, 100, 0); + stopTimer(); + } + else if (playerCount <= getGameSize() / 2) { + timer = 60; + startTimer(); + } + else if (playerCount <= getGameSize() - 1) { + timer = 60; + startTimer(); + } + else { + timer = 15; + startTimer(); + } + } + } + + @EventHandler + private void onJoin(PlayerJoinEvent e) { + playerCount++; + e.getPlayer().setGameMode(GameMode.SPECTATOR); + updateTimer(); + } + @EventHandler + private void onLeave(PlayerQuitEvent e) { + playerCount--; + updateTimer(); + } + + @EventHandler + private void onFoodLost(FoodLevelChangeEvent e) { + e.setCancelled(true); + } + + @SuppressWarnings("deprecation") + @Override + public void onEnable() { + playerCount = Bukkit.getServer().getOnlinePlayers().size(); + try { + instance = this; + getDataFolder().mkdir(); + File conf = new File(getDataFolder(), "config.yml"); + if (!conf.exists()) + try { + YamlConfiguration.loadConfiguration( + getClass() + .getClassLoader() + .getResourceAsStream("config.yml") + ).save(confFile); + } + catch (IOException e) { /* Everything is fine */ } + + // Deprecation warnings are for beginners + Config.load(conf); + File defaultFavs = new File(getDataFolder(), "default-favourites.yml"); + + if (!defaultFavs.exists()) { + try { + OutputStream w = new FileOutputStream(defaultFavs); + InputStream r = getClass() + .getClassLoader() + .getResourceAsStream("default-favourites.yml"); + + w.write(r.readAllBytes()); + + w.close(); + r.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + File favsDir = new File(getDataFolder(), "favourites"); + + try { + Traders.instance = new Traders(new File(getDataFolder(), "traders.txt")); + } catch (IOException e) { + e.printStackTrace(); + } + + YamlConfiguration sectionsConf = YamlConfiguration.loadConfiguration(new File(getDataFolder(), "sections.yml")); + + BlindnessTeamUpgrade.init(this); + FatigueTeamUpgrade.init(this); + HealTeamUpgrade.init(this); + EfficiencyTeamUpgrade.init(); + ProtectionTeamUpgrade.init(); + SharpnessTeamUpgrade.init(); + TeamUpgradeRanks.init(this, sectionsConf); + + ItemDealType.init(); + RankedDealType.init(this, sectionsConf); + EnforcedRankedDealType.init(); + RankedUpgradeDealType.init(); + Sections.init(new File(getDataFolder(), "sections.yml")); + Favourites.instance = new Favourites(favsDir, defaultFavs); + + updateTimer(); + + getServer().getWorlds().get(0).getEntitiesByClass(Villager.class).forEach(v -> { + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) v).getHandle(); + nmsEntity.b(true); // Disables its AI + }); + + Command cmd = new Command("bedwars", "bw").setExecutor(Commands._default); + cmd + .attachCommand(new Command("help") + .setExecutor(CommandExecutors.help(cmd)) + .setHelpMessage("Shows help for the command") + ) + .attachCommand(new Command("start") + .setExecutor(Commands.start) + .setHelpMessage("Starts the game") + ) + .attachCommand(new Command("stop") + .setExecutor(Commands.stop) + .setHelpMessage("Stops the game, noone wins") + ) + .attachCommand(new Command("respawn", "revive") + .setExecutor(Commands.revive) + .setHelpMessage("Respawns a spectator, if he has a bed, he is immediatly respawned")) + .attachCommand(new Command("breakbed", "eliminateteam") + .setExecutor(Commands.breakBed) + .setHelpMessage("Destoys the bed of a team") + ) + .attachCommand(new Command("eliminate") + .setHelpMessage("Eliminates a player") + ) + .attachCommand(new Command("kill") + .setExecutor(Commands.kill) + .setHelpMessage("Kills a player") + ) + .attachCommand(new Command("killteam") + .setHelpMessage("Kills all players of a team") + ) + .attachCommand(new Command("villagertools", "villager", "trader") + .setExecutor((sender, _cmd, alias, args) -> { + if (args.length == 0) { + if (sender instanceof Player) { + Player p = (Player)sender; + + p.getInventory().addItem(Utility.namedItem(new ItemStack(Material.MONSTER_EGG), "§rTrader spawner")); + p.getInventory().addItem(Utility.namedItem(new ItemStack(Material.STICK), "§rTrader eradicator")); + } + } + }) + .setHelpMessage("Gives you tools to manage traders") + ) + .attachCommand(new Command("config", "conf", "settings") + .setExecutor(Commands._default) + .setHelpMessage("Command for configuring the map") + .attachCommand(new Command("spawn") + .setHelpMessage("Sets the spawn at which the platform is going to be spawned, and where spectators are going to be spawned") + ) + .attachCommand(new Command("base", "b") + .setExecutor(Commands._default) + .setHelpMessage("Command for configuring separate bases") + .attachCommand(new Command("new", "add", "create", "c") + .setExecutor(Commands.baseAdd) + .setHelpMessage("Creates a base with a color, chat id and a wool id. NOTE: for chat id, do the following: if in chat the color you want is &2, specify just '2'") + ) + .attachCommand(new Command("remove", "delete", "del", "d") + .setExecutor(Commands.baseRemove) + .setHelpMessage("Removes a base with the selected name") + ) + .attachCommand(new Command("setbed", "bed", "b") + .setExecutor(Commands.baseSetBed) + .setHelpMessage("Sets the location of the bed. Any broken bed within 5 blocks of the specified location will trigger the breaking of the team's bed") + ) + .attachCommand(new Command("setgenerator", "generator", "setgen", "gen", "g") + .setExecutor(Commands.baseSetGenerator) + .setHelpMessage("Sets the location of the generator. Anyone within 2 blocks of it will pick up the produced items") + ) + .attachCommand(new Command("setspawn", "spawn", "s") + .setExecutor(Commands.baseSetSpawn) + .setHelpMessage("Sets the location where players of the team will respawn") + ) + .attachCommand(new Command("list", "l") + .setExecutor(Commands.baseList) + .setHelpMessage("Lists all bases") + ) + ) + .attachCommand(new Command("generator", "gen", "g") + .setExecutor(Commands._default) + .setHelpMessage("Command for configuring the global generators") + .attachCommand(new Command("diamond", "d") + .setExecutor(Commands.createDiamondGen) + .setHelpMessage("Creates a diamond generator in (approximately) your position") + ) + .attachCommand(new Command("emerald", "e") + .setExecutor(Commands.createEmeraldGen) + .setHelpMessage("Creates a emerald generator in (approximately) your position") + ) + .attachCommand(new Command("remove", "delete", "del", "r") + .setHelpMessage("Deletes all generators within 5 block of your position") + ) + ) + ) + .attachCommand(new Command("diemydarling") + .setExecutor((a, b, c, d) -> { + Bukkit.getWorld("world") + .getEntities() + .stream() + .filter(v -> v instanceof ArmorStand) + .forEach(v -> v.remove()); + }) + ) + .register(this); + + getServer().getPluginManager().registerEvents(this, this); + } + catch (Throwable t) { + getLogger().log(Level.SEVERE, "Failed to initialize. Config files are probably to blame", t); + getServer().broadcastMessage("§4The bedwars plugin failed to initialize. Many, if not all parts of the plugin won't work. Check console for details and stack trace."); + } + } + public void onDisable() { + if (Game.isStarted()) Game.instance.close(); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/Utility.java b/src/main/java/me/topchetoeu/bedwars/Utility.java new file mode 100644 index 0000000..417917f --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/Utility.java @@ -0,0 +1,178 @@ +package me.topchetoeu.bedwars; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; + +import net.minecraft.server.v1_8_R3.ChatComponentText; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.IChatBaseComponent; +import net.minecraft.server.v1_8_R3.PacketPlayOutTitle; +import net.minecraft.server.v1_8_R3.PacketPlayOutTitle.EnumTitleAction; + +public class Utility { + + private static IChatBaseComponent getText(String text) { + return new ChatComponentText(text); + } + + public static void sendTitle(Player p, String title, String subtitle, int fadein, int duration, int fadeout) { + EntityPlayer handle = ((CraftPlayer)p).getHandle(); + + handle.playerConnection.sendPacket(new PacketPlayOutTitle( + EnumTitleAction.TIMES, null, fadein, duration, fadeout + )); + if (subtitle == null) { + subtitle = ""; + } + if (title == null) { + title = ""; + } + handle.playerConnection.sendPacket(new PacketPlayOutTitle( + EnumTitleAction.SUBTITLE, getText(subtitle) + )); + handle.playerConnection.sendPacket(new PacketPlayOutTitle( + EnumTitleAction.TITLE, getText(title) + )); + } + public static void broadcastTitle(String title, String subtitle, int fadein, int duration, int fadeout) { + Bukkit.getOnlinePlayers().forEach(v -> sendTitle(v, title, subtitle, fadein, duration, fadeout)); + } + public static boolean isParsable(String val) { + try { + Integer.parseInt(val); + } catch (NumberFormatException e) { + return false; + } + + return true; + } + + public static ItemStack namedItem(ItemStack i, String name) { + ItemMeta meta = i.getItemMeta(); + meta.setDisplayName(name); + i.setItemMeta(meta); + return i; + } + public static ItemStack copyNamedItem(ItemStack i, String name) { + i = new ItemStack(i); + ItemMeta meta = i.getItemMeta(); + meta.setDisplayName(name); + i.setItemMeta(meta); + return i; + } + public static String getItemName(Material item) { + net.minecraft.server.v1_8_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(new ItemStack(item)); + return nmsStack.getItem().a(nmsStack); + } + public static String getItemName(ItemStack item) { + if (item.getItemMeta().hasDisplayName()) return item.getItemMeta().getDisplayName(); + net.minecraft.server.v1_8_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(item); + return nmsStack.getItem().a(nmsStack); + } + + @SuppressWarnings("unchecked") + public static ItemStack deserializeItemStack(Map map) { + String id = ((String)map.get("id")).toUpperCase(); + int amount = map.containsKey("amount") ? (Integer)map.get("amount") : 1; + short damage = (short)(map.containsKey("damage") ? (Integer)map.get("damage") : 0); + + ItemStack item = new ItemStack(Material.getMaterial(id), amount, damage); + + ItemMeta meta = item.getItemMeta(); + if (map.containsKey("displayName")) meta.setDisplayName((String)map.get("displayName")); + + if (map.containsKey("lore")) meta.setLore((ArrayList)map.get("lore")); + + if (map.containsKey("enchants")) { + for(Entry entry : ((Map)map.get("enchants")).entrySet()) { + Enchantment e = Enchantment.getByName(entry.getKey().toUpperCase()); + + meta.addEnchant(e, entry.getValue(), true); + } + } + if (map.containsKey("potion")) { + Map potionMap = (Map)map.get("potion"); + String name = (String)potionMap.get("id"); + int level = (Integer)potionMap.get("level"); + int duration = (Integer)potionMap.get("duration"); + boolean splash = potionMap.containsKey("splash") && (boolean)potionMap.get("splash"); + + PotionEffectType effectType = PotionEffectType.getByName(name.toUpperCase()); + + PotionMeta potionMeta = (PotionMeta)meta; + potionMeta.addCustomEffect(new PotionEffect( + effectType, + duration, level, false + ), false); + + Potion pot = new Potion(PotionType.getByEffect(effectType), 1); + if (splash) pot = pot.splash(); + pot.apply(item); + + meta = potionMeta; + } + + item.setItemMeta(meta); + + return item; + } + public static Map mapifyConfig(ConfigurationSection config) { + Map map = config.getValues(false); + for (String key : map.keySet()) { + Object val = map.get(key); + if (val instanceof ConfigurationSection) { + map.put(key, mapifyConfig((ConfigurationSection)val)); + } + } + + return map; + } + + public static Optional getPotionEffect(Collection p, PotionEffectType type) { + return p.stream().filter(v -> v.getType().equals(type)).findFirst(); + } + public static Optional getPotionEffect(LivingEntity p, PotionEffectType type) { + return getPotionEffect(p.getActivePotionEffects(), type); + } + + public static void applyPotionEffect(LivingEntity p, PotionEffect e) { + PotionEffect eff = getPotionEffect(p, e.getType()).orElse(null); + + if (eff == null) p.addPotionEffect(e); + else { + p.removePotionEffect(e.getType()); + p.addPotionEffect(e); + } + } + + @Deprecated(since = "Don't forget to remove these") + public static void debugMsg(Object obj) { + if (obj == null) obj = "null"; + Bukkit.getServer().broadcastMessage(obj.toString()); + } + @Deprecated(since = "Don't forget to remove these") + public static void debugMsg(CommandSender p, Object obj) { + if (obj == null) obj = "null"; + p.sendMessage(obj.toString()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/commandUtility/Command.java b/src/main/java/me/topchetoeu/bedwars/commandUtility/Command.java new file mode 100644 index 0000000..0a26902 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/commandUtility/Command.java @@ -0,0 +1,147 @@ +package me.topchetoeu.bedwars.commandUtility; + +import java.util.Arrays; +import java.util.HashSet; + +import org.apache.commons.lang.NullArgumentException; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; + +public class Command { + private String[] aliases; + private String name; + private String helpMessage; + private CommandExecutor fallbackExecutor; + private HashSet attachedCommands = new HashSet<>(); + + private JavaPlugin parent = null; + + public String[] getAliases() { + return aliases; + } + + public String getName() { + return name; + } + + public String getHelpMessage() { + return helpMessage; + } + public Command setHelpMessage(String val) { + helpMessage = val; + return this; + } + + public CommandExecutor getFallbackExecutor() { + return fallbackExecutor; + } + public Command setExecutor(CommandExecutor val) { + fallbackExecutor = val; + return this; + } + + public Command attachCommand(Command cmd) { + if (cmd == null) throw new NullArgumentException("cmd"); + attachedCommands.add(cmd); + return this; + } + public Command detachCommand(Command cmd) { + if (cmd == null) throw new NullArgumentException("cmd"); + attachedCommands.remove(cmd); + return this; + } + public boolean commandAttached(Command cmd) { + if (cmd == null) return false; + return attachedCommands.contains(cmd); + } + public Command[] getAttachedCommands() { + return attachedCommands.toArray(Command[]::new); + } + + public void execute(CommandSender sender, String alias, String[] args) { + Command cmd; + if (args.length == 0) cmd = null; + else cmd = getAttachedCommand(args[0]); + + String[] newArgs; + if (args.length <= 1) newArgs = new String[0]; + else { + newArgs = new String[args.length - 1]; + System.arraycopy(args, 1, newArgs, 0, args.length - 1); + } + + if (cmd != null) + cmd.execute(sender, args[0], newArgs); + else if (fallbackExecutor != null) fallbackExecutor.execute( + sender, this, + alias, args + ); + else sender.sendMessage("This command doesn't do anything :("); + } + + public Command register(JavaPlugin pl) { + if (pl == parent) throw new IllegalArgumentException("The command is already attached to the given plugin"); + if (pl == null) throw new NullArgumentException("pl"); + parent = pl; + pl.getCommand(name).setAliases(Arrays.asList(aliases)); + pl.getCommand(name).setExecutor(new org.bukkit.command.CommandExecutor() { + + @Override + public boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String alias, String[] args) { + execute(sender, alias, args); + return true; + } + }); + + return this; + } + + public Command getAttachedCommand(String alias) { + String newAlias = alias.toLowerCase(); + for (Command command : attachedCommands) { + if (command.name.equals(newAlias) || Arrays.stream(command.aliases).anyMatch(v -> v.equals(newAlias))) + return command; + } + return null; + } + + public Command(String name, String alias) { + this.name = name; + this.aliases = new String[] { alias }; + } + public Command(String name, String... aliases) { + this.name = name; + this.aliases = aliases; + } + public Command(String name, CommandExecutor executor, String... aliases) { + this.name = name; + this.aliases = aliases; + this.fallbackExecutor = executor; + } + public Command(String name, String alias, Command... commands) { + this.name = name; + this.aliases = new String[] { alias }; + + for (Command cmd : commands) { + attachCommand(cmd); + } + } + public Command(String name, String[] aliases, Command... commands) { + this.name = name; + this.aliases = aliases; + + for (Command cmd : commands) { + attachCommand(cmd); + } + } + public Command(String name, String[] aliases, CommandExecutor executor, Command... commands) { + this.name = name; + this.aliases = aliases; + fallbackExecutor = executor; + + for (Command cmd : commands) { + attachCommand(cmd); + } + } + +} diff --git a/src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutor.java b/src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutor.java new file mode 100644 index 0000000..7def61e --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutor.java @@ -0,0 +1,7 @@ +package me.topchetoeu.bedwars.commandUtility; + +import org.bukkit.command.CommandSender; + +public interface CommandExecutor { + void execute(CommandSender sender, Command cmd, String alias, String[] args); +} diff --git a/src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutors.java b/src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutors.java new file mode 100644 index 0000000..52563a5 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/commandUtility/CommandExecutors.java @@ -0,0 +1,62 @@ +package me.topchetoeu.bedwars.commandUtility; + +import org.bukkit.command.CommandSender; + +public class CommandExecutors { + private static String join(String[] arr, String separator) { + if (arr.length == 0) return ""; + if (arr.length == 1) return arr[0]; + + String res = arr[0]; + + for (int i = 1; i < arr.length; i++) { + res += separator + arr[i]; + } + + return res; + } + + public static CommandExecutor help(Command mainCmd) { + return new CommandExecutor() { + @Override + public void execute(CommandSender sender, Command cmd, String alias, String[] args) { + Command currCmd = mainCmd; + String path = "/" + mainCmd.getName(); + + for (String arg : args) { + currCmd = currCmd.getAttachedCommand(arg); + if (currCmd == null) { + String msg = "Help can't be provided for the command."; + sender.sendMessage(msg); + return; + } + + path += " " + currCmd.getName(); + } + + sender.sendMessage(path + ": " + (currCmd.getHelpMessage() == null ? + "no help provided" : + currCmd.getHelpMessage()) + ); + if (currCmd.getAliases().length != 0) + sender.sendMessage("Aliases: " + join(currCmd.getAliases(), ", ")); + + if (currCmd.getAttachedCommands().length > 0) { + sender.sendMessage("Commands: "); + for (Command subCmd : currCmd.getAttachedCommands()) { + sender.sendMessage(path + " " + subCmd.getName() + ": " + subCmd.getHelpMessage()); + } + } + } + }; + } + public static CommandExecutor message(String msg) { + return new CommandExecutor() { + + @Override + public void execute(CommandSender sender, Command cmd, String alias, String[] args) { + sender.sendMessage(msg); + } + }; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/BedwarsPlayer.java b/src/main/java/me/topchetoeu/bedwars/engine/BedwarsPlayer.java new file mode 100644 index 0000000..71eb473 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/BedwarsPlayer.java @@ -0,0 +1,493 @@ + package me.topchetoeu.bedwars.engine; + +import java.util.Map; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; + +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedDealType; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityEquipment; + +import org.bukkit.entity.Explosive; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitTask; + +import me.topchetoeu.bedwars.InventoryUtility; +import me.topchetoeu.bedwars.Main; + +public class BedwarsPlayer implements Listener, AutoCloseable { + private OfflinePlayer player; + private Team team; + private boolean dead = true; + private boolean deathPending = false; + private boolean revivalPending = false; + private boolean spectator = false; + private Map deathMessages; + private float revivalTimer = 0; + private int offenceTimer = 0; + private BukkitTask offenceTask = null; + private BukkitTask invisTask = null; + private BukkitTask reviveTask = null; + + private int kills; + private int finalKills; + private int beds; + private int deaths; + private boolean invisible = false; + + private OfflinePlayer offender = null; + + private void updateInvisibility(Player p) { + net.minecraft.server.v1_8_R3.ItemStack helmetItem = CraftItemStack.asNMSCopy(getOnlinePlayer().getInventory().getHelmet()); + net.minecraft.server.v1_8_R3.ItemStack chestplateItem = CraftItemStack.asNMSCopy(getOnlinePlayer().getInventory().getChestplate()); + net.minecraft.server.v1_8_R3.ItemStack leggingsItem = CraftItemStack.asNMSCopy(getOnlinePlayer().getInventory().getLeggings()); + net.minecraft.server.v1_8_R3.ItemStack bootsItem = CraftItemStack.asNMSCopy(getOnlinePlayer().getInventory().getBoots()); + if (invisible) { + helmetItem = chestplateItem = leggingsItem = bootsItem = null; + } + + int id = getOnlinePlayer().getEntityId(); + PacketPlayOutEntityEquipment helmet = new PacketPlayOutEntityEquipment(id, 1, helmetItem); + PacketPlayOutEntityEquipment chestplate = new PacketPlayOutEntityEquipment(id, 2, chestplateItem); + PacketPlayOutEntityEquipment leggings = new PacketPlayOutEntityEquipment(id, 3, leggingsItem); + PacketPlayOutEntityEquipment boots = new PacketPlayOutEntityEquipment(id, 4, bootsItem); + + EntityPlayer handle = ((CraftPlayer)p).getHandle(); + + handle.playerConnection.sendPacket(helmet); + handle.playerConnection.sendPacket(chestplate); + handle.playerConnection.sendPacket(leggings); + handle.playerConnection.sendPacket(boots); + } + + private void updateInvisiblity() { + for (Player player : Bukkit.getOnlinePlayers()) { + if (Game.inGame(player) && !team.hasPlayer(player)) { + updateInvisibility(player); + } + } + } + private void removeInvis() { + invisible = false; + updateInvisiblity(); + if (isOnline()) getOnlinePlayer().removePotionEffect(PotionEffectType.INVISIBILITY); + if (invisTask != null) { + invisTask.cancel(); + invisTask = null; + } + } + + public OfflinePlayer getPlayer() { + return player; + } + public Player getOnlinePlayer() { + if (player.isOnline()) return player.getPlayer(); + else return null; + } + public Team getTeam() { + return team; + } + + public boolean isDead() { + return dead; + } + public boolean isSpectator() { + return spectator; + } + public boolean isOnline() { + return player.isOnline(); + } + + public int getRegularKills() { + return kills; + } + public int getFinalKills() { + return finalKills; + } + public int getKills() { + return kills + finalKills; + } + public int getBeds() { + return beds; + } + public int getDeaths() { + return deaths; + } + + + public float getRevivalTimer() { + return revivalTimer; + } + public float increaseRevivalTimer(float amount) { + return revivalTimer += amount; + } + public void resetRevivalTimer() { + revivalTimer = 0; + } + public void kill(String deathMsg) { + if (dead) return; + if (player.isOnline()) { + Bukkit.getServer().broadcastMessage(deathMsg); + BedwarsPlayer bwOffender = null; + if (offender != null && Game.isStarted() && Game.instance.isPlaying(offender)) { + bwOffender = Game.instance.getPlayer(offender); + if (offender.isOnline()) { + Player p = offender.getPlayer(); + + ItemStack[] inv = p.getInventory().getContents(); + + getOnlinePlayer().getInventory().forEach(i -> { + if (i != null) { + if (i.getType() == Material.IRON_INGOT || + i.getType() == Material.GOLD_INGOT || + i.getType() == Material.EMERALD || + i.getType() == Material.DIAMOND) { + InventoryUtility.giveItem(inv, i); + } + } + }); + + p.getInventory().setContents(inv); + p.updateInventory(); + } + } + + for(PotionEffect effect : getOnlinePlayer().getActivePotionEffects()) + { + getOnlinePlayer().removePotionEffect(effect.getType()); + } + + if (team.hasBed()) { + dead = true; + removeInvis(); + getOnlinePlayer().setGameMode(GameMode.SPECTATOR); + getOnlinePlayer().setHealth(20); + RankedDealType.getDefinedRanks().values().forEach((v) -> { + v.onDeath(getOnlinePlayer()); + }); + + revivalTimer = 5; + + reviveTask = Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> { + if (!player.isOnline()) { + dead = false; + revivalTimer = 0; + deathPending = true; + reviveTask.cancel(); + reviveTask = null; + } + Utility.sendTitle(player.getPlayer(), + "You died!", + String.format("Respawning in %.2f", revivalTimer), + 0, 4, 5 + ); + revivalTimer -= 0.1; + if (revivalTimer <= 0) { + revive(); + } + }, 0, 2); + + offender = null; + + if (bwOffender != null) bwOffender.kills++; + } + else { + eliminate(); + if (bwOffender != null) bwOffender.finalKills++; + } + ScoreboardManager.updateAll(); + } + else deathPending = true; + } + public void revive() { + if (!dead) return; + + dead = false; + spectator = false; + if (reviveTask != null) { + reviveTask.cancel(); + reviveTask = null; + revivalTimer = 0; + } + if (player.isOnline()) { + player.getPlayer().setGameMode(GameMode.SURVIVAL); + player.getPlayer().teleport(team.getTeamColor().getSpawnLocation()); + player.getPlayer().getInventory().clear(); + player.getPlayer().setHealth(20); + WoodenSword.update(this, player.getPlayer().getInventory()); + RankedDealType.getDefinedRanks().values().forEach((v) -> { + v.refreshInv(getOnlinePlayer()); + }); + + RankedDealType.refreshPlayer(getOnlinePlayer()); + } + else revivalPending = true; + } + @SuppressWarnings("deprecation") + public void eliminate() { + if (spectator) return; + if (!dead) { + // TODO make some more spectator features + player.getPlayer().setGameMode(GameMode.SPECTATOR); + player.getPlayer().setHealth(20); + dead = true; + } + Bukkit.getServer().broadcastMessage(String.format("%s was eliminated.", player.getName())); + + if (team.decreaseRemainingPlayers() > 0) { + // TODO fix these messages + // Also, this deprecation is just fine :) + player.getPlayer().sendTitle("You are dead", "You can only spectate your more intelligent friends"); + } + else + Bukkit.getServer().broadcastMessage(String.format("Team %s was eliminated.", team.getTeamColor().getName())); + if (team.getPlayersCount() == 1) { + player.getPlayer().sendTitle("You were eliminated!", "Now you can spectate"); + } + else + player.getPlayer().sendTitle("Your team was eliminated", "Your team fucked up bad time :("); + + spectator = true; + } + public void close() { + if (reviveTask != null) { + reviveTask.cancel(); + } + + offenceTask.cancel(); + + if (isOnline()) { + for(PotionEffect effect : getOnlinePlayer().getActivePotionEffects()) { + getOnlinePlayer().removePotionEffect(effect.getType()); + } + getOnlinePlayer().setGameMode(GameMode.SPECTATOR); + getOnlinePlayer().getInventory().clear(); + getOnlinePlayer().getEnderChest().clear(); + } + + HandlerList.unregisterAll(this); + + offenceTask = null; + reviveTask = null; + team = null; + player = null; + deathMessages = null; + } + + @EventHandler + private void onLogout(PlayerQuitEvent e) { + if (equals(e.getPlayer())) { + if (!team.hasBed() ) { + eliminate(); + } + else if (!dead) deathPending = true; + } + } + @EventHandler + private void onLogin(PlayerJoinEvent e) { + if (e.getPlayer().getUniqueId().equals(player.getUniqueId())) { + player = e.getPlayer(); + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getInstance(), () -> { + if (deathPending) { + if (!revivalPending) kill(DeathMessage.getMsg(player, offender, deathMessages, "generic")); + else revivalPending = false; + deathPending = false; + } + if (revivalPending) { + if (!deathPending) revive(); + revivalPending = false; + } + ScoreboardManager.update(e.getPlayer()); + }, 3); + } + + updateInvisiblity(); + } + @EventHandler + private void onEntityDamageEntity(EntityDamageByEntityEvent e) { + if (e.getEntity() instanceof Player) { + Player p = (Player)e.getEntity(); + if (equals(p)) { + if (e.getDamager() instanceof Player) { + offender = (OfflinePlayer)e.getDamager(); + } + if (e.getDamager() instanceof Projectile) { + Projectile projectile = (Projectile)e.getDamager(); + if (projectile.getShooter() instanceof Player) { + OfflinePlayer shooter = (OfflinePlayer)projectile.getShooter(); + if (equals(shooter) && e.getDamager() instanceof Fireball) e.setDamage(0); + offender = shooter; + } + } + if (e.getDamager() instanceof Explosive) { + e.setDamage(e.getDamage() / 3); + if (e.getFinalDamage() >= p.getHealth()) { + e.setDamage(0); + kill(DeathMessage.getMessage(e.getCause(), player, offender, deathMessages)); + } + } + + if (offender != null) offenceTimer = 15; + } + } + } + @EventHandler + private void onDamage(EntityDamageEvent e) { + if (e.getEntity() instanceof Player) { + Player p = (Player)e.getEntity(); + if (equals(p)) { + if (e.getCause() == DamageCause.ENTITY_EXPLOSION) { + return; + } + if (e.getFinalDamage() >= p.getHealth()) { + e.setDamage(0); + kill(DeathMessage.getMessage(e.getCause(), player, offender, deathMessages)); + } + } + } + } + @EventHandler + private void onTeleport(PlayerTeleportEvent e) { + Player player = e.getPlayer(); + + if (e.getCause() == TeleportCause.ENDER_PEARL) { + e.setCancelled(true); + + player.teleport(e.getTo()); + } + } + private void onInvisExpire() { + removeInvis(); + } + + @EventHandler + private void onMove(PlayerMoveEvent e) { + if (e.getPlayer() instanceof Player) { + if (e.getPlayer().getUniqueId().equals(player.getUniqueId())) { + if (e.getTo().getY() < 40) { + e.setTo(e.getTo().add(0, 100, 0)); + e.getPlayer().playSound(e.getTo(), Sound.HURT_FLESH, 1, 1); + kill(DeathMessage.getMessage(DamageCause.VOID, player, offender, deathMessages)); + } + } + } + } + @EventHandler + private void onThrow(PlayerDropItemEvent e) { + if (equals(e.getPlayer())) { + if (e.getItemDrop().getItemStack().getType() == Material.WOOD_SWORD) e.setCancelled(true); + else WoodenSword.update(this, e.getPlayer().getInventory()); + } + } + @EventHandler + private void onPickup(PlayerPickupItemEvent e) { + if (WoodenSword.isOtherSword(e.getItem().getItemStack().getType())) + e.getPlayer().getInventory().remove(Material.WOOD_SWORD); + } + @EventHandler + private void onConsume(PlayerItemConsumeEvent e) { + if (e.getPlayer() instanceof Player) { + if (e.getPlayer().getUniqueId().equals(player.getUniqueId())) { + if (e.getItem().getItemMeta() instanceof PotionMeta) { + PotionMeta meta = (PotionMeta)e.getItem().getItemMeta(); + + meta.getCustomEffects().forEach(eff -> { + Utility.applyPotionEffect(getOnlinePlayer(), eff); + + if (eff.getType().equals(PotionEffectType.INVISIBILITY)) { + + if (invisible) { + invisTask.cancel(); + } + + invisTask = Bukkit.getScheduler().runTaskLater(Main.getInstance(), + () -> onInvisExpire(), + eff.getDuration() + ); + invisible = true; + updateInvisiblity(); + } + }); + + e.getPlayer().getInventory().setItemInHand(null); + e.setCancelled(true); + } + } + } + } + + @EventHandler + private void onInventory(InventoryClickEvent e) { + if (e.getCursor() != null && e.getCursor().getType() == Material.WOOD_SWORD) { + if (e.getClickedInventory() != e.getWhoClicked().getInventory()) e.setCancelled(true); + } + else if (e.getCurrentItem() != null && e.getCurrentItem().getType() == Material.WOOD_SWORD) { + if (e.getClick() == ClickType.SHIFT_LEFT || e.getClick() == ClickType.SHIFT_RIGHT) e.setCancelled(true); + } + } + + public OfflinePlayer getOffender() { + return offender; + } + + public BedwarsPlayer(OfflinePlayer p, Team t) { + Bukkit.getPluginManager().registerEvents(this, Main.getInstance()); + team = t; + player = p; + deathMessages = DeathMessage.getMessages(p); + offenceTask = Bukkit.getServer().getScheduler().runTaskTimer(Main.getInstance(), () -> { + if (offenceTimer > 0) { + offenceTimer--; + if (offenceTimer == 0) offender = null; + } + }, 0, 20); + + if (p.isOnline()) { + dead = true; + revive(); + } + else { + dead = false; + kill(DeathMessage.getMsg(p, null, deathMessages, "generic")); + } + } + + public boolean equals(UUID p) { + if (p == null) return false; + return player.getUniqueId().equals(p); + } + public boolean equals(OfflinePlayer p) { + if (p == null) return false; + return player.getUniqueId().equals(p.getUniqueId()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/Config.java b/src/main/java/me/topchetoeu/bedwars/engine/Config.java new file mode 100644 index 0000000..3119f07 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/Config.java @@ -0,0 +1,146 @@ +package me.topchetoeu.bedwars.engine; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.bukkit.Location; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +public class Config { + public static Config instance; + + private int perTeam = 0; + private Location respawnLocation; + private ArrayList colors; + private ArrayList diamondGenerators; + private ArrayList emeraldGenerators; + + public Location getRespawnLocation() { + return respawnLocation; + } + public void setRespawnLocation(Location loc) { + respawnLocation = loc; + } + + public int getTeamSize() { + return perTeam; + } + public void setTeamSize(int size) { + perTeam = size; + } + + public ArrayList getColors() { + return colors; + } + public TeamColor getColor(String name) { + return Config.instance.getColors() + .stream() + .filter(v -> v.getName().equals(name.toLowerCase())) + .findFirst() + .orElse(null); + } + + public ArrayList getDiamondGenerators() { + return diamondGenerators; + } + public Location getClosestDiamondGenerator(Location loc) { + if (diamondGenerators.size() == 0) return null; + Location closest = null; + double smallestDist = diamondGenerators.get(0).distance(loc); + + for (int i = 0; i < diamondGenerators.size(); i++) { + Location el = diamondGenerators.get(i); + double dist = el.distance(loc); + if (dist < smallestDist) { + closest = el; + smallestDist = dist; + } + } + + return closest; + } + public List getDiamondGeneratorsInRadius(double radius, Location loc) { + return diamondGenerators.stream() + .filter(v -> v.distance(loc) <= radius) + .collect(Collectors.toList()); + } + + public ArrayList getEmeraldGenerators() { + return emeraldGenerators; + } + public Location getClosestEmeraldGenerator(Location loc) { + if (diamondGenerators.size() == 0) return null; + Location closest = null; + double smallestDist = emeraldGenerators.get(0).distance(loc); + + for (int i = 0; i < emeraldGenerators.size(); i++) { + Location el = emeraldGenerators.get(i); + double dist = el.distance(loc); + if (dist < smallestDist) { + closest = el; + smallestDist = dist; + } + } + + return closest; + } + public List getEmeraldGeneratorsInRadius(double radius, Location loc) { + return emeraldGenerators.stream() + .filter(v -> v.distance(loc) <= radius) + .collect(Collectors.toList()); + } + + private static ArrayList toList(Stream s) { + return new ArrayList<>(s.collect(Collectors.toList())); + } + + @SuppressWarnings("unchecked") + public static void load(File confFile) { + Configuration conf = YamlConfiguration.loadConfiguration(confFile); + + Config c = new Config(); + + c.perTeam = conf.getInt("perTeam"); + if (conf.get("respawnLocation") != null) c.respawnLocation = Location.deserialize(conf.getConfigurationSection("respawnLocation").getValues(false)); + c.colors = (ArrayList)toList(conf + .getMapList("colors") + .stream() + .map(v -> TeamColor.deserialize((Map)v)) + ); + c.diamondGenerators = (ArrayList)toList(conf + .getMapList("diamondGenerators") + .stream() + .map(v -> Location.deserialize((Map)v)) + ); + c.emeraldGenerators = (ArrayList)toList(conf + .getMapList("emeraldGenerators") + .stream() + .map(v -> Location.deserialize((Map)v)) + ); + + instance = c; + } + + public void save(File confFile) { + FileConfiguration conf = YamlConfiguration.loadConfiguration(confFile); + + conf.set("perTeam", perTeam); + conf.set("colors", toList(colors.stream().map(v -> v.serialize()))); + conf.set("diamondGenerators", toList(diamondGenerators.stream().map(v -> v.serialize()))); + conf.set("emeraldGenerators", toList(emeraldGenerators.stream().map(v -> v.serialize()))); + + try { + conf.save(confFile); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/DeathMessage.java b/src/main/java/me/topchetoeu/bedwars/engine/DeathMessage.java new file mode 100644 index 0000000..0f8f89e --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/DeathMessage.java @@ -0,0 +1,68 @@ +package me.topchetoeu.bedwars.engine; + +import java.io.File; +import java.util.Map; +import java.util.stream.Collectors; + +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import me.topchetoeu.bedwars.Main; + +public class DeathMessage { + public static String getMsg(OfflinePlayer offended, OfflinePlayer offender, Map messages, String msg) { + return String.format(messages.get(msg), offended.getName(), offender == null ? "" : offender.getName()); + } + + public static String getMessage(DamageCause cause, OfflinePlayer offended, OfflinePlayer offender, Map messages) { + String name = "generic"; + + switch (cause) { + case BLOCK_EXPLOSION: + case ENTITY_EXPLOSION: + name = "explosion"; + break; + case DROWNING: + name = "drowned"; + break; + case FALL: + name = "fall"; + break; + case FIRE: + name = "fire"; + break; + case LAVA: + name = "lava"; + break; + case MAGIC: + name = "magic"; + break; + case POISON: + name = "poison"; + break; + case PROJECTILE: + name = "projectile"; + break; + case VOID: + name = "void"; + break; + default: + name = "generic"; + break; + } + + if (offender == null) return getMsg(offended, offender, messages, name); + else if (offender == offended) return getMsg(offended, offender, messages, name + "-suicide"); + else return getMsg(offended, offender, messages, name + "-byPlayer"); + } + + public static Map getMessages(OfflinePlayer player) { + return YamlConfiguration + .loadConfiguration(new File(Main.getInstance().getDataFolder(), "death-messages.yml")) + .getValues(true) + .entrySet() + .stream() + .collect(Collectors.toMap(v -> v.getKey(), v -> (String)v.getValue())); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/Game.java b/src/main/java/me/topchetoeu/bedwars/engine/Game.java new file mode 100644 index 0000000..d84e6e1 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/Game.java @@ -0,0 +1,450 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.CraftingInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import me.topchetoeu.bedwars.Main; +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedDealType; + +public class Game implements Listener, AutoCloseable { + public static Game instance = null; + private static Deque placedBlocks = new ArrayDeque<>(); + private static HashSet brokenBlocks = new HashSet<>(); + // private static int onlineCount; + + public static boolean inGame(OfflinePlayer p) { + return isStarted() && instance.isPlaying(p); + } + public static void start() { + Game.instance = new Game( + new ArrayList(Config.instance.getColors().stream().filter(v -> v.isFullySpecified()).collect(Collectors.toList())), + Config.instance.getTeamSize(), + new ArrayList(Bukkit.getOnlinePlayers()) + ); + + Bukkit.getOnlinePlayers().forEach(p -> { + RankedDealType.getDefinedRanks().values().forEach(v -> v.refreshInv(p.getPlayer())); + }); + + ScoreboardManager.updateAll(); + } + + public static void stop() { + Game.instance.close(); + Game.instance = null; + Main.getInstance().updateTimer(); + + ScoreboardManager.updateAll(); + } + + public static void stop(boolean immediatly) { + if (immediatly) stop(); + else Bukkit.getScheduler().runTaskLater(Main.getInstance(), () -> stop(), 20 * 5); + } + public static boolean isStarted() { + return instance != null; + } + + private ArrayList teams = new ArrayList<>(); + private ArrayList diamondGens = new ArrayList<>(); + private ArrayList emeraldGens = new ArrayList<>(); + + public List getDiamondGenerators() { + return Collections.unmodifiableList(diamondGens); + } + public List getEmeraldGenerators() { + return Collections.unmodifiableList(emeraldGens); + } + + public void teamifyItem(Player player, ItemStack item, boolean colour, boolean enchant) { + Team t = getTeam(player); + if (t != null) t.teamifyItem(item, colour, enchant); + } + + public void win(TeamColor color) { + getTeam(color).sendTitle("You won!", "", 0, 20 * 5, 0); + getTeam(color).sendTilteToOthers(color.getColorName() + " won!", "You lost :(", 0, 20 * 5, 0); + stop(false); + } + + public void breakBlock(Block block) { + SavedBlock bl = new SavedBlock(block.getLocation(), block.getState().getData(), block.getState().getType()); + brokenBlocks.add(bl); + block.setType(Material.AIR, false); + } + public void registerBrokenBlock(Location block) { + placedBlocks.remove(block); + } + public void registerPlacedBlock(Location block) { + placedBlocks.push(block); + } + + public boolean allowPlace(Location loc) { + for (Generator gen : Generator.getGenerators()) { + if (gen.getLocation().distance(loc) < 5) return false; + } + return true; + } + public boolean allowBreak(Location loc) { + if (!isStarted()) return true; + return placedBlocks.contains(loc) || loc.getWorld().getBlockAt(loc).getType() == Material.BED_BLOCK; + } + + public ArrayList getTeams() { + return teams; + } + public List getAliveTeams() { + return teams.stream().filter(v -> !v.isEliminated()).collect(Collectors.toList()); + } + public Team getTeam(TeamColor color) { + return teams + .stream() + .filter(v -> v.getTeamColor() == color) + .findFirst() + .orElse(null); + } + public Team getTeam(OfflinePlayer player) { + return teams + .stream() + .filter(v -> v.getPlayers().stream().anyMatch(p -> p.equals(player))) + .findFirst() + .orElse(null); + } + public ArrayList getPlayers() { + ArrayList res = new ArrayList<>(); + + for (Team team : teams) { + res.addAll(team.getPlayers()); + } + + return res; + } + public BedwarsPlayer getPlayer(OfflinePlayer player) { + Optional _p = getPlayers() + .stream() + .filter(v -> v.getPlayer().getUniqueId().equals(player.getUniqueId())) + .findFirst(); + + if (_p.isPresent()) return _p.get(); + else return null; + } + + public boolean isPlaying(OfflinePlayer p) { + return getPlayer(p) != null; + } + + @SuppressWarnings("deprecation") + public void close() { + for (Team team : teams) { + team.close(); + } + for (World w : Bukkit.getWorlds()) { + for (Entity e : w.getEntities()) { + if (!(e instanceof Player)) + if (!(e instanceof Villager)) + if (!(e instanceof ArmorStand)) + e.remove(); + } + } + + for (Generator gen: diamondGens) { + gen.close(); + gen.getLabel().close(); + } + for (Generator gen: emeraldGens) { + gen.close(); + gen.getLabel().close(); + } + + RankedDealType.resetPlayerTiers(); + + HandlerList.unregisterAll(this); + + for (Location placedBlock : placedBlocks) { + placedBlock.getBlock().setType(Material.AIR); + } + for (SavedBlock brokenBlock : brokenBlocks) { + brokenBlock.loc.getBlock().setType(brokenBlock.type, false); + brokenBlock.loc.getBlock().setData(brokenBlock.meta.getData(), false); + } + + placedBlocks.clear(); + brokenBlocks.clear(); + + teams = null; + } + + @EventHandler + private void onLogout(PlayerQuitEvent e) { + if (isPlaying(e.getPlayer())) { + e.setQuitMessage(e.getPlayer().getName() + " logged out."); + } + } + @EventHandler + private void onLogin(PlayerJoinEvent e) { + if(!isPlaying(e.getPlayer())) { + e.getPlayer().setGameMode(GameMode.SPECTATOR); + e.getPlayer().teleport(Bukkit.getServer().getWorlds().get(0).getSpawnLocation()); + Utility.sendTitle(e.getPlayer(), "You are now spectating", null, 5, 35, 10); + } + else + e.setJoinMessage(e.getPlayer().getName() + " reconnected."); + } + @EventHandler + private void onInventoryClick(InventoryClickEvent e) { + if (isStarted() && isPlaying((Player)e.getWhoClicked())) { + if (e.getClickedInventory() instanceof CraftingInventory) e.setCancelled(true); + } + } + @EventHandler + private void onItemDamage(PlayerItemDamageEvent e) { + e.setCancelled(true); + } + + + private static boolean isExceptional(Material mat) { + return mat == Material.LONG_GRASS || mat == Material.YELLOW_FLOWER || mat == Material.RED_ROSE; + } + + @EventHandler + private boolean onBlockBreak(Block b) { + if (isExceptional(b.getType())) { + b.getDrops().forEach(v -> b.getWorld().dropItemNaturally(b.getLocation().add(0.5, 0.5, 0.5), v)); + breakBlock(b); + } + else if (b.getType() == Material.BED_BLOCK) { + return false; + } + else if (allowBreak(b.getLocation())) { + registerBrokenBlock(b.getLocation()); + b.breakNaturally(); + } + else { + return false; + } + + return true; + } + @EventHandler + private void onBlockBreak(BlockBreakEvent e) { + e.setCancelled(true); + onBlockBreak(e.getBlock()); + } + @SuppressWarnings("incomplete-switch") + @EventHandler + private void onBlockPlace(PlayerBucketEmptyEvent e) { + + Location loc = e.getBlockClicked().getLocation(); + + switch (e.getBlockFace()) { + case UP: + loc.add(0, 1, 0); + break; + case DOWN: + loc.add(0, -1, 0); + break; + case EAST: + loc.add(1, 0, 0); + break; + case WEST: + loc.add(-1, 0, 0); + break; + case NORTH: + loc.add(0, 0, -1); + break; + case SOUTH: + loc.add(0, 0, 1); + break; + } + + if (!allowPlace(loc)) { + e.setCancelled(true); + return; + } + + if (loc.getBlock().getType() != Material.AIR) { + if (!allowBreak(loc)) e.setCancelled(true); + } + else registerPlacedBlock(loc); + } + @EventHandler + @SuppressWarnings("incomplete-switch") + private void onBlockPlace(BlockPlaceEvent e) { + if (e.getBlock().getType() == Material.TNT) { + e.setCancelled(true); + ItemStack i = e.getPlayer().getItemInHand(); + if (i.getAmount() == 0) e.getPlayer().setItemInHand(null); + else { + i.setAmount(i.getAmount() - 1); + e.getPlayer().setItemInHand(i); + } + e.getBlock().getWorld().spawnEntity(e.getBlock().getLocation().add(.5, 0, .5), EntityType.PRIMED_TNT).setVelocity(new Vector(0, 0, 0)); + } + else { + switch (e.getBlockReplacedState().getType()) { + case WATER: + case STATIONARY_WATER: + case LAVA: + case STATIONARY_LAVA: + if (!allowBreak(e.getBlock().getLocation())) e.setCancelled(true); + return; + case AIR: + if (!allowPlace(e.getBlock().getLocation())) { + e.setCancelled(true); + return; + } + break; + case GRASS: + case LONG_GRASS: + break; + } + + if (!e.isCancelled()) { + registerPlacedBlock(e.getBlock().getLocation()); + } + } + } + @EventHandler + private void onWaterPassTrough(BlockFromToEvent e) { + e.setCancelled(true); + } + @EventHandler + private void onEntityExplode(EntityExplodeEvent e) { + e.setCancelled(true); + for (Block b : e.blockList()) { + if (b.getType() != Material.GLASS) { + onBlockBreak(b); + } + } + + for (Player p : Bukkit.getOnlinePlayers()) { + p.playSound(e.getLocation(), Sound.EXPLODE, 1, 1); + } + } + @EventHandler + private void onUse(PlayerInteractEvent e) { + if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (e.getItem() == null) return; + if (e.getItem().getType() == Material.FIREBALL) { + + ItemStack i = e.getPlayer().getItemInHand(); + if (i.getAmount() == 0) e.getPlayer().setItemInHand(null); + else { + i.setAmount(i.getAmount() - 1); + e.getPlayer().setItemInHand(i); + } + + Location loc = e.getPlayer().getEyeLocation(); + + Fireball fireball = (Fireball)e.getPlayer().getWorld().spawnEntity( + loc.add(loc.getDirection().multiply(.5)), + EntityType.FIREBALL + ); + + fireball.getLocation().add(fireball.getDirection().multiply(10)); + fireball.setShooter(e.getPlayer()); + fireball.setYield(3); + e.setCancelled(true); + } + } + } + + public Game(ArrayList colors, int perTeam, ArrayList players) { + Bukkit.getPluginManager().registerEvents(this, Main.getInstance()); + int spectatorsCount = players.size() - perTeam * colors.size(); + ArrayList spectators = new ArrayList(); + + if (spectatorsCount > 0) { + for (int i = 0; i < spectatorsCount; i++) { + OfflinePlayer removed = players.remove((int)(Math.random() * players.size())); + spectators.add(removed); + if (removed.isOnline()) { + removed.getPlayer().setGameMode(GameMode.SPECTATOR); + removed.getPlayer().teleport(Config.instance.getRespawnLocation()); + } + if (removed.isOnline()) removed.getPlayer().sendMessage("You will be a spectator"); + } + } + + this.teams = new ArrayList<>(); + + if (colors.size() != 0) { + int colorI = 0; + + for (TeamColor color : colors) { + this.teams.add(new Team(color)); + } + + while (!players.isEmpty()) { + Team currTeam = this.teams.get(colorI); + OfflinePlayer p; + + currTeam.addPlayer(p = players.remove((int)(Math.random() * players.size()))); + + if (p.isOnline()) { + // onlineCount++; + } + + if (currTeam.getPlayersCount() == perTeam) { + colorI++; + } + } + } + + // TODO: Make times configurable + for (Location loc : Config.instance.getDiamondGenerators()) { + GeneratorLabel label = new GeneratorLabel("§cDiamond Generator", loc.clone().add(0, 1, 0)); + Generator gen = new Generator(loc, 4, label); + gen.addItem(Material.DIAMOND, 600); + + diamondGens.add(gen); + } + for (Location loc : Config.instance.getEmeraldGenerators()) { + GeneratorLabel label = new GeneratorLabel("§cEmerald Generator", loc.clone().add(0, 1, 0)); + Generator gen = new Generator(loc, 2, label); + gen.addItem(Material.EMERALD, 1200); + + emeraldGens.add(gen); + } + } + +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/Generator.java b/src/main/java/me/topchetoeu/bedwars/engine/Generator.java new file mode 100644 index 0000000..45ea402 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/Generator.java @@ -0,0 +1,146 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.ItemMergeEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; + +import me.topchetoeu.bedwars.Main; + +public class Generator implements AutoCloseable, Listener { + private class _Item implements AutoCloseable { + private BukkitTask task; + private BukkitTask timerTask; + private Generator parentInstance; + private int timer = 0; + + public void close() { + task.cancel(); + timerTask.cancel(); + timerTask = null; + task = null; + } + + public _Item(int interval, Material type, Generator gen) { + parentInstance = gen; + timer = interval; + this.task = Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> { + Item i = location.getWorld().dropItem(location, new ItemStack(type, 1)); + i.setVelocity(new Vector(0, 0, 0)); + parentInstance.generatedItems.add(i.getUniqueId()); + + if (parentInstance.generatedItems.size() > parentInstance.maxItems) { + if (parentInstance.generatedItems.size() != 0) { + UUID removed = parentInstance.generatedItems.stream().findFirst().get(); + + Bukkit.getServer().getWorlds() + .stream() + .flatMap(v -> v.getEntities().stream()) + .filter(v -> v.getUniqueId().equals(removed)) + .findFirst() + .ifPresent(v -> v.remove()); + + parentInstance.generatedItems.remove(removed); + } + } + }, interval, interval); + this.timerTask = Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> { + timer--; + if (timer == 0) timer = interval; + + if (parentInstance.label != null) parentInstance.label.setRemaining(type, timer / 20f); + }, 0, 1); + } + } + + private static HashSet generators = new HashSet<>(); + + private HashSet generatedItems = new HashSet<>(); + private Hashtable itemGenerators = new Hashtable<>(); + private Location location; + private int maxItems; + + private GeneratorLabel label; + + public Location getLocation() { + return location; + } + + public void addItem(Material type, int interval) { + if (itemGenerators.contains(type)) removeItem(type); + itemGenerators.put(type, new _Item(interval, type, this)); + } + public void removeItem(Material type) { + itemGenerators.remove(type).close(); + } + + public GeneratorLabel getLabel() { + return label; + } + + @EventHandler + private void onItemMerge(ItemMergeEvent e) { + if (generatedItems.contains(e.getEntity().getUniqueId()) || generatedItems.contains(e.getTarget().getUniqueId())) + e.setCancelled(true); + } + + @EventHandler + private void onPickup(PlayerPickupItemEvent e) { + if (generatedItems.contains(e.getItem().getUniqueId())) { + e.setCancelled(true); + + for (BedwarsPlayer bwp : Game.instance.getPlayers()) { + if (bwp.isOnline()) { + Player p = bwp.getOnlinePlayer(); + + if (p.getLocation().distance(e.getItem().getLocation()) < 2) { + p.playSound(e.getItem().getLocation(), Sound.ITEM_PICKUP, .5f, 2); + p.getInventory().addItem(e.getItem().getItemStack()); + } + } + } + generatedItems.remove(e.getItem().getUniqueId()); + e.getItem().remove(); + } + } + + public void close() { + for (Material m : new ArrayList<>(itemGenerators.keySet())) { + removeItem(m); + } + HandlerList.unregisterAll(this); + + itemGenerators = null; + generatedItems = null; + } + + public static Set getGenerators() { + return Collections.unmodifiableSet(generators); + } + + public Generator(Location loc, int maxItems, GeneratorLabel label) { + this.location = loc; + this.maxItems = maxItems; + this.label = label; + Bukkit.getPluginManager().registerEvents(this, Main.getInstance()); + + generators.add(this); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/GeneratorLabel.java b/src/main/java/me/topchetoeu/bedwars/engine/GeneratorLabel.java new file mode 100644 index 0000000..620edc7 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/GeneratorLabel.java @@ -0,0 +1,46 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.ArrayList; +import java.util.Hashtable; + +import org.bukkit.Location; +import org.bukkit.Material; + +import me.topchetoeu.bedwars.Utility; + +public class GeneratorLabel { + private HoverLabel label; + private String firstLine; + + private Hashtable remainingTimes = new Hashtable<>(); + + public void close() { + label.close(); + } + + public void setRemaining(Material item, float remainingSeconds) { + remainingTimes.put(item, remainingSeconds); + update(); + } + public float getRemaining(Material item) { + return remainingTimes.get(item); + } + + public void update() { + ArrayList lines = new ArrayList<>(); + + lines.add(firstLine); + lines.add(null); + + for (Material item : remainingTimes.keySet()) { + lines.add(String.format("%s in %.2f seconds", Utility.getItemName(item), remainingTimes.get(item))); + } + + label.setData(lines); + } + + public GeneratorLabel(String firstLine, Location loc) { + this.firstLine = firstLine; + label = new HoverLabel(loc, new ArrayList()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/HoverLabel.java b/src/main/java/me/topchetoeu/bedwars/engine/HoverLabel.java new file mode 100644 index 0000000..9c4f3c5 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/HoverLabel.java @@ -0,0 +1,107 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent; + +public class HoverLabel { + private List data; + private List armorStands; + private Location loc; + + private ArmorStand generateArmorStand(Location loc, String name) { + if (name == null || name.equals("")) return null; + ArmorStand as = (ArmorStand)loc.getWorld().spawnEntity(loc, EntityType.ARMOR_STAND); + + as.setGravity(false); + as.setVisible(false); + as.setCustomName(name); + as.setCustomNameVisible(true); + + return as; + } + @EventHandler + private void damage(EntityDamageEvent e) { + if (e.getEntity() instanceof ArmorStand) { + ArmorStand as = (ArmorStand)e.getEntity(); + if (armorStands.contains(as)) { + e.setCancelled(true); + } + } + } + + public void close() { + for (ArmorStand as : armorStands) { + if (as != null) as.remove(); + } + } + + public void setLocation(Location loc) { + this.loc = loc; + for(ArmorStand as : armorStands) { + if (as != null) as.teleport(loc); + loc = loc.add(0, -0.25, 0); + } + } + public Location getLocation() { + return loc; + } + + private Location replaceData(List data, int n) { + Location loc = this.loc.clone(); + for (int i = 0; i < n; i++) { + String line = data.get(i); + + if (line == null || line.equals("")) { + if (armorStands.get(i) != null) armorStands.get(i).remove(); + armorStands.set(i, null); + } + else { + if (armorStands.get(i) == null) armorStands.set(i, generateArmorStand(loc, line)); + else armorStands.get(i).setCustomName(line); + } + loc.add(0, -0.25, 0); + } + + return loc; + } + + public void setData(List data) { + if (data.size() > this.data.size()) { + Location loc = replaceData(data, this.data.size()); + + for (int i = this.data.size(); i < data.size(); i++) { + armorStands.add(generateArmorStand(loc, data.get(i))); + loc.add(0, -0.25, 0); + } + } + else if (data.size() == this.data.size()) { + replaceData(data, data.size()); + } + else { + replaceData(data, data.size()); + for (int i = data.size(); i < this.data.size(); i++) { + ArmorStand curr = armorStands.get(data.size()); + if (curr != null) curr.remove(); + armorStands.remove(data.size()); + } + } + + this.data = data; + } + public List getData() { + return data; + } + + public HoverLabel(Location loc, List data) { + this.loc = loc; + this.data = new ArrayList(); + this.armorStands = new ArrayList(); + setData(data); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/SavedBlock.java b/src/main/java/me/topchetoeu/bedwars/engine/SavedBlock.java new file mode 100644 index 0000000..4bf63fc --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/SavedBlock.java @@ -0,0 +1,17 @@ +package me.topchetoeu.bedwars.engine; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.material.MaterialData; + +public class SavedBlock { + public Location loc; + public MaterialData meta; + public Material type; + + public SavedBlock(Location l, MaterialData m, Material t) { + loc = l; + meta = m; + type = t; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/ScoreboardManager.java b/src/main/java/me/topchetoeu/bedwars/engine/ScoreboardManager.java new file mode 100644 index 0000000..793ad60 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/ScoreboardManager.java @@ -0,0 +1,79 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +public class ScoreboardManager { + private static Hashtable scoreboards = new Hashtable<>(); + + private static List getLines(Player p) { + if (!Game.isStarted()) return new ArrayList<>(); + return Game.instance + .getTeams() + .stream() + .map(v -> { + String teamCounter = "§a✔"; + if (v.getRemainingPlayers() == 0) teamCounter = "§4✖"; + else if (!v.hasBed()) teamCounter = Integer.toString(v.getRemainingPlayers()); + + String newStr = String.format(" %s§r: %s", v.getTeamColor().getColorName(), teamCounter); + + if (v.hasPlayer(p)) { + newStr = (newStr + "§r (you)").replaceAll("§([0-9a-z])", "§$1§l"); + } + + return newStr; + }) + .collect(Collectors.toList()); + + } + + public static Scoreboard getScoreboard(Player p) { + Scoreboard scoreboard = scoreboards.get(p.getUniqueId()); + if (scoreboard == null) { + scoreboards.put(p.getUniqueId(), Bukkit.getScoreboardManager().getNewScoreboard()); + scoreboard = scoreboards.get(p.getUniqueId()); + + p.setScoreboard(scoreboard); + + Objective objective = scoreboard.registerNewObjective("bedwars", "dummy"); + objective.setDisplayName(" §4§lBedwars "); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + return scoreboard; + } + + public static void update(Player p) { + Scoreboard scoreboard = getScoreboard(p); + + + List lines = getLines(p); + for (String entry : scoreboard.getEntries()) { + scoreboard.resetScores(entry); + } + + for (int i = 0; i < lines.size(); i++) { + scoreboard.getObjective("bedwars").getScore(lines.get(lines.size() - 1 - i)).setScore(i); + } + } + public static void updateAll() { + updateAll(false); + } + public static void updateAll(boolean supressTeamCheck) { + Bukkit.getServer().getOnlinePlayers().forEach(v -> update(v)); + + if (Game.isStarted() && Game.instance.getAliveTeams().size() == 1) { + Game.instance.win(Game.instance.getAliveTeams().get(0).getTeamColor()); + } + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/Team.java b/src/main/java/me/topchetoeu/bedwars/engine/Team.java new file mode 100644 index 0000000..67f0ba3 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/Team.java @@ -0,0 +1,255 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; + +import me.topchetoeu.bedwars.Main; +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.upgrades.TeamUpgrade; + +public class Team implements Listener, AutoCloseable { + private TeamColor color; + private ArrayList players = new ArrayList<>(); + private Hashtable upgrades = new Hashtable<>(); + private Generator generator; + + private boolean bed = true; + private int playersCount; + private int remainingPlayers; + + public boolean hasBed() { + return bed; + } + public boolean destroyBed(OfflinePlayer player) { + if (!bed) return false; + World world = Bukkit.getWorlds().get(0); + + for (int x = -5; x < 5; x++) { + for (int y = -5; y < 5; y++) { + for (int z = -5; z < 5; z++) { + Block block = new Location( + world, + color.getBedLocation().getBlockX() + x, + color.getBedLocation().getBlockY() + y, + color.getBedLocation().getBlockZ() + z + ).getBlock(); + if (block.getType() == Material.BED_BLOCK) { + Game.instance.breakBlock(block); + } + } + } + } + + bed = false; + for (BedwarsPlayer bwp : players) { + if (bwp.isOnline()) { + Player p = bwp.getOnlinePlayer(); + + String msg = color.getColorName() + "§r's bed was destroyed"; + if (player != null) msg += " by " + player.getName(); + msg += "."; + Bukkit.broadcastMessage(msg); + + Utility.sendTitle(p, "Bed destroyed!", "You will no longer respawn!", 5, 35, 10); + p.playSound(p.getLocation(), Sound.EXPLODE, 1, 1); + } + } + + ScoreboardManager.updateAll(); + + return true; + } + + public int decreaseRemainingPlayers() { + return --remainingPlayers; + } + public int getRemainingPlayers() { + return remainingPlayers; + } + public int getPlayersCount() { + return playersCount; + } + public void resetRemainingPlayers() { + remainingPlayers = playersCount; + } + + public void removeUpgrade(Class type) { + upgrades.keySet().removeIf(k -> { + TeamUpgrade v = upgrades.get(k); + return v.getClass().equals(type); + }); + } + public void addUpgrade(TeamUpgrade upgrade) { + upgrades.put(upgrade.getName(), upgrade); + } + public void updateUpgrades() { + upgrades.values().forEach(v -> v.updateTeam(this)); + } + public Collection getUpgrades() { + return upgrades.values(); + } + public boolean hasUpgrade(TeamUpgrade upgrade) { + return upgrades.contains(upgrade); + } + + public TeamColor getTeamColor() { + return color; + } + + public List getPlayers() { + return Collections.unmodifiableList(players); + } + + public void removePlayer(BedwarsPlayer p) { + if (players.remove(p)) { + playersCount--; + if (!p.isSpectator()) remainingPlayers--; + } + + } + public void addPlayer(BedwarsPlayer p) { + if (players.add(p)) { + playersCount++; + if (!p.isSpectator()) remainingPlayers++; + } + } + public void addPlayer(OfflinePlayer p) { + if (!hasPlayer(p)) { + players.add(new BedwarsPlayer(p, this)); + playersCount++; + if (bed) remainingPlayers++; + } + } + + public boolean hasPlayer(BedwarsPlayer p) { + return hasPlayer(p.getPlayer()); + } + public boolean hasPlayer(OfflinePlayer p) { + return players + .stream() + .filter(v -> v.getPlayer().getUniqueId().equals(p.getUniqueId())) + .findFirst() + .isPresent(); + } + + public boolean isEliminated() { + return remainingPlayers == 0; + } + + @Override + public void close() { + generator.close(); + + for (BedwarsPlayer bwp : players) { + bwp.close(); + } + + HandlerList.unregisterAll(this); + + players = null; + generator = null; + } + + @EventHandler + private void onBlockBreak(BlockBreakEvent e) { + if (e.getBlock().getType() == Material.BED_BLOCK) { + if (e.getBlock().getLocation().distance(color.getBedLocation()) < 5) { + if (hasPlayer(e.getPlayer())) { + e.setCancelled(true); + if (getPlayersCount() == 1) { + e.getPlayer().sendMessage("§4You may not destroy your bed."); + } + else { + e.getPlayer().sendMessage("§4You may not destroy your team's bed."); + } + } + else { + if (bed) { + e.setCancelled(true); + destroyBed(e.getPlayer()); + } + } + } + } + } + + public void sendMessage(String msg) { + for (BedwarsPlayer bwp : players) { + if (bwp.isOnline()) bwp.getOnlinePlayer().sendMessage(msg); + } + } + public void sendTitle(String title, String subtitle, int fadein, int duration, int fadeout) { + for (BedwarsPlayer bwp : players) { + if (bwp.isOnline()) Utility.sendTitle(bwp.getOnlinePlayer(), title, subtitle, fadein, duration, fadeout); + } + } + public void sendTilteToOthers(String title, String subtitle, int fadein, int duration, int fadeout) { + for (Player p : Bukkit.getServer().getOnlinePlayers()) { + if (players.stream().noneMatch(v -> v.getPlayer().getUniqueId().equals(p.getUniqueId()))) + Utility.sendTitle(p, title, subtitle, fadein, duration, fadeout); + } + } + + @SuppressWarnings("deprecation") + public ItemStack teamifyItem(ItemStack stack, boolean colour, boolean upgrades) { + if (colour) { + if (stack.getType() == Material.WOOL) stack.setDurability((short)color.getWoolId()); + else { + ItemMeta meta = stack.getItemMeta(); + + if (meta instanceof LeatherArmorMeta) { + LeatherArmorMeta armour = (LeatherArmorMeta)meta; + armour.setColor(DyeColor.getByData((byte)color.getWoolId()).getColor()); + stack.setItemMeta(armour); + } + } + } + + if (upgrades) { + this.upgrades.values().forEach(v -> { + v.upgradeItem(stack); + }); + } + + return stack; + } + + + public Team(TeamColor color, Player... players) { + this.players.addAll(Arrays.asList(players) + .stream() + .map(v -> new BedwarsPlayer(v, this)) + .collect(Collectors.toList()) + ); + this.color = color; + this.playersCount = this.remainingPlayers = players.length; + + this.generator = new Generator(color.getGeneratorLocation(), 48, null); + this.generator.addItem(Material.IRON_INGOT, 20); + this.generator.addItem(Material.GOLD_INGOT, 80); + + Bukkit.getPluginManager().registerEvents(this, Main.getInstance()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/TeamColor.java b/src/main/java/me/topchetoeu/bedwars/engine/TeamColor.java new file mode 100644 index 0000000..a5f2e1f --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/TeamColor.java @@ -0,0 +1,87 @@ +package me.topchetoeu.bedwars.engine; + +import java.util.Hashtable; +import java.util.Map; + +import org.bukkit.Location; +import org.bukkit.configuration.serialization.ConfigurationSerializable; + +public class TeamColor implements ConfigurationSerializable { + private String name; + private int woolId; + private char colorId; + private Location bed = null; + private Location spawnLocation = null; + private Location generatorLocation = null; + + public String getName() { + return name; + } + public String getColorName() { + return String.format("§%c%s%s", colorId, name.substring(0, 1).toUpperCase(), name.substring(1)); + } + public int getWoolId() { + return woolId; + } + public char getColorId() { + return colorId; + } + + public Location getBedLocation() { + return bed; + } + public void setBedLocation(Location loc) { + bed = loc; + } + + public Location getSpawnLocation() { + return spawnLocation; + } + public void setSpawnLocation(Location loc) { + spawnLocation = loc; + } + + public Location getGeneratorLocation() { + return generatorLocation; + } + public void setGeneratorLocation(Location loc) { + generatorLocation = loc; + } + + public boolean isFullySpecified() { + return bed != null && spawnLocation != null && generatorLocation != null; + } + + public TeamColor(String name, int woolId, char colorId) { + this.name = name; + this.woolId = woolId; + this.colorId = colorId; + } + @Override + public Map serialize() { + Map map = new Hashtable<>(); + + map.put("name", name); + map.put("woolId", woolId); + map.put("colorId", colorId); + if (bed != null) map.put("bed", bed.serialize()); + if (generatorLocation != null) map.put("generator", generatorLocation.serialize()); + if (spawnLocation != null) map.put("spawn", spawnLocation.serialize()); + + return map; + } + @SuppressWarnings("unchecked") + public static TeamColor deserialize(Map map) { + TeamColor color = new TeamColor( + (String)map.get("name"), + (int)map.get("woolId"), + ((String)map.get("colorId")).charAt(0) + ); + + if (map.containsKey("bed")) color.setBedLocation(Location.deserialize((Map) map.get("bed"))); + if (map.containsKey("generator")) color.setGeneratorLocation(Location.deserialize((Map) map.get("generator"))); + if (map.containsKey("spawn"))color.setSpawnLocation(Location.deserialize((Map) map.get("spawn"))); + + return color; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/WoodenSword.java b/src/main/java/me/topchetoeu/bedwars/engine/WoodenSword.java new file mode 100644 index 0000000..adbd3b6 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/WoodenSword.java @@ -0,0 +1,26 @@ +package me.topchetoeu.bedwars.engine; + +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class WoodenSword { + public static boolean isOtherSword(Material mat) { + return mat == Material.IRON_SWORD || + mat == Material.DIAMOND_SWORD || + mat == Material.STONE_SWORD || + mat == Material.STONE_SWORD; + } + public static boolean hasOtherSword(Inventory inv) { + return inv.contains(Material.IRON_SWORD) || + inv.contains(Material.DIAMOND_SWORD) || + inv.contains(Material.STONE_SWORD) || + inv.contains(Material.STONE_SWORD); + } + public static void update(BedwarsPlayer p, Inventory inv) { + if (hasOtherSword(inv)) + inv.remove(Material.WOOD_SWORD); + else if (!inv.contains(Material.WOOD_SWORD)) + inv.addItem(p.getTeam().teamifyItem(new ItemStack(Material.WOOD_SWORD, 1), true, true)); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/Deal.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/Deal.java new file mode 100644 index 0000000..d93a522 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/Deal.java @@ -0,0 +1,15 @@ +package me.topchetoeu.bedwars.engine.trader; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public interface Deal { + public ItemStack getDealItem(Player p); + public String getDealName(Player p); + public Material getPriceType(Player p); + public int getPrice(Player p); + public boolean alreadyBought(Player p); + + public void commence(Player p); +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/DealPtr.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/DealPtr.java new file mode 100644 index 0000000..4f86fe5 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/DealPtr.java @@ -0,0 +1,26 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.util.List; + +public class DealPtr { + private int sectionN; + private int dealN; + + public int getSectionN() { + return sectionN; + } + public int getDealN() { + return dealN; + } + + public Deal getDeal(List
sections) { + if (sections.size() <= sectionN) return null; + if (sections.get(sectionN).getDeals().size() <= dealN) return null; + return sections.get(sectionN).getDeal(dealN); + } + + public DealPtr(int sectionN, int dealN) { + this.sectionN = sectionN; + this.dealN = dealN; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/DealType.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/DealType.java new file mode 100644 index 0000000..cacdd99 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/DealType.java @@ -0,0 +1,8 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.util.Map; + +public interface DealType { + public Deal parse(Map map); + public String getId(); +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/DealTypes.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/DealTypes.java new file mode 100644 index 0000000..e54068e --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/DealTypes.java @@ -0,0 +1,20 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.util.Hashtable; + +public class DealTypes { + private static Hashtable dealTypes = new Hashtable<>(); + + private DealTypes() { + + } + + public static boolean register(DealType type) { + if (dealTypes.contains(type.getId())) return false; + dealTypes.put(type.getId(), type); + return true; + } + public static DealType get(String id) { + return dealTypes.get(id); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/Favourites.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/Favourites.java new file mode 100644 index 0000000..581f88e --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/Favourites.java @@ -0,0 +1,81 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.io.File; +import java.io.IOException; +import java.util.Hashtable; +import java.util.Map; + +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +public class Favourites { + public static Favourites instance; + + private File directory; + private Map defaults; + + private YamlConfiguration serialize(Map favs) { + YamlConfiguration config = new YamlConfiguration(); + + for (int n : favs.keySet()) { + Map map = new Hashtable<>(); + map.put("section", favs.get(n).getSectionN()); + map.put("deal", favs.get(n).getDealN()); + + config.set(Integer.toString(n), map); + } + + return config; + } + private Map deserialize(YamlConfiguration config) { + Map favs = new Hashtable<>(); + + for (String s : config.getKeys(false)) { + int n = Integer.parseInt(s); + ConfigurationSection section = config.getConfigurationSection(s); + + int dealN, sectN; + + dealN = section.getInt("deal"); + sectN = section.getInt("section"); + + DealPtr deal = new DealPtr(sectN, dealN); + + favs.put(n, deal); + } + + return favs; + } + + public Map getFavourites(OfflinePlayer p) { + File file = new File(directory, p.getUniqueId().toString() + ".yml"); + + if (file.exists() && file.canRead()) return deserialize(YamlConfiguration.loadConfiguration(file)); + else { + try { + serialize(defaults).save(file); + } catch (IOException e) { /* everythings fine */ } + + return defaults; + } + } + public void updateFavourites(OfflinePlayer p, Map newFavs) { + try { + serialize(newFavs).save(new File(directory, p.getUniqueId().toString() + ".yml")); + } catch (IOException e) { + p.getPlayer().sendMessage(e.getMessage()); + } + } + + public Favourites(File directory, Map defaults) { + directory.mkdir(); + this.directory = directory; + this.defaults = defaults; + } + public Favourites(File directory, File defaults) { + directory.mkdir(); + this.directory = directory; + this.defaults = deserialize(YamlConfiguration.loadConfiguration(defaults)); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/Section.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/Section.java new file mode 100644 index 0000000..f52ac2e --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/Section.java @@ -0,0 +1,48 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.inventory.ItemStack; + +public class Section { + private ArrayList items = new ArrayList<>(); + private ItemStack icon; + + public Deal getDeal(int i) { + if (i < 0 || i >= items.size()) return null; + return items.get(i); + } + + public Section addDeal(Deal d) { + items.add(d); + return this; + } + public void removeDeal(Deal d) { + items.remove(d); + } + + public List getDealPage(int size, int n) { + return items.stream().skip(size * n).limit(size).collect(Collectors.toList()); + } + public List getDeals() { + return new ArrayList<>(items); + } + + public ItemStack getIcon() { + return icon; + } + public void setIcon(ItemStack item) { + icon = item; + } + + public Section(ItemStack icon) { + this.items = new ArrayList<>(); + this.icon = icon; + } + public Section(ItemStack icon, List deals) { + this.items = new ArrayList<>(deals); + this.icon = icon; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/Sections.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/Sections.java new file mode 100644 index 0000000..4df267c --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/Sections.java @@ -0,0 +1,50 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.Utility; + +@SuppressWarnings("unchecked") +public class Sections { + public static File SECTIONS_FILE; + + private static List
sections; + + private static Deal deserializeDeal(Map raw) { + String type = (String)raw.get("type"); + DealType dealType = DealTypes.get(type); + + if (dealType == null) throw new RuntimeException(String.format("Deal type %s is not recognised.", type)); + + return dealType.parse(raw); + } + private static Section deserializeSection(Map raw) { + List deals = ((List>)raw.get("deals")) + .stream() + .map(v -> deserializeDeal((Map)v)) + .collect(Collectors.toList()); + ItemStack icon = Utility.deserializeItemStack((Map)raw.get("iconItem")); + + return new Section(icon, deals); + } + + public static List
getSections() { + return sections; + } + + public static void init(File sectionsFile) { + SECTIONS_FILE = sectionsFile; + sections = YamlConfiguration + .loadConfiguration(SECTIONS_FILE) + .getMapList("sections") + .stream() + .map(v -> deserializeSection((Map)v)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/TraderGUI.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/TraderGUI.java new file mode 100644 index 0000000..0f5dde5 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/TraderGUI.java @@ -0,0 +1,341 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import me.topchetoeu.bedwars.InventoryUtility; +import me.topchetoeu.bedwars.Main; +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.dealTypes.ItemDeal; + +// Very bad code. +public class TraderGUI implements Listener { + private List
sections; + private Inventory inventory = null; + private Player player; + private int currSectionN = -1; + private Map favourites; + private int currFavourite = -1; + private int sectionsOffset = 0; + private boolean sectionsOverflow = false; + + public Inventory getInventory() { + return inventory; + } + public Player getPlayer() { + return player; + } + + public ItemStack generateDealItem(Deal d, boolean addFavouriteLore) { + String name = "§r" + d.getDealName(player); + if (d.alreadyBought(player)) name += " §4(already unlocked)"; + else name += String.format(" (%dx %s)", + d.getPrice(player), + Utility.getItemName(d.getPriceType(player)) + ); + + ItemStack item = Utility.copyNamedItem(d.getDealItem(player), name); + + if (addFavouriteLore) { + List lore = new ArrayList<>(); + lore.add("§rShift + Left click to set slot"); + lore.add("§rShift + Right click to reset"); + + ItemMeta meta = item.getItemMeta(); + if (meta.getLore() != null) lore.addAll(meta.getLore()); + meta.setLore(lore); + item.setItemMeta(meta); + } + + return item; + } + + public void setSectionOffset(int n) { + sectionsOffset = n; + ItemStack[] invC = inventory.getContents(); + + ItemStack blackGlassPanes = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short)15); + ItemMeta meta = blackGlassPanes.getItemMeta(); + meta.setDisplayName(" "); + blackGlassPanes.setItemMeta(meta); + + for (int i = 1; i < 8; i++) { + invC[i] = blackGlassPanes; + } + + if (sectionsOffset == 0) + invC[1 - sectionsOffset] = Utility.namedItem(new ItemStack(Material.NETHER_STAR), "§rFavourites"); + + for (int i = 0; i < sections.size(); i++) { + Section sec = sections.get(i); + + int index = i + 2 - sectionsOffset; + if (index > 0 && index < 8) invC[index] = sec.getIcon(); + } + inventory.setContents(invC); + } + public void selectSection(int n) { + if (n == -1) + selectFavourite(); + else { + if (n < 0 || n >= sections.size()) return; + + Section sec = sections.get(n); + + ItemStack[] contents = inventory.getContents(); + + for (int x = 1; x < 8; x++) { + for (int y = 1; y < 5; y++) { + contents[x + y * 9] = null; + } + } + + for (int i = 0; i < sec.getDeals().size(); i++) { + Deal d = sec.getDeal(i); + contents[i % 7 + i / 7 * 9 + 10] = generateDealItem(d, false); + } + inventory.setContents(contents); + } + + player.playSound(player.getLocation(), Sound.CLICK, 1, 1); + + currSectionN = n; + } + public void selectFavourite() { + + ItemStack[] contents = inventory.getContents(); + + ItemStack empty = Utility.namedItem(new ItemStack(Material.STAINED_GLASS_PANE, 1, (short)8), "§rEmpty slot"); + + ItemMeta meta = empty.getItemMeta(); + List lore = new ArrayList<>(); + lore.add("§rShift + Left click to set slot"); + meta.setLore(lore); + empty.setItemMeta(meta); + + for (int x = 1; x < 8; x++) { + for (int y = 1; y < 5; y++) { + contents[x + y * 9] = empty; + } + } + + for (Integer n : favourites.keySet()) { + Deal d = favourites.get(n).getDeal(sections); + + if (d != null) contents[n % 7 + n / 7 * 9 + 10] = generateDealItem(d, true); + } + + inventory.setContents(contents); + + currSectionN = -1; + } + + public void updateSection() { + selectSection(currSectionN); + } + + public void trade(Deal deal) { + if (deal.alreadyBought(player)) { + player.sendMessage("You already own this."); + player.playSound(player.getLocation(), Sound.VILLAGER_NO, 1, 1); + } + else { + ItemStack[] inv = player.getInventory().getContents(); + ItemStack price = new ItemStack(deal.getPriceType(player), deal.getPrice(player)); + + + if (deal instanceof ItemDeal && !((ItemDeal)deal).isImplemented()) { + deal.commence(player); + } + else { + + if (InventoryUtility.hasItem(inv, price)) { + InventoryUtility.takeItems(inv, price); + + player.getInventory().setContents(inv); + + deal.commence(player); + updateSection(); + if (player.getInventory().contains(Material.STONE_SWORD) || + player.getInventory().contains(Material.IRON_SWORD) || + player.getInventory().contains(Material.DIAMOND_SWORD)) { + if (player.getInventory().contains(Material.WOOD_SWORD)) { + player.getInventory().remove(Material.WOOD_SWORD); + } + } + player.playSound(player.getLocation(), Sound.VILLAGER_YES, 1, 1); + } + else { + player.sendMessage(String.format("You don't have enough %ss!", Utility.getItemName(deal.getPriceType(player)).toLowerCase())); + player.playSound(player.getLocation(), Sound.VILLAGER_NO, 1, 1); + } + } + } + } + + private void generateInventory(Inventory inv) { + ItemStack blackGlassPanes = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short)15); + ItemMeta meta = blackGlassPanes.getItemMeta(); + meta.setDisplayName(" "); + blackGlassPanes.setItemMeta(meta); + + ItemStack[] invC = inv.getContents(); + + for (int i = 0; i < 6; i++) { + invC[i * 9] = blackGlassPanes; + invC[i * 9 + 8] = blackGlassPanes; + } + for (int i = 0; i < 9; i++) { + invC[i] = blackGlassPanes; + invC[i + 45] = blackGlassPanes; + } + + if (sectionsOverflow) { + invC[0] = Utility.namedItem(new ItemStack(Material.ARROW), "§rBack"); + invC[8] = Utility.namedItem(new ItemStack(Material.ARROW), "§rForward"); + } + + inv.setContents(invC); + + ItemStack exitItem = new ItemStack(Material.BARRIER); + meta = exitItem.getItemMeta(); + meta.setDisplayName("§rExit"); + exitItem.setItemMeta(meta); + inv.setItem(49, exitItem); + + setSectionOffset(0); + } + + public Inventory open() { + inventory = Bukkit.createInventory(null, 54, "Trader"); + generateInventory(inventory); + selectFavourite(); + + inventory = player.openInventory(inventory).getTopInventory(); + + return inventory; + } + public void dispose() { + HandlerList.unregisterAll(this); + sections = null; + inventory = null; + } + + private void setFavourite(DealPtr d) { + if (currFavourite < 0) return; + if (d == null && favourites.containsKey(currFavourite)) { + favourites.remove(currFavourite); + Favourites.instance.updateFavourites(player, favourites); + player.playSound(player.getLocation(), Sound.GHAST_FIREBALL, 1, 1); + } + else { + favourites.put(currFavourite, d); + Favourites.instance.updateFavourites(player, favourites); + player.playSound(player.getLocation(), Sound.ORB_PICKUP, 1, 1); + } + + currFavourite = -1; + selectFavourite(); + } + + @EventHandler + private void onInventoryClick(InventoryClickEvent e) { + if ((Object)inventory == (Object)e.getInventory()) { + e.setCancelled(true); + if (e.getClickedInventory() == e.getInventory()) { + if (e.getClick() != ClickType.LEFT && e.getClick() != ClickType.SHIFT_LEFT && e.getClick() != ClickType.SHIFT_RIGHT) return; + int slot = e.getSlot(); + + if (slot == 0 && sectionsOffset > 0) { + setSectionOffset(sectionsOffset - 1); + return; + } + if (slot == 8 && sectionsOffset < sections.size() - 6) { + setSectionOffset(sectionsOffset + 1); + return; + } + + if (slot % 9 == 8 || slot % 9 == 0) { + if (currFavourite >= 0) setFavourite(null); + return; + } + + if (slot == 49) { + player.closeInventory(); + player.playSound(player.getLocation(), Sound.CLICK, 1, 1); + return; + } + else if (slot < 9) selectSection(slot - 2 + sectionsOffset); // Section + else if (slot / 9 == 5) { + if (currFavourite >= 0) setFavourite(null); + } + else { + int x = slot % 9 - 1; + int y = slot / 9 - 1; + + int n = x + y * 7; + + Deal d = null; + + if (currSectionN >= 0) { + Section s = sections.get(currSectionN); + d = s.getDeal(n); + } + else if (favourites.containsKey(n)) { + d = favourites.get(n).getDeal(sections); + } + + if (currSectionN < 0) { + if (e.getClick() == ClickType.SHIFT_LEFT) { + player.playSound(player.getLocation(), Sound.CLICK, 1, 1); + currFavourite = n; return; + } + else if (e.getClick() == ClickType.SHIFT_RIGHT) { + currFavourite = n; + setFavourite(null); + return; + } + } + + if (d != null) { + if (currFavourite < 0) trade(d); + else { + if (currSectionN < 0) setFavourite(favourites.get(n)); + else setFavourite(new DealPtr(currSectionN, n)); + } + } + } + } + } + } + @EventHandler + private void onInventoryClose(InventoryCloseEvent e) { + if (e.getInventory() == inventory) { + dispose(); + } + } + + public TraderGUI(File favsDir, Player p) { + this.sections = Sections.getSections(); + this.player = p; + Bukkit.getPluginManager().registerEvents(this, Main.getInstance()); + this.favourites = Favourites.instance.getFavourites(p); + this.sectionsOverflow = sections.size() + 1 > 7; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/Traders.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/Traders.java new file mode 100644 index 0000000..559bfb4 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/Traders.java @@ -0,0 +1,182 @@ +package me.topchetoeu.bedwars.engine.trader; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import com.google.common.io.Files; + +import me.topchetoeu.bedwars.Main; +import net.minecraft.server.v1_8_R3.NBTTagCompound; + +public class Traders implements Listener { + public static Traders instance = null; + + private List villagers = new ArrayList<>(); + private File file; + + private void write() { + BufferedWriter writer; + try { + writer = Files.newWriter(file, Charset.defaultCharset()); + + for (UUID uuid : villagers) { + writer.write(uuid.toString() + "\n"); + } + writer.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public Villager summonVillager(Location loc) { + Villager vil = (Villager)loc.getWorld().spawnEntity(loc, EntityType.VILLAGER); + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) vil).getHandle(); + NBTTagCompound tag = nmsEntity.getNBTTag(); + if (tag == null) { + tag = new NBTTagCompound(); + } + + nmsEntity.c(tag); + tag.setInt("NoAI", 1); + nmsEntity.f(tag); + + nmsEntity.b(true); + + villagers.add(vil.getUniqueId()); + + write(); + + return vil; + } + + @EventHandler + private void onEntityInteract(PlayerInteractEntityEvent e) { + if (e.getRightClicked() instanceof Villager) { + Villager v = (Villager)e.getRightClicked(); + + if (villagers.stream().anyMatch(_v -> _v.equals(v.getUniqueId()))) { + e.setCancelled(true); + + File favsDir = new File(Main.getInstance().getDataFolder(), "favourites"); + + new TraderGUI(favsDir, e.getPlayer()).open(); + } + } + } + @EventHandler + private void onUse(PlayerInteractEvent e) { + if (e.getAction() == Action.RIGHT_CLICK_BLOCK && + e.hasItem() && + e.getItem().hasItemMeta() && + e.getItem().getItemMeta().hasDisplayName() && + e.getItem().getItemMeta().getDisplayName() == "§rTrader spawner") { + if (e.getItem().getType() == Material.MONSTER_EGG) { + int yaw = (int)e.getPlayer().getLocation().getYaw() - 45; + if (yaw < 0) yaw += 360; + + yaw = yaw / 90 * 90; + yaw -= 90; + + + Location loc = new Location( + e.getClickedBlock().getLocation().getWorld(), + e.getClickedBlock().getLocation().getBlockX() + .5, + e.getClickedBlock().getLocation().getBlockY(), + e.getClickedBlock().getLocation().getBlockZ() + .5, + yaw, 0 + ); + + if (e.getBlockFace() == BlockFace.DOWN) loc.setY(loc.getY() - 2); + if (e.getBlockFace() == BlockFace.UP) loc.setY(loc.getY() + 1); + if (e.getBlockFace() == BlockFace.SOUTH) loc.setZ(loc.getZ() + 1); + if (e.getBlockFace() == BlockFace.NORTH) loc.setZ(loc.getZ() - 1); + if (e.getBlockFace() == BlockFace.EAST) loc.setX(loc.getX() + 1); + if (e.getBlockFace() == BlockFace.WEST) loc.setX(loc.getX() - 1); + + summonVillager(loc); + + e.getPlayer().sendMessage("Trader spawned!"); + e.getPlayer().playSound(e.getPlayer().getLocation(), Sound.VILLAGER_YES, 1, 1); + } + } + } + @EventHandler + private void onEntityDamage(EntityDamageEvent e) { + if (e.getEntity() instanceof Villager) { + Villager v = (Villager)e.getEntity(); + + if (villagers.stream().anyMatch(_v -> _v.equals(v.getUniqueId()))) { + e.setCancelled(true); + } + } + } + @EventHandler + private void onEntityDamageEntity(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Player) { + Player p = (Player)e.getDamager(); + + if (e.getEntity() instanceof Villager) { + Villager v = (Villager)e.getEntity(); + + if (villagers.stream().anyMatch(_v -> _v.equals(v.getUniqueId()))) { + e.setCancelled(true); + + ItemStack hand = p.getInventory().getItemInHand(); + + if (hand != null && + hand.hasItemMeta() && + hand.getItemMeta().hasDisplayName() && + hand.getItemMeta().getDisplayName().equals("§rTrader eradicator")) { + if (hand.getType() == Material.STICK) { + villagers.remove(v.getUniqueId()); + write(); + v.remove(); + p.playSound(p.getLocation(), Sound.VILLAGER_DEATH, 1, 1); + p.sendMessage("Trader removed!"); + } + } + } + } + } + } + + + + public Traders(File tradersFile) throws IOException { + if (!tradersFile.exists()) tradersFile.createNewFile(); + villagers = Files.readLines(tradersFile, Charset.defaultCharset()) + .stream() + .map(v -> UUID.fromString(v)) + .collect(Collectors.toList()); + + file = tradersFile; + + Bukkit.getPluginManager().registerEvents(this, Main.getInstance()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDeal.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDeal.java new file mode 100644 index 0000000..54caa36 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDeal.java @@ -0,0 +1,52 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Hashtable; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.trader.Deal; + +public class EnforcedRankedDeal implements Deal { + private Rank soldRank; + private Hashtable prices; + + public Rank getRank() { + return soldRank; + } + + @Override + public ItemStack getDealItem(Player p) { + ItemStack icon = soldRank.getNextTier(p).getIcon(); + if (Game.isStarted()) Game.instance.teamifyItem(p, icon, true, true); + return icon; + } + @Override + public String getDealName(Player p) { + return soldRank.getNextTier(p).getDisplayName(); + } + @Override + public Material getPriceType(Player p) { + return prices.get(soldRank.getNextTier(p)).getPriceType(); + } + @Override + public int getPrice(Player p) { + return prices.get(soldRank.getNextTier(p)).getPrice(); + } + @Override + public boolean alreadyBought(Player p) { + return soldRank.getNextTier(p) == soldRank.getPlayerTier(p); + } + @Override + public void commence(Player p) { + p.sendMessage(String.format("§rYou just purchased %s.", getDealName(p))); + soldRank.increasePlayerTier(p, soldRank.getNextTier(p)); + } + + public EnforcedRankedDeal(Rank rank, Hashtable prices) { + this.soldRank = rank; + this.prices = prices; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDealType.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDealType.java new file mode 100644 index 0000000..fcda286 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/EnforcedRankedDealType.java @@ -0,0 +1,35 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Hashtable; +import java.util.Map; + +import me.topchetoeu.bedwars.engine.trader.Deal; +import me.topchetoeu.bedwars.engine.trader.DealType; +import me.topchetoeu.bedwars.engine.trader.DealTypes; + +public class EnforcedRankedDealType implements DealType { + @SuppressWarnings("unchecked") + @Override + public Deal parse(Map map) { + Hashtable prices = new Hashtable<>(); + Rank rank = RankedDealType.getDefinedRanks().get((String)map.get("rank")); + + Map> pricesMap = (Map>)map.get("prices"); + + for (String name : pricesMap.keySet()) { + RankTier tier = rank.getTier(name); + Price price = Price.deserialize(pricesMap.get(name)); + + prices.put(tier, price); + } + + return new EnforcedRankedDeal(rank, prices); + } + + @Override + public String getId() { return "tier_enforced"; } + + public static void init() { + DealTypes.register(new EnforcedRankedDealType()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDeal.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDeal.java new file mode 100644 index 0000000..3a953c0 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDeal.java @@ -0,0 +1,74 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.InventoryUtility; +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.BedwarsPlayer; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.WoodenSword; +import me.topchetoeu.bedwars.engine.trader.Deal; + +public class ItemDeal implements Deal { + private ItemStack item; + private int price; + private Material priceType; + private boolean implemented; + + @Override + public ItemStack getDealItem(Player p) { + ItemStack item = this.item; + if (Game.isStarted()) Game.instance.teamifyItem(p, item, true, true); + return item; + } + + @Override + public String getDealName(Player p) { + return String.format("§r%dx %s%s", item.getAmount(), Utility.getItemName(item), implemented ? "" : " §4§l(not implemented)§r"); + } + + @Override + public Material getPriceType(Player p) { + return priceType; + } + public boolean isImplemented() { + return implemented; + } + + @Override + public int getPrice(Player p) { + return price; + } + + @Override + public void commence(Player p) { + if (!implemented) { + p.sendMessage("The item you're trying to buy is not implemented yet."); + return; + } + ItemStack item = getDealItem(p); + p.sendMessage(String.format("You just purchased %s.", getDealName(p))); + ItemStack[] contents = p.getInventory().getContents(); + InventoryUtility.giveItem(contents, item); + p.getInventory().setContents(contents); + if (Game.isStarted()) { + BedwarsPlayer bwp = Game.instance.getPlayer(p); + if (bwp != null) WoodenSword.update(bwp, p.getInventory()); + } + + } + + public ItemDeal(ItemStack item, int price, Material priceType, boolean implemented) { + this.item = item; + this.price = price; + this.priceType = priceType; + this.implemented = implemented; + } + + @Override + public boolean alreadyBought(Player p) { + return false; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDealType.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDealType.java new file mode 100644 index 0000000..c652864 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/ItemDealType.java @@ -0,0 +1,34 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Map; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.Deal; +import me.topchetoeu.bedwars.engine.trader.DealType; +import me.topchetoeu.bedwars.engine.trader.DealTypes; + +public class ItemDealType implements DealType { + + @SuppressWarnings("unchecked") + @Override + public Deal parse(Map map) { + boolean implemented = !map.containsKey("implemented") || (boolean)map.get("implemented"); + int price = (Integer)map.get("price"); + Material priceType = Material.getMaterial(((String)map.get("priceType")).toUpperCase()); + ItemStack type = Utility.deserializeItemStack((Map)map.get("item")); + + return new ItemDeal(type, price, priceType, implemented); + } + + @Override + public String getId() { + return "item"; + } + + public static void init() { + DealTypes.register(new ItemDealType()); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Price.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Price.java new file mode 100644 index 0000000..3535b4d --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Price.java @@ -0,0 +1,35 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Map; + +import org.bukkit.Material; + +public class Price { + private int price; + private Material priceType; + private String displayName; + + public int getPrice() { + return price; + } + public Material getPriceType() { + return priceType; + } + public String getDisplayName() { + return displayName; + } + + public static Price deserialize(Map map) { + int price = (Integer)map.get("price"); + Material priceType = Material.getMaterial(((String)map.get("priceType")).toUpperCase()); + String displayName = (String)map.get("displayName"); + + return new Price(price, priceType, displayName); + } + + public Price(int price, Material priceType, String displayName) { + this.price = price; + this.priceType = priceType; + this.displayName = displayName; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Rank.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Rank.java new file mode 100644 index 0000000..275fbff --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/Rank.java @@ -0,0 +1,259 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.plugin.Plugin; + +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedDealType.InventoryBehaviour; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedDealType.LoseAction; + +public class Rank implements Listener { + private RankTier defaultTier; + private LoseAction onLose; + private InventoryBehaviour inventory; + private Map nameToTierMap; + private ArrayList tiers; + private Hashtable currentTier = new Hashtable<>(); + + public void resetPlayerTiers() { + for (UUID key : new HashSet<>(currentTier.keySet())) { + if (defaultTier == null) currentTier.remove(key); + else currentTier.put(key, defaultTier); + } + } + + public boolean hasDefaultTier() { + return defaultTier != null; + } + public RankTier getDefaultTier() { + return defaultTier; + } + public LoseAction getOnLoseAction() { + return onLose; + } + public InventoryBehaviour getInventoryBehaviour() { + return inventory; + } + + public Collection getTiers() { + return nameToTierMap.values(); + } + public Set getTierNames() { + return nameToTierMap.keySet(); + } + public RankTier getTier(String name) { + return nameToTierMap.get(name); + } + + public boolean containsItem(ItemStack item) { + if (item == null) return false; + return tiers.stream() + .flatMap(v -> v.getItems() + .stream() + .filter(_v -> _v instanceof RankTierItemApplier) + .map(_v -> (RankTierItemApplier)_v) + .map(i -> i.getItem()) + ) + .anyMatch(v -> v.getType().equals(item.getType())); + } + + public boolean playerHasOrAboveTier(OfflinePlayer player, RankTier tier) { + return tiers.indexOf(tier) <= tiers.indexOf(getPlayerTier(player)); + } + public RankTier getPlayerTier(OfflinePlayer player) { + return currentTier.get(player.getUniqueId()); + } + public RankTier getNextTier(OfflinePlayer player) { + int i = tiers.indexOf(getPlayerTier(player)) + 1; + if (i >= tiers.size()) i--; + return tiers.get(i); + } + + public void increasePlayerTier(OfflinePlayer player, RankTier target) { + int i = tiers.indexOf(getPlayerTier(player)); + int targetI = tiers.indexOf(target); + + if (targetI <= i) return; + + if (player.isOnline()) { + Player p = player.getPlayer(); + ItemStack[] inv = p.getInventory().getContents(); + + i++; + for (; i <= targetI; i++) { + tiers.get(i).apply(inv, p, this); + } + + p.getInventory().setContents(inv); + } + + currentTier.put(player.getUniqueId(), target); + } + + public void clear(ItemStack[] inv) { + for (int i = 0; i < inv.length; i++) { + if (inv[i] != null && containsItem(inv[i])) { + inv[i] = null; + } + } + } + + public void onDeath(Player p) { + RankTier tier = getPlayerTier(p); + + if (tier != null) { + currentTier.put(p.getUniqueId(), onLose.getTier(tier)); + } + refreshInv(p); + } + @EventHandler + private void onRespawn(PlayerRespawnEvent e) { + if (Game.instance.isPlaying(e.getPlayer())) { + } + } + @EventHandler + private void onJoin(PlayerJoinEvent e) { + if (Game.inGame(e.getPlayer())) { + if (defaultTier != null) increasePlayerTier(e.getPlayer(), defaultTier); + refreshInv(e.getPlayer()); + } + } + + @EventHandler + private void onDrop(PlayerDropItemEvent e) { + if (containsItem(e.getItemDrop().getItemStack())) { + if (inventory != InventoryBehaviour.FREE) e.setCancelled(true); + } + } + @EventHandler + private void onInventory(InventoryClickEvent e) { + if (Game.isStarted() && Game.instance.isPlaying((Player)e.getWhoClicked())) { + if (containsItem(e.getCurrentItem()) || containsItem(e.getCursor())) { + switch (inventory) { + case STUCK: + e.setCancelled(true); + return; + case NOENDER: + if ((e.getClickedInventory() instanceof PlayerInventory)) { + if (e.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) e.setCancelled(true); + } + else e.setCancelled(true); + + case NODROP: + switch (e.getAction()) { + case DROP_ALL_CURSOR: + case DROP_ALL_SLOT: + case DROP_ONE_CURSOR: + case DROP_ONE_SLOT: + e.setCancelled(true); + default: + break; + } + return; + case FREE: + return; + } + } + } + } + + public void refreshInv(Player p) { + ItemStack[] inv = p.getInventory().getContents(); + + clear(inv); + + RankTier tier = getPlayerTier(p); + + if (tier != null) { + int max = tiers.indexOf(tier); + + for (int i = 0; i <= max; i++) { + tiers.get(i).apply(inv, p, this); + } + } + + p.getInventory().setContents(inv); + p.updateInventory(); + } + + + @SuppressWarnings("unchecked") + public static Rank deserialize(Plugin pl, Map map) { + List tiers = ((Map)map.get("tiers")) + .entrySet() + .stream() + .map(v -> RankTier.deserialize(v.getKey(), (Map)v.getValue())) + .collect(Collectors.toList()); + + RankTier defaultTier = map.containsKey("default") ? tiers + .stream() + .filter(v -> v.getName().equals(map.get("default"))) + .findFirst() + .orElseThrow() : null; + InventoryBehaviour inventory = InventoryBehaviour.valueOf(((String)map.get("inventory")).toUpperCase()); + + return new Rank(pl, tiers, inventory, defaultTier, (String)map.get("onLose")); + } + + public Rank(Plugin pl, Collection tiers, InventoryBehaviour inventory, RankTier defaultTier, String loseAction) { + this.tiers = new ArrayList<>(tiers); + this.nameToTierMap = this.tiers.stream().collect(Collectors.toMap(v -> v.getName(), v -> v)); + this.inventory = inventory; + this.defaultTier = defaultTier; + + switch (loseAction) { + case "keep": + onLose = currTier -> currTier; + break; + case "lower": + onLose = currTier -> { + int i = this.tiers.indexOf(currTier) - 1; + if (i < 0) i = 0; + Bukkit.getServer().broadcastMessage(Integer.toString(i)); + + return this.tiers.get(i); + }; + break; + case "lose": + onLose = currTier -> null; + break; + default: + if (loseAction.startsWith("tier_")) { + String tierName = loseAction.substring(5); + RankTier tier = nameToTierMap.get(tierName); + onLose = currTier -> tier; + } + else throw new RuntimeException(String.format("The lose action %s was not recognised.", loseAction)); + break; + } + + if (defaultTier != null) { + for (Player p : Bukkit.getServer().getOnlinePlayers()) { + increasePlayerTier(p, defaultTier); + } + } + + Bukkit.getPluginManager().registerEvents(this, pl); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTier.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTier.java new file mode 100644 index 0000000..01f4e69 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTier.java @@ -0,0 +1,55 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.Utility; + +public class RankTier { + private String name; + private ItemStack icon; + private Collection items; + + public String getName() { + return name; + } + public String getDisplayName() { + return Utility.getItemName(icon); + } + public ItemStack getIcon() { + return icon; + } + public Collection getItems() { + return items; + } + + public void apply(ItemStack[] inv, Player p, Rank rank) { + for (RankTierItemApplier item : items) { + item.apply(p, inv, rank); + } + } + + @SuppressWarnings("unchecked") + public static RankTier deserialize(String name, Map map) { + Collection items = ((Collection>)map.get("items")) + .stream() + .map(v -> RankTierItemApplier.deserialize(v)) + .collect(Collectors.toList()); + + ItemStack icon = null; + if (map.containsKey("icon")) icon = Utility.deserializeItemStack((Map)map.get("icon")); + else icon = items.stream().findFirst().orElseThrow().getIcon(); + + return new RankTier(name, icon, items); + } + + public RankTier(String name, ItemStack icon, Collection items) { + this.name = name; + this.icon = icon; + this.items = items; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierApplier.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierApplier.java new file mode 100644 index 0000000..9d3bf73 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierApplier.java @@ -0,0 +1,24 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Map; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public interface RankTierApplier { + ItemStack getIcon(); + void apply(Player p, ItemStack[] inv, Rank rank); + + public static RankTierApplier deserialize(Map map) { + if (!map.containsKey("type")) throw new RuntimeException("A type property was expected for a rank tier item."); + + switch (map.get("type").toString()) { + case "item": + return RankTierItemApplier.deserialize(map); + case "upgrade": + return null; + default: + throw new RuntimeException("Unrecoginsed rank tier item type '" + map.get("type") + "'."); + } + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierItemApplier.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierItemApplier.java new file mode 100644 index 0000000..057a162 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankTierItemApplier.java @@ -0,0 +1,72 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Map; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.InventoryUtility; +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.Team; +import me.topchetoeu.bedwars.engine.trader.dealTypes.RankedDealType.ApplyAction; + +public class RankTierItemApplier implements RankTierApplier { + private ItemStack item; + private ApplyAction apply; + + public ItemStack getIcon() { + return item; + } + public ItemStack getItem() { + return item; + } + public ApplyAction getApplyAction() { + return apply; + } + public void apply(Player p, ItemStack[] items, Rank rank) { + ItemStack item = this.item.clone(); + if (Game.isStarted()) { + Team team = Game.instance.getTeam(p); + if (team != null) team.teamifyItem(item, true, true); + } + ItemStack remaining = null; + switch (apply) { + case GIVE: + remaining = InventoryUtility.giveItem(items, item); + break; + case REPLACEPREV: + rank.clear(items); + remaining = InventoryUtility.giveItem(items, item); + break; + case SLOT_HELMET: + p.getInventory().setHelmet(item); + break; + case SLOT_CHESTPLATE: + p.getInventory().setChestplate(item); + break; + case SLOT_LEGGINGS: + p.getInventory().setLeggings(item); + break; + case SLOT_BOOTS: + p.getInventory().setBoots(item); + break; + } + + if (remaining != null) p.getWorld().dropItemNaturally(p.getLocation(), remaining); + } + + @SuppressWarnings("unchecked") + public static RankTierItemApplier deserialize(Map map) { + ItemStack item = Utility.deserializeItemStack((Map)map.get("item")); + ApplyAction apply = ApplyAction.REPLACEPREV; + if (map.containsKey("apply")) apply = ApplyAction.valueOf(((String)map.get("apply")).toUpperCase()); + + return new RankTierItemApplier(item, apply); + } + + public RankTierItemApplier(ItemStack item, ApplyAction apply) { + this.item = item; + this.apply = apply; + } +} \ No newline at end of file diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDeal.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDeal.java new file mode 100644 index 0000000..01f03cd --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDeal.java @@ -0,0 +1,59 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.trader.Deal; + +public class RankedDeal implements Deal { + private Rank soldRank; + private RankTier soldTier; + + private Material priceType; + private int price; + + public Rank getRank() { + return soldRank; + } + public RankTier getTier() { + return soldTier; + } + + @Override + public ItemStack getDealItem(Player p) { + ItemStack icon = soldTier.getIcon(); + if (Game.isStarted()) Game.instance.teamifyItem(p, icon, true, true); + return icon; + } + @Override + public String getDealName(Player p) { + return Utility.getItemName(soldTier.getIcon()); + } + @Override + public Material getPriceType(Player p) { + return priceType; + } + @Override + public int getPrice(Player p) { + return price; + } + @Override + public boolean alreadyBought(Player p) { + return soldRank.playerHasOrAboveTier(p, soldTier); + } + @Override + public void commence(Player p) { + p.sendMessage(String.format("§rYou just purchased %s.", getDealName(p))); + soldRank.increasePlayerTier(p, soldTier); + } + + public RankedDeal(Rank rank, RankTier tier, Material priceType, int price) { + soldRank = rank; + soldTier = tier; + this.priceType = priceType; + this.price = price; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDealType.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDealType.java new file mode 100644 index 0000000..5424041 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedDealType.java @@ -0,0 +1,83 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Collections; +import java.util.Hashtable; +import java.util.Map; + +import org.bukkit.Material; +import org.bukkit.configuration.Configuration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.Deal; +import me.topchetoeu.bedwars.engine.trader.DealType; +import me.topchetoeu.bedwars.engine.trader.DealTypes; + +public class RankedDealType implements DealType { + private static Hashtable definedRanks = new Hashtable<>(); + + @Override + public Deal parse(Map map) { + Material priceType = Material.getMaterial(((String)map.get("priceType")).toUpperCase()); + int price = (Integer)map.get("price"); + Rank rank = definedRanks.get((String)map.get("rank")); + RankTier tier = rank.getTier((String)map.get("tier")); + + return new RankedDeal(rank, tier, priceType, price); + } + + @Override + public String getId() { return "tier"; } + + public interface LoseAction { + RankTier getTier(RankTier curr); + } + + public enum InventoryBehaviour { + FREE, + NODROP, + NOENDER, + STUCK, + } + + public enum ApplyAction { + GIVE, + REPLACEPREV, + SLOT_HELMET, + SLOT_CHESTPLATE, + SLOT_LEGGINGS, + SLOT_BOOTS, + } + + @SuppressWarnings("unchecked") + public static void init(Plugin pl, Configuration config) { + DealTypes.register(new RankedDealType()); + Map mapConf = Utility.mapifyConfig(config); + Map ranks = (Map)mapConf.get("ranks"); + + if (ranks != null) { + for (String key : ranks.keySet()) { + Map map = (Map)ranks.get(key); + + definedRanks.put(key, Rank.deserialize(pl, map)); + } + } + } + + public static void resetPlayerTiers() { + for (String key: definedRanks.keySet()) { + definedRanks.get(key).resetPlayerTiers(); + } + } + + public static void refreshPlayer(Player p) { + for (Rank rank : definedRanks.values()) { + rank.refreshInv(p); + } + } + + public static Map getDefinedRanks() { + return Collections.unmodifiableMap(definedRanks); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDeal.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDeal.java new file mode 100644 index 0000000..78ba61e --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDeal.java @@ -0,0 +1,88 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Hashtable; +import java.util.Map; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.Team; +import me.topchetoeu.bedwars.engine.trader.Deal; +import me.topchetoeu.bedwars.engine.trader.upgrades.TeamUpgrade; + +public class RankedUpgradeDeal implements Deal { + private TeamUpgradeRank rank; + private Hashtable prices = new Hashtable<>(); + + @Override + public ItemStack getDealItem(Player p) { + ItemStack _default = new ItemStack(Material.DIAMOND, 1); + if (!Game.isStarted()) return _default; + Team t = Game.instance.getTeam(p); + if (t == null) return _default; + + TeamUpgrade upgrade = rank.getNextTeamUpgrade(t); + ItemStack icon = rank.getIcon(upgrade); + if (icon == null) return _default; + else return icon; + } + + + @Override + public void commence(Player p) { + if (!Game.isStarted()) return; + Team t = Game.instance.getTeam(p); + if (t == null) return; + TeamUpgrade upgrade = rank.getNextTeamUpgrade(t); + if (upgrade == null) return; + upgrade.addToTeam(t); + upgrade.updateTeam(t); + t.sendMessage(p.getName() + "§r purchased " + upgrade.getDisplayName() + "§r!"); + } + + @Override + public String getDealName(Player p) { + if (!Game.isStarted()) return "None"; + Team t = Game.instance.getTeam(p); + if (t == null) return "None"; + + return rank.getNextTeamUpgrade(t).getDisplayName(); + } + + @Override + public Material getPriceType(Player p) { + if (!Game.isStarted()) return Material.DIAMOND; + Team t = Game.instance.getTeam(p); + if (t == null) return Material.DIAMOND; + + TeamUpgrade upgrade = rank.getNextTeamUpgrade(t); + Price price = prices.get(upgrade); + return price.getPriceType(); + } + + @Override + public int getPrice(Player p) { + if (!Game.isStarted()) return 128; + Team t = Game.instance.getTeam(p); + if (t == null) return 128; + + TeamUpgrade upgrade = rank.getNextTeamUpgrade(t); + Price price = prices.get(upgrade); + return price.getPrice(); + } + + @Override + public boolean alreadyBought(Player p) { + if (!Game.isStarted()) return false; + Team t = Game.instance.getTeam(p); + if (t == null) return false; + return rank.isTeamAlreadyHighest(t); + } + + public RankedUpgradeDeal(TeamUpgradeRank rank, Map prices) { + this.prices = new Hashtable<>(prices); + this.rank = rank; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDealType.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDealType.java new file mode 100644 index 0000000..3339a82 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/RankedUpgradeDealType.java @@ -0,0 +1,40 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Hashtable; +import java.util.Map; + +import me.topchetoeu.bedwars.engine.trader.Deal; +import me.topchetoeu.bedwars.engine.trader.DealType; +import me.topchetoeu.bedwars.engine.trader.DealTypes; +import me.topchetoeu.bedwars.engine.trader.upgrades.TeamUpgrade; + +public class RankedUpgradeDealType implements DealType { + + @Override + @SuppressWarnings("unchecked") + public Deal parse(Map map) { + Hashtable prices = new Hashtable<>(); + TeamUpgradeRank rank = TeamUpgradeRanks.get((String)map.get("rank")); + + Map pricesMap = (Map)map.get("prices"); + + for (String name : pricesMap.keySet()) { + TeamUpgrade tier = rank.get(name); + Price price = Price.deserialize((Map)pricesMap.get(name)); + + prices.put(tier, price); + } + + return new RankedUpgradeDeal(rank, prices); + } + + @Override + public String getId() { + return "upgrade"; + } + + public static void init() { + DealTypes.register(new RankedUpgradeDealType()); + } + +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRank.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRank.java new file mode 100644 index 0000000..9f9235f --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRank.java @@ -0,0 +1,85 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; + +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.Team; +import me.topchetoeu.bedwars.engine.trader.upgrades.TeamUpgrade; +import me.topchetoeu.bedwars.engine.trader.upgrades.TeamUpgrades; + +public class TeamUpgradeRank { + private ArrayList upgrades = new ArrayList<>(); + private ArrayList items = new ArrayList<>(); + private String name; + + public Collection getUpgrades() { + return Collections.unmodifiableCollection(upgrades); + } + public String getName() { + return name; + } + + public ItemStack getIcon(TeamUpgrade upgrade) { + int index = upgrades.indexOf(upgrade); + if (index < 0) return null; + else return items.get(index); + } + public TeamUpgrade getTeamUpgrade(Team t) { + for (int i = upgrades.size() - 1; i >= 0; i--) { + TeamUpgrade upgrade = upgrades.get(i); + + if (t.getUpgrades().contains(upgrade)) return upgrade; + } + + return null; + } + public TeamUpgrade getNextTeamUpgrade(Team t) { + if (upgrades.size() == 1) + return upgrades.get(0); + + for (int i = upgrades.size() - 2; i >= 0; i--) { + TeamUpgrade upgrade = upgrades.get(i); + + if (t.getUpgrades().contains(upgrade)) { + return upgrades.get(i + 1); + } + } + + return upgrades.get(0); + } + public boolean isTeamAlreadyHighest(Team t) { + return t.getUpgrades().contains(upgrades.get(upgrades.size() - 1)); + } + public TeamUpgrade get(String name) { + return upgrades + .stream() + .filter(v -> v.getName().equals(name)) + .findAny() + .orElse(null); + } + + @SuppressWarnings("unchecked") + public static TeamUpgradeRank deserialize(Plugin pl, Collection list) { + TeamUpgradeRank rank = new TeamUpgradeRank(); + for (Object obj : list) { + Map map = (Map)obj; + if (!map.containsKey("name")) throw new RuntimeException("Expected name property in upgrade rank definition."); + if (!map.containsKey("item")) throw new RuntimeException("Expected item property in upgrade rank definition."); + + String name = map.get("name").toString(); + TeamUpgrade upgrade = TeamUpgrades.get(name); + ItemStack item = Utility.deserializeItemStack((Map)map.get("item")); + + rank.items.add(item); + rank.upgrades.add(upgrade); + } + + return rank; + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRanks.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRanks.java new file mode 100644 index 0000000..de5181b --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/dealTypes/TeamUpgradeRanks.java @@ -0,0 +1,40 @@ +package me.topchetoeu.bedwars.engine.trader.dealTypes; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.configuration.Configuration; +import org.bukkit.plugin.Plugin; + +import me.topchetoeu.bedwars.Utility; +import me.topchetoeu.bedwars.engine.trader.DealTypes; + +public class TeamUpgradeRanks { + private static HashMap ranks = new HashMap<>(); + + public static Collection getAll() { + return Collections.unmodifiableCollection(ranks.values()); + } + public static TeamUpgradeRank get(String name) { + return ranks.get(name); + } + + @SuppressWarnings("unchecked") + public static void init(Plugin pl, Configuration config) { + DealTypes.register(new RankedDealType()); + Map mapConf = Utility.mapifyConfig(config); + Map> rawRanks = (Map>)mapConf.get("upgrades"); + + ranks.clear(); + + if (rawRanks != null) { + for (String key : rawRanks.keySet()) { + Collection map = (Collection)rawRanks.get(key); + + ranks.put(key, TeamUpgradeRank.deserialize(pl, map)); + } + } + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/BlindnessTeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/BlindnessTeamUpgrade.java new file mode 100644 index 0000000..02e306b --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/BlindnessTeamUpgrade.java @@ -0,0 +1,61 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import me.topchetoeu.bedwars.engine.BedwarsPlayer; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.Team; + +public class BlindnessTeamUpgrade implements TeamUpgrade { + + @Override + public void addToTeam(Team team) { + team.addUpgrade(this); + } + + @Override + public void updateTeam(Team team) { + } + + @Override + public void upgradeItem(ItemStack item) { + } + + @Override + public String getName() { + return "blindness"; + } + @Override + public String getDisplayName() { + return "Blindness"; + } + + public BlindnessTeamUpgrade(Plugin pl) { + Bukkit.getScheduler().runTaskTimer(pl, () -> { + if (!Game.isStarted()) return; + + for (BedwarsPlayer bwp : Game.instance.getPlayers()) { + if (!bwp.isOnline()) continue; + Player p = bwp.getOnlinePlayer(); + + for (Team t : Game.instance.getTeams()) { + if (!t.hasUpgrade(this)) continue; + if (t.hasPlayer(bwp)) continue; + if (p.getLocation().distance(t.getTeamColor().getBedLocation()) < 7.5) { + p.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 200, 1, true, false)); + t.removeUpgrade(getClass()); + } + } + } + }, 0, 20); + } + + public static void init(Plugin pl) { + TeamUpgrades.register(new BlindnessTeamUpgrade(pl)); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/EfficiencyTeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/EfficiencyTeamUpgrade.java new file mode 100644 index 0000000..295d866 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/EfficiencyTeamUpgrade.java @@ -0,0 +1,79 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.engine.Team; +import net.minecraft.server.v1_8_R3.ItemTool; + +public class EfficiencyTeamUpgrade implements TeamUpgrade { + private int level; + + @Override + public void addToTeam(Team team) { + team.removeUpgrade(getClass()); + team.addUpgrade(this); + updateTeam(team); + } + + @Override + public void updateTeam(Team team) { + team.getPlayers().forEach(ofp -> { + if (ofp.isOnline()) { + Player p = ofp.getOnlinePlayer(); + + ItemStack[] inv = p.getInventory().getContents(); + ItemStack[] armorInv = p.getInventory().getArmorContents(); + + for (ItemStack i : inv) { + upgradeItem(i); + } + for (ItemStack i : armorInv) { + upgradeItem(i); + } + + p.getInventory().setContents(inv); + p.getInventory().setArmorContents(armorInv); + p.updateInventory(); + } + }); + } + + @Override + public String getName() { + return "efficiency-" + level; + } + @Override + public String getDisplayName() { + return "Efficiency " + level; + } + + @Override + public void upgradeItem(ItemStack item) { + if (item == null) return; + net.minecraft.server.v1_8_R3.Item nmsItem = CraftItemStack.asNMSCopy(item).getItem(); + if (nmsItem instanceof ItemTool) { + item.addEnchantment(Enchantment.DIG_SPEED, level); + } + } + + public EfficiencyTeamUpgrade(int level) { + this.level = level; + } + + public static void init() { + TeamUpgrades.register(new EfficiencyTeamUpgrade(1)); + TeamUpgrades.register(new EfficiencyTeamUpgrade(2)); + TeamUpgrades.register(new EfficiencyTeamUpgrade(3)); + TeamUpgrades.register(new EfficiencyTeamUpgrade(4)); + TeamUpgrades.register(new EfficiencyTeamUpgrade(5)); + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return getName(); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/FatigueTeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/FatigueTeamUpgrade.java new file mode 100644 index 0000000..11793a4 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/FatigueTeamUpgrade.java @@ -0,0 +1,61 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import me.topchetoeu.bedwars.engine.BedwarsPlayer; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.Team; + +public class FatigueTeamUpgrade implements TeamUpgrade { + + @Override + public void addToTeam(Team team) { + team.addUpgrade(this); + } + + @Override + public void updateTeam(Team team) { + } + + @Override + public void upgradeItem(ItemStack item) { + } + + @Override + public String getName() { + return "fatigue"; + } + @Override + public String getDisplayName() { + return "Mining Fatigue"; + } + + public FatigueTeamUpgrade(Plugin pl) { + Bukkit.getScheduler().runTaskTimer(pl, () -> { + if (!Game.isStarted()) return; + + for (BedwarsPlayer bwp : Game.instance.getPlayers()) { + if (!bwp.isOnline()) continue; + Player p = bwp.getOnlinePlayer(); + + for (Team t : Game.instance.getTeams()) { + if (!t.hasUpgrade(this)) continue; + if (t.hasPlayer(bwp)) continue; + if (p.getLocation().distance(t.getTeamColor().getBedLocation()) < 7.5) { + p.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING, 200, 1, true, false)); + t.removeUpgrade(getClass()); + } + } + } + }, 0, 20); + } + + public static void init(Plugin pl) { + TeamUpgrades.register(new FatigueTeamUpgrade(pl)); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/HealTeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/HealTeamUpgrade.java new file mode 100644 index 0000000..01ba162 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/HealTeamUpgrade.java @@ -0,0 +1,59 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import me.topchetoeu.bedwars.engine.BedwarsPlayer; +import me.topchetoeu.bedwars.engine.Game; +import me.topchetoeu.bedwars.engine.Team; + +public class HealTeamUpgrade implements TeamUpgrade { + + @Override + public void addToTeam(Team team) { + team.addUpgrade(this); + } + + @Override + public void updateTeam(Team team) { + } + + @Override + public void upgradeItem(ItemStack item) { + } + + @Override + public String getName() { + return "heal"; + } + @Override + public String getDisplayName() { + return "Healing"; + } + + public HealTeamUpgrade(Plugin pl) { + Bukkit.getScheduler().runTaskTimer(pl, () -> { + if (!Game.isStarted()) return; + + for (Team t : Game.instance.getTeams()) { + if (!t.hasUpgrade(this)) continue; + for (BedwarsPlayer bwp : t.getPlayers()) { + if (bwp.isOnline()) { + Player p = bwp.getOnlinePlayer(); + + if (p.getLocation().distance(t.getTeamColor().getSpawnLocation()) < 20) + p.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 20, 1, true, false)); + } + } + } + }, 0, 20); + } + + public static void init(Plugin pl) { + TeamUpgrades.register(new HealTeamUpgrade(pl)); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/ProtectionTeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/ProtectionTeamUpgrade.java new file mode 100644 index 0000000..47bc85d --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/ProtectionTeamUpgrade.java @@ -0,0 +1,77 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.engine.Team; +import net.minecraft.server.v1_8_R3.ItemArmor; + +public class ProtectionTeamUpgrade implements TeamUpgrade { + private int level; + + @Override + public void addToTeam(Team team) { + team.removeUpgrade(getClass()); + team.addUpgrade(this); + updateTeam(team); + } + + @Override + public void updateTeam(Team team) { + team.getPlayers().forEach(ofp -> { + if (ofp.isOnline()) { + Player p = ofp.getOnlinePlayer(); + + ItemStack[] inv = p.getInventory().getContents(); + ItemStack[] armorInv = p.getInventory().getArmorContents(); + + for (ItemStack i : inv) { + upgradeItem(i); + } + for (ItemStack i : armorInv) { + upgradeItem(i); + } + + p.getInventory().setContents(inv); + p.getInventory().setArmorContents(armorInv); + p.updateInventory(); + } + }); + } + + @Override + public String getName() { + return "protection-" + level; + } + @Override + public String getDisplayName() { + return "Protection " + level; + } + + @Override + public void upgradeItem(ItemStack item) { + if (item == null) return; + if (CraftItemStack.asNMSCopy(item).getItem() instanceof ItemArmor) { + item.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, level); + } + } + + public ProtectionTeamUpgrade(int level) { + this.level = level; + } + + public static void init() { + TeamUpgrades.register(new ProtectionTeamUpgrade(1)); + TeamUpgrades.register(new ProtectionTeamUpgrade(2)); + TeamUpgrades.register(new ProtectionTeamUpgrade(3)); + TeamUpgrades.register(new ProtectionTeamUpgrade(4)); + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return getName(); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/SharpnessTeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/SharpnessTeamUpgrade.java new file mode 100644 index 0000000..8e30289 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/SharpnessTeamUpgrade.java @@ -0,0 +1,77 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.engine.Team; +import net.minecraft.server.v1_8_R3.ItemAxe; +import net.minecraft.server.v1_8_R3.ItemSword; + +public class SharpnessTeamUpgrade implements TeamUpgrade { + private int level; + + @Override + public void addToTeam(Team team) { + team.removeUpgrade(getClass()); + team.addUpgrade(this); + updateTeam(team); + } + + @Override + public void updateTeam(Team team) { + team.getPlayers().forEach(ofp -> { + if (ofp.isOnline()) { + Player p = ofp.getOnlinePlayer(); + + ItemStack[] inv = p.getInventory().getContents(); + ItemStack[] armorInv = p.getInventory().getArmorContents(); + + for (ItemStack i : inv) { + upgradeItem(i); + } + for (ItemStack i : armorInv) { + upgradeItem(i); + } + + p.getInventory().setContents(inv); + p.getInventory().setArmorContents(armorInv); + p.updateInventory(); + } + }); + } + + @Override + public String getName() { + return "sharpness-" + level; + } + @Override + public String getDisplayName() { + return "Sharpness " + level; + } + + @Override + public void upgradeItem(ItemStack item) { + if (item == null) return; + net.minecraft.server.v1_8_R3.Item nmsItem = CraftItemStack.asNMSCopy(item).getItem(); + if (nmsItem instanceof ItemSword || nmsItem instanceof ItemAxe) { + item.addEnchantment(Enchantment.DAMAGE_ALL, level); + } + } + + public SharpnessTeamUpgrade(int level) { + this.level = level; + } + + public static void init() { + TeamUpgrades.register(new SharpnessTeamUpgrade(1)); + TeamUpgrades.register(new SharpnessTeamUpgrade(2)); + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return getName(); + } +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrade.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrade.java new file mode 100644 index 0000000..599c711 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrade.java @@ -0,0 +1,13 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import org.bukkit.inventory.ItemStack; + +import me.topchetoeu.bedwars.engine.Team; + +public interface TeamUpgrade { + void addToTeam(Team team); + void updateTeam(Team team); + void upgradeItem(ItemStack item); + String getName(); + String getDisplayName(); +} diff --git a/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrades.java b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrades.java new file mode 100644 index 0000000..8d51a23 --- /dev/null +++ b/src/main/java/me/topchetoeu/bedwars/engine/trader/upgrades/TeamUpgrades.java @@ -0,0 +1,22 @@ +package me.topchetoeu.bedwars.engine.trader.upgrades; + +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; + +public class TeamUpgrades { + private static Hashtable upgrades = new Hashtable<>(); + + public static TeamUpgrade get(String name) { + return upgrades.get(name); + } + public static boolean register(TeamUpgrade upgrade) { + if (upgrades.containsKey(upgrade.getName())) return false; + + upgrades.put(upgrade.getName(), upgrade); + return true; + } + public static Collection getAll() { + return Collections.unmodifiableCollection(upgrades.values()); + } +}