package com.projectkorra.projectkorra.ability.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.event.PlayerBindChangeEvent; public class MultiAbilityManager { public static Map> playerAbilities = new ConcurrentHashMap<>(); public static Map playerSlot = new ConcurrentHashMap<>(); public static Map playerBoundAbility = new ConcurrentHashMap<>(); public static ArrayList multiAbilityList = new ArrayList(); public MultiAbilityManager() { final ArrayList waterArms = new ArrayList(); waterArms.add(new MultiAbilityInfoSub("Pull", Element.WATER)); waterArms.add(new MultiAbilityInfoSub("Punch", Element.WATER)); waterArms.add(new MultiAbilityInfoSub("Grapple", Element.WATER)); waterArms.add(new MultiAbilityInfoSub("Grab", Element.WATER)); waterArms.add(new MultiAbilityInfoSub("Freeze", Element.ICE)); waterArms.add(new MultiAbilityInfoSub("Spear", Element.ICE)); multiAbilityList.add(new MultiAbilityInfo("WaterArms", waterArms)); } /** * Sets up a player's binds for a MultiAbility. * * @param player Player having the multiability bound * @param multiAbility MultiAbility being bound */ public static void bindMultiAbility(final Player player, final String multiAbility) { final PlayerBindChangeEvent event = new PlayerBindChangeEvent(player, multiAbility, true); Bukkit.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; } if (playerAbilities.containsKey(player)) { unbindMultiAbility(player); } playerSlot.put(player, player.getInventory().getHeldItemSlot()); playerBoundAbility.put(player, multiAbility); final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); final HashMap currAbilities = new HashMap(); for (final int i : bPlayer.getAbilities().keySet()) { currAbilities.put(i, bPlayer.getAbilities().get(i)); } playerAbilities.put(player, currAbilities); final List modes = getMultiAbility(multiAbility).getAbilities(); bPlayer.getAbilities().clear(); for (int i = 0; i < modes.size(); i++) { if (!player.hasPermission("bending.ability." + multiAbility + "." + modes.get(i).getName())) { bPlayer.getAbilities().put(i + 1, new StringBuilder().append(modes.get(i).getAbilityColor()).append(ChatColor.STRIKETHROUGH).append(modes.get(i).getName()).toString()); } else { bPlayer.getAbilities().put(i + 1, modes.get(i).getAbilityColor() + modes.get(i).getName()); } } if (player.isOnline()) { bPlayer.addCooldown("MAM_Setup", 1L); // Support for bending scoreboards. player.getInventory().setHeldItemSlot(0); } } /** * Returns the MultiAbility the player has bound. Returns null if no * multiability is bound and active. * * @param player The player to use * @return name of multi ability bounded */ public static String getBoundMultiAbility(final Player player) { if (playerBoundAbility.containsKey(player)) { return playerBoundAbility.get(player); } return null; } /** * Returns a MultiAbility based on name. * * @param multiAbility Name of the multiability * @return the multiability object or null */ public static MultiAbilityInfo getMultiAbility(final String multiAbility) { for (final MultiAbilityInfo ma : multiAbilityList) { if (ma.getName().equalsIgnoreCase(multiAbility)) { return ma; } } return null; } /** * Returns a boolean based on whether a player has a MultiAbility active. * * @param player The player to check * @return true If player has a multiability active */ public static boolean hasMultiAbilityBound(final Player player) { if (playerAbilities.containsKey(player)) { return true; } return false; } /** * MultiAbility equivalent of * {@link GeneralMethods#getBoundAbility(Player)}. Returns a boolean based * on whether a player has a specific MultiAbility active. * * @param player The player to check * @param multiAbility The multiability name * @return true If player has the specified multiability active */ public static boolean hasMultiAbilityBound(final Player player, final String multiAbility) { final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); if (bPlayer == null) { return false; } return playerAbilities.containsKey(player) && playerBoundAbility.get(player).equals(multiAbility); } /** * Clears all MultiAbility data for a player. Called on player quit event. * * @param player */ public static void remove(final Player player) { playerAbilities.remove(player); playerBoundAbility.remove(player); playerSlot.remove(player); } /** * Cleans up all MultiAbilities. */ public static void removeAll() { playerAbilities.clear(); playerSlot.clear(); playerBoundAbility.clear(); } /** * Keeps track of the player's selected slot while a MultiAbility is active. */ public static boolean canChangeSlot(final Player player, int slot) { if (playerAbilities.isEmpty()) { return true; } final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); if (bPlayer != null) { if (bPlayer.getBoundAbility() == null && multiAbilityList.contains(getMultiAbility(playerBoundAbility.getOrDefault(player, "")))) { return slot < getMultiAbility(playerBoundAbility.get(player)).getAbilities().size(); } } return true; } /** * Reverts a player's binds to a previous state before use of a * MultiAbility. * * @param player */ public static void unbindMultiAbility(final Player player) { if (playerAbilities.containsKey(player)) { final HashMap prevBinds = playerAbilities.get(player); final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); if (bPlayer == null) { return; } int lastNonNull = -1; for (int i = 1; i < 10; i++) { if (prevBinds.get(i) != null) { lastNonNull = i; } bPlayer.getAbilities().put(i, prevBinds.get(i)); } if (lastNonNull > -1) { GeneralMethods.saveAbility(bPlayer, lastNonNull, prevBinds.get(lastNonNull)); } if (player.isOnline()) { bPlayer.addCooldown("MAM_Setup", 1L); // Support for bending scoreboards. } playerAbilities.remove(player); } if (playerSlot.containsKey(player)) { if (player.isOnline()) { player.getInventory().setHeldItemSlot(playerSlot.get(player)); } playerSlot.remove(player); } else { if (player.isOnline()) { player.getInventory().setHeldItemSlot(0); } } if (playerBoundAbility.containsKey(player)) { playerBoundAbility.remove(player); } } /** * MultiAbility class. Manages each MultiAbility's sub abilities. * */ public static class MultiAbilityInfo { private String name; private ArrayList abilities; public MultiAbilityInfo(final String name, final ArrayList abilities) { this.name = name; this.abilities = abilities; } public ArrayList getAbilities() { return this.abilities; } public String getName() { return this.name; } public void setAbilities(final ArrayList abilities) { this.abilities = abilities; } public void setName(final String name) { this.name = name; } } public static class MultiAbilityInfoSub { private String name; private Element element; public MultiAbilityInfoSub(final String name, final Element element) { this.name = name; this.element = element; } public Element getElement() { return this.element; } public String getName() { return this.name; } public void setElement(final Element element) { this.element = element; } public void setName(final String name) { this.name = name; } public ChatColor getAbilityColor() { return this.element != null ? this.element.getColor() : null; } } }